写入 GL_R8 纹理

Writing to a GL_R8 texture

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

纹理初始化:

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

片段着色器:

#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 是安全的。此外,应该注意的是,我已经去除了几何着色器的所有复杂性以尝试找到问题的根源。当我期待一个完全红色的屏幕时,代码产生了一个完全黑色的屏幕。

我认为问题在于您绑定输出缓冲区的方式。临界线在这里:

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() 时,它谈到:

The binding of a user-defined varying out variable to a fragment color number [..]

在下一页(重点是我加的):

When a program is linked, any varying out variables without a binding specified either through BindFragDataLocationIndexed or BindFragDataLocation, or explicitly set within the shader text will automatically be bound to fragment colors and indices by the GL.

现在,这些 "color numbers" 与您指定的绘图缓冲区的索引匹配。来自同一文档第210页glDrawBuffer()的描述:

defines the set of color buffers to which fragment color zero is written.

所以你的电话:

glDrawBuffer(GL_COLOR_ATTACHMENT0 + RayBuffer_TextureType_SHADOW);

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

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

layout (location = 0) out float out_shadow;

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