PDA

View Full Version : framebuffer rendering and reading rendered texture in loop, with shader



formjk
11-09-2013, 06:30 PM
I have 2 framebuffers, each with one color_attachment and depth_stencil_buffer attachment(both textures) to implement ping-pong kind of rendering. (the answer was altogether deleted from my previous question, where someone suggested this ping-pong technique.. ).

The problem is all the even though, all the layers are rendered in correct order, they are not rendered at correct coordinates. All of them should be rendered at same coordinates as while rendering i am attaching same vertex array object. Instead when previously rendered texture is read-back and rendered with new layers(for blending effect), the previously rendered texture's vertices are shifted downwards, and the new layer is rendered at its correct location.

The fragment shader has 3 textures input, 1--> from previously rendered framebuffer texture (blend of all three textures) and 2 ,3 -> new textures

and the output is blending of these three textures. here is how my fragment shader looks like.


#version 330 core
// Interpolated values from the vertex shaders
in vec2 UV;
// Ouput data
out vec4 color;

// Values that stay constant for the whole mesh.
uniform sampler2D texBackGround;
uniform sampler2D texForeGround;
uniform sampler2D texShadow;

void main(){
vec4 backGround = texture2D(texBackGround, UV);
vec4 foreGround = texture2D(texForeGround, UV);
vec4 shadow = texture2D(texShadow, UV);
vec4 color1 = mix(backGround, shadow, shadow.a);
color = mix(color1, foreGround, foreGround.a);

}

And the vertex shader is simply pass-through kind of a shader.

I am not too sure as where I am going wrong. Here is my code, abt generation of framebuffers and texture attachments.


glGenTextures(2, depthStencilTexture);
glGenFramebuffers(2, frameBuffer);
glGenTextures(2, texColorBuffer);

for(int i=0; i<2; i++)
{
// Create frame buffer
glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer[i]);

// Create texture to hold color buffer
glBindTexture(GL_TEXTURE_2D, texColorBuffer[i]);
lTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, 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, texColorBuffer[i], 0);

// Depth texture.
glBindTexture(GL_TEXTURE_2D, depthStencilTexture[i]);
glTexImage2D(GL_TEXTURE_2D, 0,GL_DEPTH24_STENCIL8, width, height, 0,GL_DEPTH_STENCIL, GL_FLOAT, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH24_STENCIL8, GL_TEXTURE_2D, depthStencilTexture[i], 0);


// Set the list of draw buffers.
GLenum DrawBuffers[1] = {GL_COLOR_ATTACHMENT0};
glDrawBuffers(1, DrawBuffers); // "1" is the size of DrawBuffers

}

Here is how the framebuffers are switched between read/write and rendered.


glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texColorBuffer[read]); // from previously rendered framebuffer
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, shadowTex); // new texture
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_2D, foreGroundTex); // new texture
cout<<" read , write :" << read << " " << write <<endl;

// Bind our framebuffer and draw scene
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, frameBuffer[write]);
static const GLenum buffer1[] = {GL_COLOR_ATTACHMENT0};
glDrawBuffers(1, buffer1);

glBindVertexArray(vaoID);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(0);

glActiveTexture(GL_TEXTURE0); //do drawing

glEnable(GL_DEPTH_TEST);
// Use our shader
glUseProgram(programID);

// Enable blending
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

// Clear the screen
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

// backGround --> from previoudly rendered famebuffer
glUniform1i(backGroundTexID, 1);
//// Draw the triangles
glDrawArrays(GL_TRIANGLES, 0, 2*3); // 2*3 indices starting at 0 -> 2 triangles

// shadow -- > new texture
glUniform1i(shadowTexID, 2);
// Draw the triangles
glDrawArrays(GL_TRIANGLES, 0, 2*3); // 2*3 indices starting at 0 -> 2 triangles

// foreGround
glUniform1i(foreGroundTexID, 3);
// Draw the triangles
glDrawArrays(GL_TRIANGLES, 0, 2*3); // 2*3 indices starting at 0 -> 2 triangles

glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);

glBindVertexArray(0);

glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);

After each rendering pass, i just switch read and write buffers.

Here is how the vertex array object and vertex buffer object are created (in case, i am making mistake here itself..)


const GLfloat vertices[] = {
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f, //top-left
1.0f, 1.0f, 0.0f, 1.0f, 1.0f, //top-right
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f, // bottom-left

1.0f, -1.0f, 0.0f, 1.0f, 0.0f, //bottom-right
1.0f, 1.0f, 0.0f, 1.0f, 1.0f, //top-right
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f, // bottom-left

};
glGenBuffers(1, &vboID);

glGenVertexArrays(1, &vaoID);
glBindVertexArray(vaoID);
{
glBindBuffer(GL_ARRAY_BUFFER, vboID);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), 0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (GLvoid*) (3*sizeof(GLfloat)));

glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);

}



Just to add, if the framebuffer is rendered for just one pass, all the three layers are blended correctly and i get correct output. Its just when i read the previously rendered framebuffer and try to re-render it with two other textures, the problem comes up.

I would really appreciate any pointers as to why the coordinates could be changing for previously rendered layer as I am stuck to this since last 10 days.

Thanks in advance.