OpenGL的Image特性简介
Image是在OpenGL 4.2成为core标准的,大概目标是用于通用计算,因此它只能在Compute Shader和Fragment Shader里使用。它跟一个特定的纹理绑定在一起,所进行的操作会直接影响这个纹理。
纹理在glsl里是sampler,是只能读不能写的,以前要实现通用计算的数据输出,就得建一个FBO,绑定一张跟源纹理一样大的新纹理,把计算结果画上去。这样的绘制有其局限性,比方说读取数据可以用纹理坐标指定,但是写入数据的位置却是不能任意指定的,只能是当前绘制的像素,在许多方面有其不便之处。
Image的引入就使得事情变得比较简单了。Image绑定的纹理可以直接指定Image坐标写入,使得更为复杂的操作成为可能。不过由于坐标可以任意指定,就可能出现两组数据同时指定同一个坐标的可能,造成访问冲突。因此Image还有一个Atomic操作的机制用于解决访问冲突。
Compute Shader由于其特殊性,不会对当前的Color Buffer进行任何写入,因此数据的输出必然要借助Image,大概这是Image出现的一个最重要的原因吧。
Image的使用
OpenGL环境端
Image定义
首先一张纹理是必须的。纹理生成之后,使用glBindImageTexture
命令来建立一个Image。原型如下:
void glBindImageTexture(GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format)
这里有几个重要参数。
其中要重点注意的是unit
,这个参数可以看成是Image的编号。Wiki里说只有Compute Shader和Fragment Shader支持非零个Image Unit,意思就是只有这两个Shader才能用Image的意思了吧。具体支持几个可以用GL_MAX_*_IMAGE_UNIFORMS
来查询,星号指的是Shader。一般而言,编号从0开始呗,至少能用8个,一般也够了吧。
另外一个就是access
,有GL_READ_ONLY