如何正確渲染對象的整數ID到整數紋理緩衝區?glsl fragmentshader渲染對象ID
說我有一個內部格式GL_LUMINANCE16一個Texture2D,我重視其作爲附色到我的FBO。
當渲染的對象,我傳遞一個整數ID着色器,並想使這個ID到我的整數質感。
然而片段輸出是vec4類型的輸出。 如何正確地將我的ID轉換爲四個分量float,並避免轉換不準確,以至於最終整數紋理目標中的整數值對應於我想渲染的整數ID?
如何正確渲染對象的整數ID到整數紋理緩衝區?glsl fragmentshader渲染對象ID
說我有一個內部格式GL_LUMINANCE16一個Texture2D,我重視其作爲附色到我的FBO。
當渲染的對象,我傳遞一個整數ID着色器,並想使這個ID到我的整數質感。
然而片段輸出是vec4類型的輸出。 如何正確地將我的ID轉換爲四個分量float,並避免轉換不準確,以至於最終整數紋理目標中的整數值對應於我想渲染的整數ID?
你的問題有幾個問題。
首先,GL_LUMINANCE16
是而不是「整數紋理」。它是一個包含標準化的無符號整數值的紋理。它使用整數來表示範圍[0,1]上的浮點數。如果你想存儲實際的整數,你必須使用一個實際的integer image format。
其次,你不能渲染到亮度紋理;它們不是可呈現顏色的格式。如果您實際想要渲染到單通道紋理,則必須創建單通道圖像格式。因此,代替GL_LUMINANCE16
,您使用的是GL_R16UI
,它是一種16位單通道無符號整數圖像格式。
現在你有這樣的設置正確,這是非常容易的。定義uint
片段着色器輸出並讓片段着色器將uint
值寫入它。這uint
可能來自頂點着色器或來自制服;但是你想要做到這一點。
很明顯,你還需要你的紋理或渲染附加到FBO,但我相當肯定知道。
的最後一件事:不要使用短語「紋理緩衝器」,除非你是one of these。否則,它會變得混亂。
我想你的整數ID是一組原語的標識符;事實上,它可以被定義爲一個統一的着色器:
uniform int vertedObjectId;
一旦你渲染,你要分片處理存儲到integer texture。注意,整數紋理應採樣爲整數採樣器(isampler2D
),其返回整數向量(即ivec3
)。
該紋理可連接到一個幀緩衝區對象(注意framebuffer completeness)。幀緩衝器連接可以bound整數輸出變量:
out int fragmentObjectId;
void main() {
fragmentObjectId = vertedObjectId;
}
你需要幾個擴展支持,或高級的OpenGL版本(3.2?)。
我還是不認爲這裏有明確的答案。因此,這裏是我如何做它通過一個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);
我認爲接受的答案有點含糊。無數小時後,這實際上節省了我的一天!謝謝你,先生 –
聽起來不錯 - 儘管我得到了它與GL_LUMINANCE16工作已經除以我的...由於某種原因,我可以呈現到它 - 也許它只是支持它我的顯卡?如果我使用整型紋理格式,那麼如何才能爲一個渲染目標定義int輸出?我在着色器中使用了5個顏色附件,前4個渲染其他東西int浮點紋理,第5個渲染objectId。它現在可以工作(使用GL_LUMINANCE16),但也許我只是使用未定義的行爲?我有一個OpenGL 4.2上下文 – Mat
@Mat:你必須聲明輸出爲'int'來寫入'int'輸出。另外,考慮到這一點,我猜你有一張NVIDIA顯卡。 –
是的,我有一張nvidia卡。但我怎麼能聲明一個單一的輸出組件作爲int?我有我的碎片生成器的out變量聲明爲'out vec4 out_colors [5]' – Mat