使用 FBO 和着色器 OpenGL 渲染到纹理



我想在我的FBO中加载两个纹理,一个纹理包含HDR图像,我的第一个目标是将图像从第一个纹理"复制"到第二个纹理(这是空的(,并称为">DownSamplingTex"。

所以我创建了FBO,加载我想用COLOR_ATTACHMENT_0写的纹理,并绑定它;然后初始化我的着色器程序并渲染一个四边形,我想在GL_TEXTURE_0中绑定要读取的纹理。

然后我解绑FBO并绑定">DownSamplingTex",并绘制一个四边形。

我不知道过程是否正确,我的输出是黑屏。

下面是渲染代码:

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();

顶点着色器:

#version 420
in vec4 vUV;
in vec4 vVertex;
smooth out vec2 vTexCoord;
uniform mat4 MVP;
void main()
{
   vTexCoord = vUV;
   gl_Position = MVP*vVertex;
}

片段着色器:

#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);
}

在 'drawQuad((' 中,我使用 glGetAttribLocation(( 和 glVertexAttribPointer(( 设置 vVertex 值。

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);

我不知道错误是否在这个过程中,或者可能是在片段着色器中使用属性不正确(我想">layout(binding=1(",如果你使用带有 FBO 绑定的着色器,需要GL_COLOR_ATTACHMENT_1纹理(; 或使用"vTexCoords"作为顶点的 .xy 值。

我认为您将采样器绑定与片段数据输出位置混淆了。虽然这两件事都可以使用 layout (...) 限定符进行分配,但它们非常不同。

layout (location = X) out vec3 color将输出color分配给GL_COLOR_ATTACHMENT0 + X

layout (binding = Y) sampler2D texHDR告诉 GLSL 使用纹理图像单元GL_TEXTURE0 + Y

片段着色器仅写入单个输出,因此在这种情况下没有实际理由具有多个颜色附件。将图像附加到 FBO 是为了从片段着色器写入它们,而不是从它们作为纹理读取。事实上,在附加到 FBO 进行写入的同时读取纹理是不定义的行为,而无需使用特殊扩展名(例如 GL_NV_texture_barrier (。


在这种情况下,您实际想要执行的操作如下:

修改后的片段着色器:

#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);
}

现在,您要读取的纹理应绑定到GL_TEXTURE0(这是默认设置,除非您手动调用glActiveTexture (...)(,并且要输出到的纹理应附加到GL_COLOR_ATTACHMENT0帧缓冲对象。

这里要记住的最重要的一点是,bindinglocation限定符是完全分开的:颜色附件 0 不对应于纹理图像单元 0。

最新更新