GL_TEXTURE_2D作为渲染输入

时间:2016-08-29 19:48:55

标签: c++ opengl

我在GL_TEXTURE_2D中有一张图片。从这里开始,我需要将此纹理移动到framebuffer对象上。有人可以请一个使用填充了数据并将其放在FBO上的2d纹理的示例吗?我不是要渲染纹理,而是从纹理渲染。

1 个答案:

答案 0 :(得分:1)

这是一个简单的FBO演示。

您可以在github上找到整个代码here(代码基于来自OpenGL SuperBible的this示例程序)。

该程序执行以下操作

  1. 将绿色背景上的红色方块绘制成FBO。 FBO的后备存储是2D纹理。

  2. 在蓝色屏幕上绘制正方形,但将纹理从步骤1映射到正方形。这会将整个场景从上一步映射到正方形。

  3. Screen shot

    所以使用帧缓冲时的理论,

    1. (初始化)将纹理附加到屏幕外的帧缓冲区。
    2. 然后有2个程序(或2个程序)

      1. 在程序1中,渲染到帧缓冲区(渲染到纹理中)

      2. 在程序2中,现在渲染到窗口(屏幕)并使用第一个程序中的纹理作为输入。

      3. 因此第一个程序的输出是第二个程序的输入。

        这意味着两个阶段的顶点着色器将是相同的。由于没有遮罩(旋转)和没有光照效果,所有顶点着色器都将输入传递给输出(即坐标)。

        但每个阶段的片段着色器都会略有不同。

        第一个片段着色器为每个像素输出一个恒定的颜色。在源代码中,第一个片段着色器的输出配置为FBO,FBO使用纹理来存储颜色数据。

        第一个片段着色器中生成的纹理在第二个片段着色器中用作输入。在第二个片段着色器中,颜色由纹理(第一个片段着色器的输出)确定。

        所以这是顶点着色器。请注意,顶点着色器的输入是坐标(vp)和纹理坐标。 2程序的片段着色器需要texcoords来知道纹理的映射位置。在顶点着色器中,texcoord简单地从输入传递到输出。

        #version 130
        in vec3 vp;
        in vec2 texcoord;
        
        out vec2 outtexcoord;
        
        void main () {
            gl_Position = vec4 (vp, 1.0);
            outtexcoord = texcoord; 
        }
        

        这是第一个程序的片段着色器。每个像素都画成红色。

        #version 130
        
        in vec2 outtexcoord;
        
        out vec4 frag_colour;
        void main () {
          frag_colour = vec4 (1.0, 0.0, 0.0, 0.0); //everything red
        }
        

        第二个程序片段着色器。注意sampler2D是输入纹理(由第一个程序生成)。 outtexcoord也是顶点着色器的纹理坐标。输出颜色(frag_color)由纹理决定。

        #version 130
        uniform sampler2D tex;
        
        in vec2 outtexcoord;
        
        out vec4 frag_color;
        
        void main () {
            frag_color = texture(tex, outtexcoord);
        }
        

        这是C程序(我用g ++编译,请参阅github链接中的makefile)。

        #include <GL/glew.h>
        #include <GLFW/glfw3.h>
        
        #include "shader_utils.h" //see github link for details
        
        void Initialize();
        void InitGL();
        void InitProgramFBO();
        void InitProgramScreen();
        void InitBuffer();
        void InitFBO();
        void Loop();
        void RenderToFBO();
        void RenderToScreen();
        void Shutdown();
        void OnWindowResize(GLFWwindow* window, int width, int height);
        
        GLFWwindow* window;
        int screenWidth = 640;
        int screenHeight = 480;
        GLuint render2FBOProgram;
        GLuint render2ScreenProgram;
        GLuint vao;
        GLuint vbo;
        GLuint fbo;
        GLuint color_texture;
        
        int main() {
           Initialize();
           Loop();
           Shutdown();
           return 0;
        }
        
        void Initialize() {
            InitGL();
            InitProgramScreen();
            InitProgramFBO();
            InitBuffer();
            InitFBO();
        }
        
        void InitGL() {
            glfwInit();
            window = glfwCreateWindow(screenWidth, screenHeight, "FBO Demo", NULL, NULL);
        
            glfwMakeContextCurrent(window);
            glewInit();
        
            glClearColor(0.0f, 0.0f, 0.1f, 1.0f);
        }
        
        void InitProgramFBO() {
          GLuint vs;
          GLuint fs;
          render2FBOProgram = create_program("vs.glsl", "fbo.fs.glsl", vs, fs);
          glDeleteShader(vs);
          glDeleteShader(fs);
        }
        
        void InitProgramScreen() {
          GLuint vs;
          GLuint fs;
          render2ScreenProgram = create_program("vs.glsl", "screen.fs.glsl", vs, fs);
          glDeleteShader(vs);
          glDeleteShader(fs);
        }
        
        void InitBuffer() {
          //define the square made up of 2 triangles
          static const GLfloat points[] = {
          //x     y      z       texcoord u and v
          -0.5f,  0.5f,  0.0f,   0.0f, 0.0f,
           0.5f,  0.5f,  0.0f,   1.0f, 0.0f,
           0.5f, -0.5f,  0.0f,   1.0f, 1.0f,
        
           0.5f, -0.5f,  0.0f,   1.0f, 1.0f,
          -0.5f, -0.5f,  0.0f,   0.0f, 1.0f,
          -0.5f,  0.5f,  0.0f,   0.0f, 0.0f
          };
        
          glGenVertexArrays(1, &vao);
          glBindVertexArray(vao);
        
          //create buffer for points
          glGenBuffers(1, &vbo);
          glBindBuffer(GL_ARRAY_BUFFER, vbo);
          glBufferData(GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW);
        
          //tell opengl how to find the coordinate data
          glVertexAttribPointer (0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (GLubyte*)NULL);
          glEnableVertexAttribArray(0);
        
          //tell opengl how to find the texcoord data
          glVertexAttribPointer (1, 2, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (GLvoid *)(3 * sizeof(GLfloat)));
          glEnableVertexAttribArray(1);
        }
        
        void InitFBO() {
        
          //create a framebuffer
          glGenFramebuffers(1, &fbo);
          glBindFramebuffer(GL_FRAMEBUFFER, fbo);
        
          //create a texture as the backing store for the framebuffer
          glGenTextures(1, &color_texture);
          glBindTexture(GL_TEXTURE_2D, color_texture);
          glTexStorage2D(GL_TEXTURE_2D, 9, GL_RGBA8, 512, 512); //1 = mipmap     levels
        
          //mip map filtering
          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        
          //attach the texture as the color attachment of the framebuffer
          glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,     GL_TEXTURE_2D, color_texture, 0);
        
          //tell opengl to draw into the color attachment
          static const GLenum draw_buffers[] = { GL_COLOR_ATTACHMENT0 };
          glDrawBuffers(1, draw_buffers);
        }
        
        void Loop() {
        
          //glBindVertexArray(vao);
          //glBindBuffer(GL_ARRAY_BUFFER, vbo);
        
          while (!glfwWindowShouldClose(window)) {
        
            RenderToFBO();
        
            RenderToScreen();
        
            glfwSwapBuffers(window);
        
            glfwPollEvents();
            if (GLFW_PRESS == glfwGetKey(window, GLFW_KEY_ESCAPE)) {
              glfwSetWindowShouldClose(window, 1);
            }
        
          }
        }
        
        void RenderToFBO() {
          static const GLfloat green[] = { 0.0f, 1.0f, 0.0f, 1.0f }; //texture background is green
        
          glBindFramebuffer(GL_FRAMEBUFFER, fbo);
          glViewport(0, 0, 512, 512); //set view port to texture size
          glClearBufferfv(GL_COLOR, 0, green);
          glUseProgram(render2FBOProgram);
          glDrawArrays(GL_TRIANGLES, 0, 6);
          glBindFramebuffer(GL_FRAMEBUFFER, 0);
        }
        
        void RenderToScreen() {
          static const GLfloat blue[] = { 0.0f, 0.0f, 1.0f, 1.0f }; //screen     background is blue
        
          glViewport(0, 0, screenWidth, screenHeight);
          glClearBufferfv(GL_COLOR, 0, blue);
          glBindTexture(GL_TEXTURE_2D, color_texture);
          glUseProgram(render2ScreenProgram);
          glDrawArrays(GL_TRIANGLES, 0, 6);
          glBindTexture(GL_TEXTURE_2D, 0);
        }
        
        void Shutdown() {
          glUseProgram(0);
          glBindBuffer(GL_ARRAY_BUFFER, 0);
          glDeleteProgram(render2FBOProgram);
          glDeleteProgram(render2ScreenProgram);
          glfwTerminate();
         }
        
        // a call-back function
        void OnWindowResize(GLFWwindow* window, int width, int height) {
          screenWidth = width;
          screenHeight = height;
          glViewport(0, 0, screenWidth, screenHeight);
        }