Using Integer Textures in OpenGL for Calculation
OpenGL could perfectly support integer textures through 'GL_EXT_gpu_shader4' and '
GL_EXT_texture_integer' extension. So we can do some GPGPU work with integer values in shaders.
First of all, prepare the integer texture:
- glGenTextures (1, &imageTex);
- glBindTexture(GL_TEXTURE_2D,imageTex);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
- glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA32UI, 2,2,0,GL_RGBA_INTEGER,GL_UNSIGNED_INT,data);
Take a look at the last funciton above: glTexImage2D(); There are something important here:
1. Internal Format of this texture should be one of 'GL_RGBA32UI' 'GL_RGBA32I' or something like these;
2.Format should be 'GL_RGBA_INTEGER' or something like this. Be careful the '_INTEGER' suffix;
3.Type should be one of 'GL_UNSIGNED_INT' and 'GL_INT' which depends on the internal format you chose.
4.The last parameter 'data' is an integer array.
Then in the shader, we must use 'isampler2D' or 'usampler2D' for signed integer texture and unsigned integer texture respectively.
At the end, we must write :
- #extension GL_EXT_gpu_shader4 : enable
on top of shaders which will use integer textures.
Here is an example of fragment shader:
- #extension GL_EXT_gpu_shader4 : enable
- varying out uvec4 FragOut;
- uniform usampler2D Tex1;
- void main(void) {
- uvec4 texel = texture2D(Tex1,gl_TexCoord[0].st);
- FragOut = texel;
- }
We have a user-defined fragment out put varying 'FragOut' instead of 'gl_FragColor' here, because gl_FragColor will only accept float vectors but not integer ones.
在OpenGL中使用整数类型纹理进行计算
通过 'GL_EXT_gpu_shader4'和'GL_EXT_texture_integer' 扩展,OpenGL能够支持整数型纹理。因此便可以使用该特性进行一些基于整数的GPU通用计算。
首先要创建一张整数型纹理:
- glGenTextures (1, &imageTex);
- glBindTexture(GL_TEXTURE_2D,imageTex);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
- glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA32UI,
- 2,2,0,GL_RGBA_INTEGER,GL_UNSIGNED_INT,data);
仔细看最后一个函数。几个非常重要的地方:
1.Internal Format 参数要带有’I‘或’UI‘的后缀,表明是有符号或无符号整数;
2.Format 参数要带有’_INTEGER'后缀;
3.Type 参数必须为 'GL_UNSIGNED_INT' 和 'GL_INT' 中的一个,具体是哪个取决于Internal Format 的选择;
4.最后一个参数'data’是一个已经在内存中创建好的整数型数组。
纹理准备好后,在Shader中,要将采样器类型前面加上‘i'或’ui‘的前缀,分别表明有符号和无符号整数,如'isampler2D'
最后,在Shader顶部,必须写入
- #extension
- GL_EXT_gpu_shader4 : enable
才能实现对整数型纹理的操作。
下面是一个fragment shader的实例代码:
- #extension
- GL_EXT_gpu_shader4 : enable
- varying out uvec4 FragOut;
- uniform usampler2D Tex1;
- void main(void) {
- uvec4 texel = texture2D(Tex1,gl_TexCoord[0].st);
- FragOut = texel;
- }
注意我们使用了自己定义的片元易变变量 FragOut而非gl_FragColor来进行输出,因为gl_FragColor只支持浮点型数据。