glsl fragmenthader渲染objectID

时间:2012-05-12 10:56:55

标签: opengl glsl

如何将对象的整数ID正确呈现为整数纹理缓冲区?

假设我有一个内部格式为GL_LUMINANCE16的texture2D,并将其作为颜色附件附加到我的FBO。

渲染对象时,我将整数ID传递给着色器,并希望将此id渲染为整数纹理。

然而,

fragmenthader输出的类型为vec4。 如何正确地将我的ID转换为四个组件浮点数并避免转换不准确,以便最终整数纹理目标中的整数值对应于我想渲染的整数ID?

3 个答案:

答案 0 :(得分:5)

我仍然认为这里没有明确的答案。所以这就是我如何使它通过2D纹理工作:

// 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);

答案 1 :(得分:4)

您的问题存在一些问题。

首先,GL_LUMINANCE16 是“整数纹理”。它是一个包含规范化无符号整数值的纹理。它使用整数来表示范围[0,1]上的浮点数。如果要存储实际整数,则必须使用实际的integer image format

其次,你不能渲染到亮度纹理;它们不是颜色可渲染的格式。如果您确实要渲染到单通道纹理,则必须创建单通道图像格式。因此,使用GL_LUMINANCE16而不是GL_R16UI,这是一种16位单通道无符号整数图像格式。

现在你已经正确设置了它,这非常简单。定义uint片段着色器输出,让片段着色器将uint值写入其中。这个uint可以来自顶点着色器或来自制服;但是你想要这样做。

显然你还需要将你的纹理或渲染缓冲附加到FBO,但我很确定你知道这一点。

最后一件事:除非你的意思是one of these,否则不要使用短语“纹理缓冲区”。否则,它会让人感到困惑。

答案 2 :(得分:0)

我认为你的整数ID是一组基元的标识符;实际上它可以定义为着色器制服:

uniform int vertedObjectId;

渲染后,您希望将片段处理存储到integer texture中。请注意,整数纹理应使用整数采样器(isampler2D)进行采样,该采样器返回整数向量(即ivec3)。

此纹理可以附加到帧缓冲对象(请注意framebuffer completeness)。帧缓冲附件可以是bound到整数输出变量:

out int fragmentObjectId;

void main() {
    fragmentObjectId = vertedObjectId;
}

您需要一些扩展支持,或高级OpenGL版本(3.2?)。