2
votes

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.

1
Why do you have two color attachments if your fragment shader only writes to a single output? Since there are no calls to glBindFragDataLocation (...) I am going to assume only the attachment GL_COLOR_ATTACHMENT0 is written to in this situation. In fact, your fragment shader as written right now should not even compile because color is undefined.Andon M. Coleman
Yes, sorry, it was my fault to comment that line, fixed that mistake.MikeFadeCrew
My idea is to load two textures into fragment shader, but only write into downsamplingtex, using the other texture, which contains the image and is attached to GL_COLOR_ATTACHMENT_1MikeFadeCrew

1 Answers

1
votes

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 output color to GL_COLOR_ATTACHMENT0 + X

layout (binding = Y) sampler2D texHDR tells GLSL to use texture image unit GL_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:

#version 420
smooth in vec2 vTexCoord;
//out vec4 vFragColor;

layout(location=0) out     vec3      color;  // Fragment Data Output Location
layout(binding=0)  uniform sampler2D texHDR; // Texture Image Unit Binding

void main(void)
{
//vFragColor = texture(textureMap, vTexCoord);
//color = vec4(1.0,0.5,0.5,0.5);
   color = texture(texHDR,vTexCoord);
}

Now, the texture you want to read should be bound to GL_TEXTURE0 (this is the default unless you manually call glActiveTexture (...) somehwere) and the texture you want to output to should be attached to your Framebuffer Object at GL_COLOR_ATTACHMENT0.

The most important thing to keep in mind here is that the binding and location qualifiers are completely separate: Color Attachment 0 does not correspond to Texture Image Unit 0.