问题
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