/* * demoscene-eo, an ASCII art demoscene written as a gift for Emmanuel Otton retirement * Copyright (C) 2019 XXXXXX XXXXXXX * * This file is part of demoscene-eo. * * demoscene-eo is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * demoscene-eo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with demoscene-eo. If not, see */ #include "scene01.h" #include "utils.h" // Mostly inspired by CC0 https://gist.github.com/koute/7391344 typedef enum t_attrib_id { attrib_position, attrib_color } t_attrib_id; int scene01_init_gl(graphical_env_t *ge, scene01_env_t *se) { GLuint vs, fs, program, vbo, renderedTexture, depthrenderbuffer; GLint status; GLenum DrawBuffers[1] = {GL_COLOR_ATTACHMENT0}; TRACE("call"); vs = glCreateShader(GL_VERTEX_SHADER); status = gl_compile_shader_from_file(vs, "res/scene01_vs_basic.glsl"); if (status) return 40+status; fs = glCreateShader(GL_FRAGMENT_SHADER); status = gl_compile_shader_from_file(fs, "res/scene01_fs_colorfultest.glsl"); if (status) return 50+status; program = glCreateProgram(); glAttachShader(program, vs); glAttachShader(program, fs); glBindAttribLocation(program, attrib_position, "i_position"); glBindAttribLocation(program, attrib_color, "i_color"); glLinkProgram(program); glGetProgramiv(program, GL_LINK_STATUS, &status); glDetachShader(program, vs); glDetachShader(program, fs); glDeleteShader(vs); glDeleteShader(fs); if(status == GL_FALSE) { gl_trace_shader_or_program_log(program); return 60; } glUseProgram(program); // http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-14-render-to-texture/ // The framebuffer, which regroups 0, 1, or more textures, and 0 or 1 depth buffer. glGenFramebuffers(1, &ge->gl_fbo); // The texture we're going to render to glGenTextures(1, &renderedTexture); // "Bind" the newly created texture : all future texture functions will modify this texture glBindTexture(GL_TEXTURE_2D, renderedTexture); // Give an empty image to OpenGL ( the last "0" ) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, FBUF_W, FBUF_H, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); // Poor filtering. Needed ! glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); // The depth buffer glGenRenderbuffers(1, &depthrenderbuffer); glBindRenderbuffer(GL_RENDERBUFFER, depthrenderbuffer); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, FBUF_W, FBUF_H); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthrenderbuffer); // Set "renderedTexture" as our colour attachement #0 glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, renderedTexture, 0); // Set the list of draw buffers. glDrawBuffers(1, DrawBuffers); // "1" is the size of DrawBuffers // Always check that our framebuffer is ok if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { return 1; } glDisable(GL_DEPTH_TEST); //glClearColor(0.5, 0.0, 0.0, 0.0); glViewport(0, 0, FBUF_W, FBUF_H); glGenVertexArrays(1, &(se->vao)); glGenBuffers(1, &vbo); glBindVertexArray(se->vao); glBindBuffer(GL_ARRAY_BUFFER, vbo); glEnableVertexAttribArray(attrib_position); glEnableVertexAttribArray(attrib_color); glVertexAttribPointer(attrib_color, 4, GL_FLOAT, GL_FALSE, sizeof(float)*6, 0); glVertexAttribPointer(attrib_position, 2, GL_FLOAT, GL_FALSE, sizeof(float)*6, (void *)(4*sizeof(float))); const GLfloat g_vertex_buffer_data[] = { /* R, G, B, A, X, Y */ 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, FBUF_W, 0, 0, 0, 1, 1, FBUF_W, FBUF_H, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, FBUF_W, FBUF_H, 1, 1, 1, 1, 0, FBUF_H }; glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW); t_mat4x4 projection_matrix; gl_mat4x4_ortho(projection_matrix, 0.0f, (float)FBUF_W, (float)FBUF_H, 0.0f, 0.0f, 100.0f); glUniformMatrix4fv(glGetUniformLocation(program, "u_projection_matrix"), 1, GL_FALSE, projection_matrix); return 0; } int scene01_init_sdl(graphical_env_t *ge, scene01_env_t *se) { TRACE("call"); return 0; } int scene01_init_caca(graphical_env_t *ge, scene01_env_t *se) { TRACE("call"); return 0; } void scene01_free_gl(graphical_env_t *ge, scene01_env_t *se) { TRACE("call"); //TODO } void scene01_free_sdl(graphical_env_t *ge, scene01_env_t *se) { TRACE("call"); } void scene01_free_caca(graphical_env_t *ge, scene01_env_t *se) { TRACE("call"); } int scene01_next_gl(graphical_env_t *ge, scene01_env_t *se) { TRACE_CALL_ONCE; // Render to the in-VRAM Framebuffer Object glBindFramebuffer(GL_FRAMEBUFFER, ge->gl_fbo); glClear(GL_COLOR_BUFFER_BIT); glBindVertexArray(se->vao); glDrawArrays(GL_TRIANGLES, 0, 6); // [...] // Render to the screen glBindFramebuffer(GL_FRAMEBUFFER, 0); glClear(GL_COLOR_BUFFER_BIT); glBindVertexArray(se->vao); glDrawArrays(GL_TRIANGLES, 0, 6); SDL_GL_SwapWindow(ge->gl_win); // Download the rendered texture from videocard to main memory //SDL_RenderReadPixels(r, NULL, 0, ge->raw_target, FBUF_W*4); return 0; } int scene01_next_sdl(graphical_env_t *ge, scene01_env_t *se) { TRACE_CALL_ONCE; return 0; } int scene01_next_caca(graphical_env_t *ge, scene01_env_t *se) { // Shorthands caca_canvas_t *cv = ge->cv; int w = ge->w, h = ge->h; Uint32 frame = ge->sc_framecount; TRACE_CALL_ONCE; // "convert" the raw pixel stream from SDL to ASCII art on caca canevas caca_set_dither_gamma(ge->d, 1.0); caca_dither_bitmap(cv, 0, 0, w, h, ge->d, ge->raw_target); // Add things on top of caca canvas caca_set_color_ansi(cv, CACA_WHITE, CACA_BLACK); caca_put_str(cv, (w-17)/2, h/2, "This is a message"); if (frame >= 300) { return 1; } return 0; }