简体   繁体   English

glsl fragmenthader渲染objectID

[英]glsl fragmentshader render objectID

How do I properly render an integer ID of an object to an integer texture buffer? 如何将对象的整数ID正确呈现为整数纹理缓冲区?

Say I have a texture2D with internal format GL_LUMINANCE16 and i attach it as color attachment to my FBO. 假设我有一个带有内部格式GL_LUMINANCE16的texture2D,我将它作为颜色附件附加到我的FBO。

When rendering an object, i pass an integer ID to the shader and would like to render this id into my integer texture. 渲染对象时,我将整数ID传递给着色器,并希望将此id渲染为整数纹理。

fragmentshader output is of type vec4 however. 片段着色器输出的类型为vec4。 How do I properly transform my ID to four component float and avoid conversion inaccuracies such that in the end the integervalue in my integer texture target corresponds to the integer ID i wanted to render? 如何正确地将我的ID转换为四个组件浮点数并避免转换不准确,以便最终整数纹理目标中的整数值对应于我想要渲染的整数ID?

I still don't think that there is a clear answer here. 我仍然认为这里没有明确的答案。 So here is how I made it work through a 2D texture: 所以这就是我通过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);

On the GLSL side the fragment shader should have (4.3 core profile code here): 在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.

}

You can read the values on the host side: 您可以在主机端读取值:

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

There are several problems with your question. 你的问题有几个问题。

First, GL_LUMINANCE16 is not an "integer texture." 首先, GL_LUMINANCE16 不是 “整数纹理”。 It is a texture that contains normalized unsigned integer values. 它是一个包含规范化无符号整数值的纹理。 It uses integers to represent floats on the range [0, 1]. 它使用整数来表示范围[0,1]上的浮点数。 If you want to store actual integers, you must use an actual integer image format . 如果要存储实际整数,则必须使用实际的整数图像格式

Second, you cannot render to a luminance texture; 其次,你无法渲染到亮度纹理; they are not color-renderable formats. 它们不是颜色可渲染的格式。 If you actually want to render to a single-channel texture, you must create a single-channel image format. 如果您确实要渲染到单通道纹理,则必须创建单通道图像格式。 So instead of GL_LUMINANCE16 , you use GL_R16UI , which is a 16-bit single-channel unsigned integral image format. 因此,而不是GL_LUMINANCE16 ,您使用GL_R16UI ,这是一个16位单通道无符号整数图像格式。

Now that you have this set up correctly, it's pretty trivial. 现在你已经正确设置了它,这非常简单。 Define a uint fragment shader output and have your fragment shader write your uint value to it. 定义uint片段着色器输出并让片段着色器将uint值写入其中。 This uint could come from the vertex shader or from a uniform; 这个uint可能来自顶点着色器或来自制服; however you want to do it. 但是你想要这样做。

Obviously you'll also need to attach your texture or renderbuffer to an FBO, but I'm fairly sure you know that. 显然你还需要将你的纹理或渲染缓冲器附加到FBO,但我很确定你知道这一点。

One final thing: don't use the phrase "texture buffer" unless you mean one of these . 最后一件事:不要使用短语“纹理缓冲区”,除非你的意思是其中之一 Otherwise, it gets confusing. 否则,它会让人感到困惑。

I suppose that your integer ID is an identifier for a set of primitives; 我想你的整数ID是一组基元的标识符; indeed it can be defined as an shader uniform: 实际上它可以定义为着色器制服:

uniform int vertedObjectId;

Once you render, you want to store the fragment processing into an integer texture . 渲染后,您希望将片段处理存储为整数纹理 Note that integer textures shall be sampled with integer samplers ( isampler2D ), which returns integer vectors (ie ivec3 ). 请注意,整数纹理应使用整数采样器( isampler2D )进行采样, 整数采样器返回整数向量(即ivec3 )。

This texture can be attached to a framebuffer object (be aware of framebuffer completeness ). 此纹理可以附加到帧缓冲对象(请注意帧缓冲完整性 )。 The framebuffer attachment can be bound to an integer output variable: 帧缓冲附件可以绑定到整数输出变量:

out int fragmentObjectId;

void main() {
    fragmentObjectId = vertedObjectId;
}

You need a few extension supports, or an advanced OpenGL version (3.2?). 您需要一些扩展支持,或高级OpenGL版本(3.2?)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM