写入GL_R8纹理

时间:2016-02-13 17:06:12

标签: c opengl graphics shader render-to-texture

在从附加到同一FBO(GL_RGB32F)的另一个纹理读取时,写入附加到FBO的纹理(GL_R8格式)时遇到一些问题。我相信问题在于我的片段着色器中的输出类型。

纹理初始化:

    glGenFramebuffers(1, &rBuffer->fbo);
    glBindFramebuffer(GL_FRAMEBUFFER, rBuffer->fbo);


    glGenTextures(RayBuffer_TextureType_NUMTEXTURES, rBuffer->textures);
    ...
    glBindTexture(GL_TEXTURE_2D, rBuffer->textures[RayBuffer_TextureType_SHADOW]);
    glTexImage2D
    (
            GL_TEXTURE_2D,  
            0,         
            GL_R8,        
            textureWidth,
            textureHeight,
            0,
            GL_RED,
            GL_UNSIGNED_BYTE,
            NULL
    );

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

    glFramebufferTexture2D
    (
            GL_FRAMEBUFFER,                                
            GL_COLOR_ATTACHMENT0 + RayBuffer_TextureType_SHADOW,
            GL_TEXTURE_2D,
            rBuffer->textures[RayBuffer_TextureType_SHADOW],
            0
    );

结合:

    glBindFramebuffer(GL_FRAMEBUFFER, rBuffer->fbo);

    glDrawBuffer(GL_COLOR_ATTACHMENT0 + RayBuffer_TextureType_SHADOW);

    glActiveTexture(GL_TEXTURE0 + RayBuffer_TextureType_POSITION);
    glBindTexture(GL_TEXTURE_2D, rBuffer->textures[RayBuffer_TextureType_POSITION]);

几何着色器:

#version 330
layout(triangles) in; 
layout (triangle_strip, max_vertices=4) out;
uniform sampler2D positionTexture;
uniform vec3 lightDirection;
uniform vec3 rightDirection;
uniform vec3 upDirection;
uniform vec2 screenSize;
void main()
{



    gl_Position = vec4(1.0f, 1.0f, 0.0f, 1.0f);
    EmitVertex();

    gl_Position = vec4(-1.0f, 1.0f, 0.0f, 1.0f);
    EmitVertex();

    gl_Position = vec4(1.0f, -1.0f, 0.0f, 1.0f);
    EmitVertex();

    gl_Position = vec4(-1.0f, -1.0f, 0.0f, 1.0f);
    EmitVertex();

    EndPrimitive();
}

Fragment Shader:

#version 330
layout (location = 3) out float out_shadow;
void main()
{
    out_shadow = 1.0f;
}

将纹理模糊到屏幕:

    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
    glBindFramebuffer(GL_READ_FRAMEBUFFER, members->rBuffer->fbo);
    glReadBuffer(GL_COLOR_ATTACHMENT0 + RayBuffer_TextureType_SHADOW);
    glBlitFramebuffer
    (
            0, 0, eBuffer->windowWidth, eBuffer->windowHeight,
            0, 0, eBuffer->windowWidth, eBuffer->windowHeight,
            GL_COLOR_BUFFER_BIT, GL_LINEAR
    );

可以安全地假设RayBuffer_TextureType_SHADOW是3.此外,应该注意我已经删除了几何着色器的所有复杂性以尝试找到问题的根源。该代码产生一个完全黑屏,而我期待一个完全红色的屏幕。

1 个答案:

答案 0 :(得分:3)

我认为问题在于绑定输出缓冲区的方式。关键路线在这里:

layout (location = 3) out float out_shadow;

您似乎假设需要值3来匹配您渲染的FBO的颜色附件的索引:

glFramebufferTexture2D
(
    GL_FRAMEBUFFER,                                
    GL_COLOR_ATTACHMENT0 + RayBuffer_TextureType_SHADOW,

RayBuffer_TextureType_SHADOW的值为3。

这不是片段着色器输出与FBO附件的关联如何工作。您使用layout(location=...)限定符指定的值在规范的大多数部分中称为颜色编号。例如,在OpenGL 3.3规范的第190页上,在描述glBindFragDataLocationIndexed()时,它讨论了:

  

用户定义的变量输出与片段颜色编号[..]

的绑定

在下一页(我强调):

  

当一个程序被链接时,没有通过BindFragDataLocationIndexed或BindFragDataLocation,或在着色器文本中明确设置指定的绑定的任何变化变量将自动绑定到片段颜色和GL的指数。

现在,这些“颜色编号”与您指定的绘图缓冲区的索引相匹配。来自同一文档第210页的glDrawBuffer()的说明:

  

定义写入颜色零片段的颜色缓冲区集。

通过电话:

glDrawBuffer(GL_COLOR_ATTACHMENT0 + RayBuffer_TextureType_SHADOW);

指定片段着色器生成的颜色 0 写入FBO的附件 3

这一切意味着您需要为片段着色器的输出指定颜色编号 0

layout (location = 0) out float out_shadow;

大于0的颜色数仅在从片段着色器生成多个输出时才有用。在这种情况下,location值指定传递给输出所写的glDrawBuffers()的列表中的颜色缓冲区的索引。