【问题标题】:OpenGL Implementing MultiPassOpenGL实现MultiPass
【发布时间】:2018-10-10 22:39:45
【问题描述】:

我在将我在Shadertoy 中成功实现的一些代码移植到桌面 OpenGL 时遇到问题,问题是我需要创建一个 FrameBufferObject FBO,以便我可以进行屏幕外计算,然后将其传递给主 glsl片段着色器,问题是这个缓冲区需要将自己作为纹理来引用,以获取之前的值,以便能够运行模拟。

我已成功创建 FBO:

// Framebuffer configuration.
unsigned int frameBufferOne;
glGenFramebuffers(1, &frameBufferOne);
glBindFramebuffer(GL_FRAMEBUFFER, frameBufferOne);

// Create a colour attachment texture.
unsigned int textureColourBufferOne;
glGenTextures(1, &textureColourBufferOne);
glBindTexture(GL_TEXTURE_2D, textureColourBufferOne);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, WIDTH, HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureColourBufferOne, 0);

if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
    std::cout << "ERROR::FRAMEBUFFER:: Framebuffer is not complete!" << std::endl;
glBindFramebuffer(GL_FRAMEBUFFER, 0);

并设法在我的渲染循环中调用它,以便我可以渲染到 FBO,然后将这些值传递给默认帧缓冲区:

// Render Loop.
while( !glfwWindowShouldClose( window ) )
{

    // Input.
    processInput( window );

    // Render.

    // Bind to frameBuffer and draw scene as normally would to colour texture.
    glBindFramebuffer( GL_FRAMEBUFFER, frameBufferOne );

    glClearColor( 0.2f, 0.3f, 0.1f, 1.0f );
    glClear( GL_COLOR_BUFFER_BIT );

    bufferShader.use();
    float currentFrame = glfwGetTime();
    //Set the iTimeDelta uniform.
    float deltaTime = currentFrame - lastFrame;
    lastFrame = currentFrame;
    bufferShader.setFloat( "iTimeDelta", deltaTime );
    // Set the iTime uniform.
    float timeValue = currentFrame;
    bufferShader.setFloat( "iTime", timeValue );
    // Set the iResolution uniform.
    bufferShader.setVec2( "iResolution", WIDTH, HEIGHT );
    // Input iMouse.
    double xPos, yPos;
    glfwGetCursorPos( window, &xPos, &yPos );
    yPos = HEIGHT - yPos;
    bufferShader.setVec2( "iMouse", xPos, yPos );

    glBindVertexArray( VAO );
    glBindTexture( GL_TEXTURE_2D, textureColourBufferOne );
    glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0 );
    glBindVertexArray( 0 );

    glBindFramebuffer( GL_FRAMEBUFFER, 0 );
    glDisable( GL_DEPTH_TEST );

    glClearColor( 1.0f, 1.0f, 1.0f, 1.0f );
    glClear( GL_COLOR_BUFFER_BIT );

    ourShader.use();
    ourShader.setVec2( "iResolution", WIDTH, HEIGHT );
    // Set the iTime uniform.
    ourShader.setFloat( "iTime", timeValue );
    glBindVertexArray(VAO);
    glBindTexture( GL_TEXTURE_2D, textureColourBufferOne );
    glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0 );

    glfwSwapBuffers( window );
    glfwPollEvents();

    frameCount++;
    finalTime = time( NULL );
    if( finalTime - initialTime > 0 )
    {

        std::cout << "FPS : " << frameCount / (finalTime - initialTime) << std::endl;
        frameCount = 0;
        initialTime = finalTime;

    }

但我无法将缓冲区作为纹理呈现给自身,我知道它会输出未定义的行为,我应该使用乒乓球技术。

有人能指出我正确的方向吗?

【问题讨论】:

    标签: c++ opengl glsl shader fragment-shader


    【解决方案1】:

    但我无法将缓冲区作为纹理呈现给自身,我知道它会输出未定义的行为,我应该使用乒乓球技术。

    有人能指出正确的方向吗?

    您必须创建 2 个帧缓冲区对象,就像您在问题中所做的那样:frameBufferOneframeBufferTwo
    这 2 个帧缓冲区对象中的每个对象都必须附加一个纹理对象:textureColourBufferOnetextureColourBufferTwo

    在程序的主循环中,您必须知道帧数是偶数还是奇数。
    如果数字是偶数,那么你必须渲染到textureColourBufferOne,渲染通道的输入是textureColourBufferTwo
    如果数字是奇数,那么您必须渲染到 textureColourBufferTwo,渲染通道的输入是 textureColourBufferOne
    渲染的结果总是存储在属于当前帧的帧缓冲区的纹理中:

    bool even = true;
    while( !glfwWindowShouldClose( window ) )
    {
        .....
    
        glBindFramebuffer( GL_FRAMEBUFFER, even ? frameBufferOne : frameBufferTwo );
    
        glClearColor( 0.2f, 0.3f, 0.1f, 1.0f );
        glClear( GL_COLOR_BUFFER_BIT );
    
        .....
    
        glBindVertexArray( VAO );
        glBindTexture( GL_TEXTURE_2D, even ? textureColourBufferTwo : textureColourBufferOne );
        glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0 );
        glBindVertexArray( 0 );
    
        .....
    
        glBindFramebuffer( GL_FRAMEBUFFER, 0 );
        glClearColor( 1.0f, 1.0f, 1.0f, 1.0f );
        glClear( GL_COLOR_BUFFER_BIT );
    
        .....
    
        glBindVertexArray(VAO);
        glBindTexture( GL_TEXTURE_2D, even ? textureColourBufferOne : textureColourBufferTwo );
        glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0 );
    
        glfwSwapBuffers( window );
        glfwPollEvents();
    
        even = !even;
    
        .....
    }
    

    【讨论】:

    • 就是这样!非常感谢@Rabbid76。
    • 它适用于一个简单的例子,比如在最后一帧上绘画,但是当我尝试运行波浪模拟时它不起作用。
    • 我认为这可能与纹理的大小有关,但它也不适用于 RGB32F! @Rabbid76
    • @FelipeGutierrez 哦,可能你的纹理需要一个 Alpha 通道 GL_RGBAGL_RGBA32F 而不是 GL_RGB
    • 问题上的 shadertoy 链接上的相同片段着色器不起作用(我已成功将它们移植到桌面上编译),但我没有得到以前的状态。它适用于一个简单的示例,在该示例中,我创建了一个圆,从同一个着色器中读取并将值添加到 fragColor。 @Rabbid76
    猜你喜欢
    • 2016-07-09
    • 1970-01-01
    • 2013-09-30
    • 2016-08-21
    • 2014-03-26
    • 1970-01-01
    • 1970-01-01
    • 2012-02-10
    • 2017-12-20
    相关资源
    最近更新 更多