参考文章
什么是立方体贴图
简单来说,立方体贴图就是一个包含了6个2D纹理的纹理,每个2D纹理都组成了立方体的一个面:一个有纹理的立方体。这样做的好处是什么?不妨假设我们使用的立方体是1×1×1的,那么从坐标原点到该立方体上的任意一点可以组成一个方向向量,该方向向量最终会击中立方体的某个面,从而获取与之对应的纹理值。如下图所示:
所以用立方体贴图来实现天空盒非常简单。
创建一个立方体贴图
由于它有6个面,所以我们要为每个面分别使用一张2D纹理,事实上,opengl已经为我们提供了立方体贴图的6个特殊纹理坐标:
和OpenGL的很多枚举(Enum)一样,它们背后的int值是线性递增的,所以如果我们有一个纹理位置的数组或者vector,我们就可以从GL_TEXTURE_CUBE_MAP_POSITIVE_X开始遍历它们,在每个迭代中对枚举值加1,从而遍历整个纹理目标。
更多的细节可以看参考文章中提到的教程,这里就不再赘述了,下面将探讨一下立方体贴图的采样方式。
采样方式
现在让我们思考一下,如果让我们自己实现samplerCube,要怎么做呢?首先我们需要6张2D纹理,对应到GLSL中也就是6个sampler2D对象,然后我们知道立方体贴图的纹理坐标是三维的,那么如何把它们对应起来呢?我们可以取纹理坐标绝对值最大的那一维——这告诉我们这个方向向量将命中立方体的哪个面,即我们将在哪个纹理上进行采样,然后把其它两个维度的值转换到 [ 0 , 1 ] [0,1] [0,1]当作sampler2D对象的纹理坐标即可。由于我们立方体的坐标范围是 [ − 1 , 1 ] 3 [-1,1]^3 [−1,1]3,那么把它转换到 [ 0 , 1 ] [0,1] [0,1]是非常简单的: ( x + 1 ) / 2 (x+1)/2 (x+1)/2。
那么着色器部分的代码就很好写了:
#version 330 core
out vec4 FragColor;
in vec3 TexCoords;
uniform sampler2D posx;
uniform sampler2D negx;
uniform sampler2D posy;
uniform sampler2D negy;
uniform