如何将对象的整数ID正确地渲染到整数纹理缓冲区中?
假设我有一个内部格式为GL_LUMINANCE16的texture2D,并将其作为颜色附件附加到我的FBO上。
在渲染对象时,我将一个整数ID传递给着色器,并希望将此ID渲染到我的整数纹理中。
然而,fragmentshader输出的类型是vec4。 我该如何正确地将我的ID转换为四个组件的浮点数,并避免转换不准确,以便最终整数纹理目标中的整数值对应于我想要渲染的整数ID?
// First, create a frame buffer:
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
// Then generate your texture and define an unsigned int array:
glGenTextures(1, &textureid);
glBindTexture(GL_TEXTURE_2D, textureid);
glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, w, h, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
// Attach it to the frame buffer object:
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, textureid, 0);
// Before rendering
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
GLuint buffers[2] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 }; // this assumes that there is another texture that is for the render buffer. Color attachment1 is preserved for the element ids.
glDrawBuffers(2, buffers);
// Clear and render here
glFlush(); // Flush after just in case
glBindFramebuffer(GL_FRAMEBUFFER, 0);
对于GLSL方面,片段着色器应该具有以下(4.3核心配置代码):
layout(location = 0) out vec4 colorOut; // The first element in 'buffers' so location 0
layout(location = 1) out uvec4 elementID; // The second element in 'buffers' so location 1. unsigned int vector as color
// ...
void main()
{
//...
elementID = uvec4( elementid, 0, 0, 0 ); // Write the element id as integer to the red channel.
}
您可以在主机端读取这些值:
unsigned int* ids = new unsigned int[ w*h ];
glBindTexture(GL_TEXTURE_2D, textureid);
glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, ids);
你的问题存在几个问题。
首先,GL_LUMINANCE16
不是一个“整数纹理”。它是一个包含归一化无符号整数值的纹理。它使用整数来表示范围为 [0, 1] 的浮点数。如果你想存储实际的整数,你必须使用实际的 整数图像格式。
其次,你不能将光度纹理渲染出来;它们不是可渲染颜色格式。如果你真的想要渲染到单通道纹理中,你必须创建一个单通道图像格式。所以你需要使用 GL_R16UI
,它是一个 16 位单通道无符号整数图像格式,而不是 GL_LUMINANCE16
。
现在你已经正确设置了这个,它就变得非常简单了。定义一个 uint
片段着色器输出,并让你的片段着色器将你的 uint
值写入其中。这个 uint
可以来自于顶点着色器或者一个 uniform,无论你想如何做都可以。
显然,您还需要将纹理或渲染缓冲区附加到FBO上,但我相信您已经知道了。
最后一件事情:除非您指的是其中之一,否则不要使用“纹理缓冲区”这个短语,否则会让人感到困惑。
out vec4 out_colors[5]
。 - Mat