OpenGL Implementing MultiPass

徘徊边缘 提交于 2020-01-21 14:22:10

问题


I am having trouble porting some code I have successfully implemented in Shadertoy to desktop OpenGL, the problem is that I need to create a FrameBufferObject FBO so that I can do offscreen computations that will be later passed on to the main glsl fragment shader, the thing is that this buffer needs to reference itself as a texture to get the previous values for it to be able to run a simulation.

I have successfully created the 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);

And managed to call it inside my Render Loop so that I can render to the FBO and later on pass those values to the Default Framebuffer:

// 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;

    }

But I am not able to render the buffer to itself as a texture, I understand that it outputs undefined behaviour and that I should be using a technique as Ping-Pong.

Can somebody point me in the right direction?


回答1:


But I am not able to render the buffer to itself as a texture, I understand that it outputs undefined behaviour and that I should be using a technique as Ping-Pong.

Can somebody point me in the right direction?

You have to create 2 framebuffer objects, as you did it with the one in your question: frameBufferOne and frameBufferTwo.
Each fo this 2 framebuffer objects has to have a texture object attached: textureColourBufferOne and textureColourBufferTwo.

In the main loop of your program you have to know if the number of the frame is even or odd.
If the number is even then you have to render to textureColourBufferOne and the input to the render pass is textureColourBufferTwo.
It the number is odd then you have to render to textureColourBufferTwo and the input to the render pass is textureColourBufferOne.
The result of the rendering is always stored int the texture which belongs to the framebuffer of the current frame:

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;

    .....
}


来源:https://stackoverflow.com/questions/52749733/opengl-implementing-multipass

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!