I want to load two textures in my FBO, one texture contains a HDR image, and my first target is to "copy" the image from first texture to second (which is empty), and called 'DownSamplingTex'.
So I create FBO, load the texture I want to write in COLOR_ATTACHMENT_0, and bind it; then init my shader program and render a quad, with texture I want to read bound in GL_TEXTURE_0.
Then I unbind the FBO and bind 'DownSamplingTex', and draw a quad.
I don't know if the process is correct, the output I have is a black screen.
Here's the render code:
glBindFramebuffer(GL_FRAMEBUFFER, fboA);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
FBOtex->bind(); // Set read texture bound in GL_TEXTURE_0
glDrawBuffer(GL_COLOR_ATTACHMENT0); // draw to write texture (DownSamplingTex)
fboShad->bind(); // use program of FBO shader
fboShad->setUniformValue4f("MVP", glm::value_ptr(MVP)); // Shader attribute
drawQuad(); // Draw
fboShad->unbind();
FBOtex->unbind();
// Main FB rendering
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
fboShad->bind();
fboShad->setUniformValue4f("MVP", glm::value_ptr(MVP));
DownSamplingTex->bind();
drawQuad();
DownSamplingTex->unbind();
fboShad->unbind();
Vertex shader:
#version 420
in vec4 vUV;
in vec4 vVertex;
smooth out vec2 vTexCoord;
uniform mat4 MVP;
void main()
{
vTexCoord = vUV;
gl_Position = MVP*vVertex;
}
Fragment shader:
#version 420
smooth in vec2 vTexCoord;
layout(location = 0) out vec4 color;
layout(binding=0) uniform sampler2D texHDR;
void main(void)
{
color = texture(texHDR,vTexCoord);
}
Inside 'drawQuad()' I set vVertex value with glGetAttribLocation() and glVertexAttribPointer().
std::vector<GLfloat> quadVerts = {
-1, -1, 0, 0, 1,
-1, 1, 0, 0, 0,
1, 1, 0, 1, 0,
-1, -1, 0, 0, 1,
1, 1, 0, 2, 0,
1, -1, 0, 1, 1 };
GLuint quadVbo;
glGenBuffers(1, &quadVbo);
glBindBuffer(GL_ARRAY_BUFFER, quadVbo);
glBufferData(GL_ARRAY_BUFFER, 6*3*4, &quadVerts[0], GL_STATIC_DRAW);
GLuint vVertex = fboShad->getLocation("vVertex");
GLuint vUV = fboShad->getLocation("vUV");
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 3 * sizeof(GLfloat), NULL);
glEnableVertexAttribArray(vVertex);
glVertexAttribPointer(vVertex, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 3, 0);
glEnableVertexAttribArray(vUV);
glVertexAttribPointer(vUV, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, (void*)(3 * sizeof(GLfloat)));
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glDisableVertexAttribArray(vVertex);
glDisableVertexAttribArray(vUV);
I don't know if the mistake is in the process, or maybe is not correct the use of attributes in fragment shader ( I suppose that 'layout(binding=1)', if you use shader with FBO bound, tooks GL_COLOR_ATTACHMENT_1 texture); or the use of 'vTexCoords' as the .xy values of vertex.
I think you are confusing sampler bindings with fragment data output locations. While the two things can both be assigned using a
layout (...)
qualifier, they are very different.layout (location = X) out vec3 color
assigns the outputcolor
toGL_COLOR_ATTACHMENT0 + X
layout (binding = Y) sampler2D texHDR
tells GLSL to use texture image unitGL_TEXTURE0 + Y
Your fragment shader only writes to a single output, so there is no actual reason to have multiple color attachments in this situation. You attach images to FBOs in order to write to them from a fragment shader, not to read from them as a texture. In fact, it is undefined behavior to read from a texture at the same time as it is attached to an FBO for writing without using special extensions (e.g.
GL_NV_texture_barrier
).What you actually want to do in this situation is the following:
Modified Fragment Shader:
Now, the texture you want to read should be bound to
GL_TEXTURE0
(this is the default unless you manually callglActiveTexture (...)
somehwere) and the texture you want to output to should be attached to your Framebuffer Object atGL_COLOR_ATTACHMENT0
.The most important thing to keep in mind here is that the
binding
andlocation
qualifiers are completely separate: Color Attachment 0 does not correspond to Texture Image Unit 0.