2012-05-12 12 views
6

オブジェクトの整数IDを整数テクスチャバッファに正しくレンダリングするにはどうすればよいですか?glsl fragmentshader render objectID

私は内部フォーマットGL_LUMINANCE16のtexture2Dを持っており、FBOにカラーアタッチメントとしてアタッチしています。

オブジェクトをレンダリングするとき、私は整数IDをシェーダに渡し、このIDを整数テクスチャにレンダリングしたいと思います。

フラグメントハードウェア出力はvec4タイプですが、 私のIDを4つのコンポーネントフロートに正しく変換し、最終的に整数テクスチャターゲットの整数値がレンダリングする整数IDに対応するように、変換の不正確さを避けるにはどうすればよいですか?

答えて

4

質問にはいくつか問題があります。

まず、GL_LUMINANCE16は、ではありません。「整数テクスチャ」です。これは、正規化符号なし整数値を含むテクスチャです。 [0、1]の範囲の浮動小数点数を表すために整数を使用します。実際の整数を格納する場合は、実際にはinteger image formatを使用する必要があります。

第2に、輝度テクスチャにレンダリングできません。カラーレンダリング可能な形式ではありません。実際にシングルチャンネルテクスチャにレンダリングする場合は、シングルチャンネルのイメージフォーマットを作成する必要があります。そのため、GL_LUMINANCE16の代わりに、GL_R16UIを使用します。これは、16ビットのシングルチャネル符号なし整数形式です。

これで正しく設定できました。これはかなり簡単です。 uintフラグメントシェーダ出力を定義し、フラグメントシェーダにuintの値を書き込ませます。このuintは、頂点シェーダまたはユニフォームから来る可能性があります。しかし、あなたはそれをしたい。

もちろん、テクスチャやレンダバッファをFBOに接続する必要がありますが、私はかなり知っていると思います。

最終的なもの:one of theseを意味しない限り、「テクスチャバッファ」というフレーズを使用しないでください。それ以外の場合は、混乱します。

+0

私はGL_LUMINANCE16ですでに作業していますが、私はいくつかの理由でそれをレンダリングすることができます - 多分それをサポートするグラフィックスカードですか?整数テクスチャ形式を使用する場合、1つのレンダーターゲットに対してint出力を定義するにはどうすればよいですか?シェーダで5つのカラーアタッチメントを使用し、最初の4つはint浮動小数点テクスチャをレンダリングし、5番目はobjectIdをレンダリングします。それは今(GL_LUMINANCE16を使用して)動作しますが、多分私は未定義の振る舞いを使用していますか?私はOpenGL 4.2のコンテキストを持っています – Mat

+0

@Mat: 'int'出力に書き込むために出力を' int'に宣言する必要があります。また、これが動作することを考慮すると、私はあなたがNVIDIAカードを持っていると推測しています。 –

+0

はい、私はnvidiaカードを持っています。しかし、どのように私はintとして単一の出力コンポーネントを宣言できますか?私はあなたのアウトプットを持っています。あなたのアウトプットは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テクスチャを介して動作作った方法です:GLSL側で

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

フラグメントシェーダ(ここでは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

私は受け入れられた答えが少し曖昧だと思います。無数の時間の後、これは実際に私の日を救った!ありがとうございます –