1 问题的发生
在一个安静祥和的夜晚,我撸了一个实验:读入一个图片,贴到一个矩形上显示出来;读入六个图片,做一个cubeMap然后渲染一个天空盒。
我发现,出现了两个情况:
这张是在矩形显示一个路飞,我发现它反过来了,为什么呢?因为图片正常的存储格式都会把一张图的左上角定位(0 , 0)点,但是OpenGL的纹理映射会把当前Texture对应的图片的左下角定为(0,0)点,具体来说,一张图读入之后,会是一个RGB为一个单位的内存,理论上就是一个线性排列的RGB数组,比如我传入(100 , 105)这个位置取一个像素,那么就会取到:
那么如果我传入uv是(0,0)进行采样会找到那个点呢?那么就是图片的左上角了。如果传入(0.1 , 0.2)这一组uv呢?那么假设图片长宽为100:150,通过跟uv相乘得到了(10 , 30)这个图片的像素坐标,由于在Texture分配的纹理空间当中仍然是按照图片的内存方式存储的,所以仍然得到的是左上角为(0,0)然后取(10 , 30)这个像素,所以我们需要把这个图片读入之后,在做成纹理之前,让它上下翻转一下,比如你用stb_image,就得调用:
stbi_set_flip_vertically_on_load(true);
这个句代码,然后我们看下效果:
一切正常了!
但是第二个实验,也就是cubemap的实验,诡异的情况发生了!在我没有进行图片像素翻转的情况下,竟然神乎其神的正确了!
渲染结果
原始图片
此时我陷入了沉思,难道CubeMap自己会做翻转?而且我还发现了,跟原来的图片相比,貌似左右也被它自己翻转了!
2 原理的通晓
为了能够搞清楚这个问题,我翻查了OpenGL的官方文档,我找到了一个很有趣的表格:
很多同学看到这个表格肯定不舒服,不知道这玩意儿到底是啥,我带着大家一点点看。
首先左边的一列代表我目前看向那个方向的轴,比如+rx代表了看向x轴正方向,即GL_TEXTURE_CUBE_MAP_POSITIVE_X,其他的依次类推。
第二列就是对应的参数
剩下的Sc Tc Ma都代表什么意思呢?我们先从CubeMap的向量采样说起,说有一个向量R(xyz),如果使用这个R向当前的CubeMap进行采样,那么是如何被翻译到某一个Texture的uv上面呢?
1 首先我们看下在R的每个分量当中,绝对值最大的是哪个,比如是 x 绝对值最大,并且 x 还是正数,那就说明要冲POSITIVE_X这个Texture进行取值
2 既然要取值了,总要计算uv坐标吧,ok,剩下的还有yz呢,此时由于冲着x正方向,那么u = z,v= y不就好了么,一横一竖,但是这里就有问题了!
出现的问题:
在冲向POSITIVE_X这个情况下我们讨论:此时我们在来看表格,这里的s就是u,t就是v,m就是我们选定的绝对值最大的那个分量。按照这个标准表格的说法,OpenGL在做CubeMap的采样的时候,会自动的根据方向不同(表格第一列决定的),从而对R的剩下的zy进行如下变化:
R.y = -R.y R.z = -R.z (此处操作对照表格第一行即可)
然后将变化完毕的yz作为计算st的参数传进去
所以我们就能够解释了,原来图片不进行翻转,在CubeMap的特殊系统之下,早就已经对我们的坐标进行了翻转,针对不同的直面方向,对坐标进行表格当中的变化,如果你问我为啥给出这样的标准呢?我只能一笑了之,这个我还不清楚,或者说约定俗成!
课程推荐:
OpenGL计算机图形学编程—从小白到精通