2012-05-12 129 views
6

如何正確渲染對象的整數ID到整數紋理緩衝區?glsl fragmentshader渲染對象ID

說我有一個內部格式GL_LUMINANCE16一個Texture2D,我重視其作爲附色到我的FBO。

當渲染的對象,我傳遞一個整數ID着色器,並想使這個ID到我的整數質感。

然而片段輸出是vec4類型的輸出。 如何正確地將我的ID轉換爲四個分量float,並避免轉換不準確,以至於最終整數紋理目標中的整數值對應於我想渲染的整數ID?

回答

4

你的問題有幾個問題。

首先,GL_LUMINANCE16而不是「整數紋理」。它是一個包含標準化的無符號整數值的紋理。它使用整數來表示範圍[0,1]上的浮點數。如果你想存儲實際的整數,你必須使用一個實際的integer image format

其次,你不能渲染到亮度紋理;它們不是可呈現顏色的格式。如果您實際想要渲染到單通道紋理,則必須創建單通道圖像格式。因此,代替GL_LUMINANCE16,您使用的是GL_R16UI,它是一種16位單通道無符號整數圖像格式。

現在你有這樣的設置正確,這是非常容易的。定義uint片段着色器輸出並讓片段着色器將uint值寫入它。這uint可能來自頂點着色器或來自制服;但是你想要做到這一點。

很明顯,你還需要你的紋理或渲染附加到FBO,但我相當肯定知道。

的最後一件事:不要使用短語「紋理緩衝器」,除非你是one of these。否則,它會變得混亂。

+0

聽起來不錯 - 儘管我得到了它與GL_LUMINANCE16工作已經除以我的...由於某種原因,我可以呈現到它 - 也許它只是支持它我的顯卡?如果我使用整型紋理格式,那麼如何才能爲一個渲染目標定義int輸出?我在着色器中使用了5個顏色附件,前4個渲染其他東西int浮點紋理,第5個渲染objectId。它現在可以工作(使用GL_LUMINANCE16),但也許我只是使用未定義的行爲?我有一個OpenGL 4.2上下文 – Mat

+0

@Mat:你必須聲明輸出爲'int'來寫入'int'輸出。另外,考慮到這一點,我猜你有一張NVIDIA顯卡。 –

+0

是的,我有一張nvidia卡。但我怎麼能聲明一個單一的輸出組件作爲int?我有我的碎片生成器的out變量聲明爲'out vec4 out_colors [5]' – Mat

0

我想你的整數ID是一組原語的標識符;事實上,它可以被定義爲一個統一的着色器:

uniform int vertedObjectId; 

一旦你渲染,你要分片處理存儲到integer texture。注意,整數紋理應採樣爲整數採樣器(isampler2D),其返回整數向量(即ivec3)。

該紋理可連接到一個幀緩衝區對象(注意framebuffer completeness)。幀緩衝器連接可以bound整數輸出變量:

out int fragmentObjectId; 

void main() { 
    fragmentObjectId = vertedObjectId; 
} 

你需要幾個擴展支持,或高級的OpenGL版本(3.2?)。

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

我認爲接受的答案有點含糊。無數小時後,這實際上節省了我的一天!謝謝你,先生 –