写入 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()
的列表中颜色缓冲区的索引,输出被写入。
我在写入附加到 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()
的列表中颜色缓冲区的索引,输出被写入。