C 写入GL_R8纹理

C 写入GL_R8纹理,c,opengl,graphics,shader,render-to-texture,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, rBuff

我在读取附加到同一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();
}
片段着色器:

#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\u TextureType\u SHADOW为3。此外,应该注意的是,我已经去除了几何体着色器的所有复杂性,试图找到问题的根源。代码产生了一个完全的黑屏,而我原本以为会出现一个完全的红屏。

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

layout (location = 3) out float out_shadow;
您似乎假设需要值3来匹配渲染到的FBO颜色附件的索引:

glFramebufferTexture2D
(
    GL_FRAMEBUFFER,                                
    GL_COLOR_ATTACHMENT0 + RayBuffer_TextureType_SHADOW,
对于
RayBuffer\u TextureType\u SHADOW
,值为3

这不是碎片着色器输出与FBO附件的关联方式。使用
布局(location=…)
限定符指定的值在规范的大多数部分称为颜色编号。例如,在OpenGL 3.3规范的第190页,在描述
glbindfragdatalocationindex()
时,它谈到:

将用户定义的可变输出变量绑定到片段颜色编号[…]

在下一页(我添加了重点):

链接程序时,通过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()
的列表中颜色缓冲区的索引,输出将写入该列表。

哦,天哪,我这方面真是误解。谢谢你澄清这一点。这很有道理。我将更新我的代码并返回结果。这非常有效,但更重要的是,我现在正确地理解了纹理渲染的工作原理。再次感谢你。我注意到问题的标题并不代表我在这里犯的根本错误。有没有人认为应该换成别的东西(会有什么建议)?