2

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.

MikeFadeCrew
  • 107
  • 2
  • 11
  • 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 Nov 30 '14 at 19:06
  • Yes, sorry, it was my fault to comment that line, fixed that mistake. – MikeFadeCrew Nov 30 '14 at 19:18
  • 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_1` – MikeFadeCrew Nov 30 '14 at 19:19

1 Answers1

1

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.

Community
  • 1
  • 1
Andon M. Coleman
  • 42,359
  • 2
  • 81
  • 106
  • Thank you for your help, that wasn't clear for me. I edit my fragment shader as you said, and put only the output texture in `GL_COLOR_ATTACHMENT0` of the FBO, and the texture I want to read in `GL_TEXTURE0`, but I still have black screen; maybe is `drawQuad()` the problem – MikeFadeCrew Dec 01 '14 at 20:15
  • I edited the code; I'm not sure how is the correct way to set vertex coords (the hidden lines of my vertex shader about `vUV`, I know that I have to set this parameter in the same way as `vVertex` in `drawQuad()`, but I don't know what parameters for texture are the correct ones. – MikeFadeCrew Dec 01 '14 at 20:24
  • @MikeFadeCrew: Well, according to the recent edit, you don't have your shader bound when you call `drawQuad (...)` the second time. I also do not see you setting up a vertex attribute pointer for the texture coordinates anywhere, so the texture coordinates will all have undefined values. – Andon M. Coleman Dec 01 '14 at 20:37
  • Okey, you are right; I modified that, and now I can see something (a little piece of the texture), that's a progress hahaha. I think that right now the only problem I have is vertex positions. Thank you very much! – MikeFadeCrew Dec 02 '14 at 10:08