引言
在某些情况下会需要用到多层绘制。FBO下有多个颜色挂接点(Color Attachment),可以用不同的挂接点挂接不同的纹理对象,实现绘制多张纹理(MRT),这在之前的文章里已经有所描述。但是有时候这种方法是不够好用的:
- 当纹理非常多时,挂接点往往不够;
- 用多层绘制还能实现一些更为方便的功能,比如只调用一次shader就完成多个不同视点图像的绘制。
特别是后面一点,实在是利器,配合视口矩阵(Viewport Array),简直是方便。
网上的资料非常有限,不过幸好有 OpenGL Wiki 这种官方的文档,只是文档往往也写得不够详细,英文的看着也费劲得很。折腾了好久,终于试出来了。
要实现Layered Rendering,需要用到多层纹理Array Texture、帧缓存对象FBO、几何着色器Geometry Shader。
多层纹理(Array Texture)
多层纹理就是一个纹理对象的一层MipMap下储存着多张纹理。最常用的二维纹理是GL_TEXTURE_2D
,对应的多层纹理就是GL_TEXTURE_2D_ARRAY
。其实这种纹理跟三维纹理差不多,用的函数往往也是三维纹理相关的函数,区别只在于第三维:深度,多层纹理的深度值就是层号,而三维纹理的深度值是像素坐标。
生成
二维多层纹理的生成方法跟普通的二维纹理几乎没有区别,只不过将GL_TEXTURE_2D
换成GL_TEXTURE_2D_ARRAY
。当然,在传入纹理数据时,应当换成glTexImage3D
函数,而这个函数相比glTexImage2D
也就多了一个深度变量,这个变量的值是纹理层数。对于Layered Rendering而言,是要将这个纹理绑到FBO上,然后画到这个纹理里,因此只需要调用:
glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, width, height, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
这里是写了2层width
*height
分辨率的纹理,用的是RGBA像素排列格式,最后一个参数是nullptr因为不必传内容。
读取
当然,纹理的读出还是有一些讲究的。在内存里纹理是按行优先的顺序存储,因此实际上拿到的