本文主要是介绍CubeMap天空盒的方向与调整,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
参考:https://learnopengl.com/Advanced-OpenGL/Cubemaps
参考:https://www.jianshu.com/p/91c367d732b3
参考:https://docs.microsoft.com/en-us/windows/win32/direct3d9/cubic-environment-mapping
(Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu)
讨论天空盒之前, 先明确下坐标系:
对于View投影坐标系, OpenGL与Direct采用了不同的坐标系, OpenGL采用的View坐标系(右手坐标系)-Y-up坐标系的front为-z(negtive z), Direct采用的View坐标系(左手坐标系)-Y-up坐标系的front为+z(postive z).
天空盒6张图片组装盒子时, 均以front为中心进行的组装.
TOP
Left Front Right BackBottom
下面讨论的基础以Front为-z方向进行讨论(如果是Front为+z情况,需要反转+z/-z的位置);
另外不考虑flip-y的情况(flip-y情况-所有图片方向颠倒, 图片的Top/Bottom放置图片需要置换, 例如盒子倒过来后, 上面的盖子要移到下面)
1. 构造CubeMap
对于CubeMap来说,构造一个完整的Cubemap的基本代码为:
a. 先创建一个纹理,并绑定为TEXTURE_CUBE_MAP类型纹理
b. 为CUBE纹理设置前后左右上下的贴图
var texture = gl.createTexture();
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture);
gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, ..., dataFront);
gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSTIVE_Z, 0, ..., dataBack);
gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, ..., dataLeft);
gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSTIVE_X, 0, ..., dataRight);
gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSTIVE_Y, 0, ..., dataTop);
gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, ..., dataBottom);
2. CubeMap的方向
可以看到:
前对应的-z轴,后对应+z轴,左对应-x轴,右对应+x轴,上对应正y轴,下对应-y轴
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z Front
GL_TEXTURE_CUBE_MAP_POSITIVE_Z Back
GL_TEXTURE_CUBE_MAP_NEGATIVE_X Left
GL_TEXTURE_CUBE_MAP_POSITIVE_X Right
GL_TEXTURE_CUBE_MAP_POSITIVE_Y Top
GL_TEXTURE_CUBE_MAP_NEGATIVE_Y Bottom
这个是著名的Y-up坐标系,和Model-View-Projection的View-Camera坐标系很相似,+Y指向相机的上方向,-Z指向镜头观察的方向,X+指向相机的右侧方向。
3. CubeMap图片的连接
特别需要关注的是,图片的连接方式:
我们都知道这六张图要拼接成一个正方体,图与图之间是要连接到一块的;
但是如何连接,以那张图为中心连接,这会决定了图片的上方向是否需要调整;正常情况以Front作为连接的中心,但例如改为以Bottom底部图片作为连接的中心,那么左右侧的连接边就会和变化,从而导致图片需要旋转90度/-90度才能连接上。
下面是连接方式经典的图形:以Front为中心连接其它的图片
----------- T O P -------------
LEFT -> FRONT ->RIGHT
-----------BOTTOM------------
(Back图片放在Top上/Bottom下/Left左/Right右 均可)
4. CubeMap作为天空盒的位置
作为天空盒时,需要具备天空盒的一些特点,如始终在天空盒的内部,天空盒的方向稳定。
已知:View投影矩阵把世界坐标系转换到以相机点为中心,-Z指向相机观察方向,+Y指向相机上方向;
实现:相机放在CubeMap的中心位置
我们希望时钟把相机放在CubeMap的中心位置,那么可以在SkyBox的的Vertex着色器中,仅保留相机View矩阵的旋转量作为SkyBox的View矩阵,从而让相机可以旋转观察CubeMap内部。
实现:SkyBox方向固定
盒子的位置固定,主要是采样信息的固定,采样坐标使用Skybox的点坐标,相机的采样点和SkyBox的原始点统一,保证固定点的采样值时钟不变,SkyBox方向固定。
attribute vec3 a_pos;
varying vec3 v_coord;
uniform mat4 viewRotate;
void main()
{v_coord = a_pos;vec4 pos = viewRotate * vec4(aPos, 1.0);gl_Position = vec4(pos.xy, 1.0, 1.0);
}
CubeMap天空盒的方向调整
CubeMap的坐标系是Y-Up;创建模型时通常创建的Z-Up的模型坐标系,场景中我们也经常使用Z-Up的场景坐标系;
CubeMap实现的是Y-Up,以Front为中心连接各个图片,Front指向-Z。
要实现:使用Z-Up坐标采样到天空盒
对于天空盒的旋转,我们可以考虑几种做法来调整CubeMap采样的方向:
- 修改天空盒的照片,Front(-Z)放Bottom图片,其它图片,修改方向,匹配连接到Bottom图片上。这样,图片对应的为Z-Up结构。
- 修改viewRotate旋转量,Z-Up与Y-Up的转换,可以以x轴为中心旋转90度得到,为viewRotate添加上该旋转量,从而采样时调整方向采样。
- 修改采样坐标值,盒子不变的情况下,把采样坐标值调整90度,从而上方采样到y轴图片。
(Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu)
这篇关于CubeMap天空盒的方向与调整的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!