From b6ab2f2c62e593edb50508e0b911a01fe773122f Mon Sep 17 00:00:00 2001 From: Ludovic Pouzenc Date: Sun, 15 Sep 2019 12:36:19 +0200 Subject: Unplug SDL_Renderer from OpenGL process. Use FrameBufferObject. --- src/demoscene-eo.c | 2 +- src/main.h | 3 ++- src/scene01.c | 60 +++++++++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 53 insertions(+), 12 deletions(-) diff --git a/src/demoscene-eo.c b/src/demoscene-eo.c index 94db4e5..ed6fe1b 100644 --- a/src/demoscene-eo.c +++ b/src/demoscene-eo.c @@ -367,7 +367,7 @@ int worker_gl() { SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); // Initialize OpenGL diff --git a/src/main.h b/src/main.h index bf622ed..a8e0722 100644 --- a/src/main.h +++ b/src/main.h @@ -36,7 +36,8 @@ typedef struct { // OpenGL worker SDL_Window* gl_win; SDL_GLContext gl_ctx; - SDL_Renderer *gl_rndr; + SDL_Renderer *gl_rndr; //XXX remove me + GLuint gl_fbo; SDL_Texture *gl_target; // framebuffer to inject OpenGL or SDL result in caca canvas uint32_t raw_target[FBUF_W*FBUF_H]; diff --git a/src/scene01.c b/src/scene01.c index 39083d0..a93aa3d 100644 --- a/src/scene01.c +++ b/src/scene01.c @@ -75,7 +75,9 @@ typedef enum t_attrib_id } t_attrib_id; int scene01_init_gl(graphical_env_t *ge, scene01_env_t *se) { - GLuint vs, fs, program; + GLuint vs, fs, program, vbo, renderedTexture, depthrenderbuffer; + GLint status; + GLenum DrawBuffers[1] = {GL_COLOR_ATTACHMENT0}; TRACE("call"); vs = glCreateShader(GL_VERTEX_SHADER); @@ -85,7 +87,6 @@ int scene01_init_gl(graphical_env_t *ge, scene01_env_t *se) { glShaderSource(vs, 1, (const GLchar **)&vertex_shader, &length); glCompileShader(vs); - GLint status; glGetShaderiv(vs, GL_COMPILE_STATUS, &status); if(status == GL_FALSE) return 40; @@ -106,12 +107,45 @@ int scene01_init_gl(graphical_env_t *ge, scene01_env_t *se) { 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); + //glClearColor(0.5, 0.0, 0.0, 0.0); glViewport(0, 0, FBUF_W, FBUF_H); - GLuint vbo; - glGenVertexArrays(1, &(se->vao)); glGenBuffers(1, &vbo); glBindVertexArray(se->vao); @@ -139,6 +173,8 @@ int scene01_init_gl(graphical_env_t *ge, scene01_env_t *se) { t_mat4x4 projection_matrix; 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; } @@ -166,21 +202,25 @@ void scene01_free_caca(graphical_env_t *ge, scene01_env_t *se) { } int scene01_next_gl(graphical_env_t *ge, scene01_env_t *se) { - SDL_Renderer *r = ge->gl_rndr; TRACE_CALL_ONCE; - // https://gist.github.com/Twinklebear/8265888 - // https://forums.libsdl.org/viewtopic.php?p=51634 + // 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); // [...] - //SDL_GL_SwapWindow(ge->gl_win); + // 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); + //SDL_RenderReadPixels(r, NULL, 0, ge->raw_target, FBUF_W*4); return 0; } -- cgit v1.2.3