前面学习OpenGL的时候渲染的东西都是2D(更准确地说是在2D平面渲染2D的物体)的,而现在开始学习了3D的渲染,其中的门道还是很多的。这里提一提。
首先我们要了解OpenGL的坐标系统,屏幕中心为空间坐标系原点,向右为正x半轴,上为正y半轴,而 从屏幕内指向屏幕外为 正z半轴,如果要渲染一个物体的话需要给出顶点 (x, y, z) 坐标(渲染2D物体的时候z = 0)。
在每次顶点着色器运行之后,所有我们给出的这些顶点 (x, y, z)会被转化为标准设备坐标,再转化成屏幕坐标。而这个过程是像流水线那样分布的,方便我们对渲染出来的3D物体进行各种各样的操作(这里原本想写变换,但是这个过程又不止变换这个行为)。
这里流水线上的坐标系统有:
- 局部空间 (一个物体一开始在的空间)
- 世界空间 (将多个物体放在一起时候的空间)
- 观察空间(看物体,也就是使得每个坐标都是从观测的角度看到的)
- 裁剪空间(超出屏幕空间外的不会渲染)
- 屏幕空间(就是实际你看到的那个物体啦,当然还得经过其他几个着色器运行之后才能看到)
全写的话太长,因此先写局部 -> 世界空间的,后续的后面几篇blog会写到。
局部空间到世界空间,也就是位置的变换, 无非就是三个函数:位移,旋转,以及缩放。
//trans初始化为单位矩阵 glm::mat4 model = glm::mat4(1.0f); //位移 model = glm::translate(model, vec3); //旋转 model = glm::rotate(model, glm::radians(angle), vec3) //缩放 model = glm::scale(model, vec3);
这样子就组成了一个位移矩阵,值得注意的是,矩阵乘法是不遵守交换律的,也就是说我们写矩阵的顺序至关重要,一般在最右边的矩阵第一个和向量相乘(与实际阅读习惯相反)。举个栗子:上面的代码是先进行缩放操作,然后进行旋转,最后再位移。
单纯地创造一个位移矩阵当然不够(这什么事情也办不成),如果要确确实实地造成一系列变换操作,我们需要在vertex Shader中创建一个uniform变量,将model变换矩阵传入,接着与顶点数组相乘,再赋值到gl_Position。当出现多个变换矩阵的时候,记住乘法是从右往左读的。
忘了提一点,提供从局部空间到世界空间的变换的矩阵称之为模型矩阵(model matrix),也就是变量名model的由来
稍微详细一些的博客: