![6606882bc07ffaec8e88bc3d037ba650.png](https://img-blog.csdnimg.cn/img_convert/6606882bc07ffaec8e88bc3d037ba650.png)
LookAt 矩阵
OpenGL本身没有摄像机(Camera)的概念,但我们可以通过把场景中的所有物体往相反方向移动的方式来模拟出摄像机,产生一种我们在移动的感觉,而不是场景在移动。
lookat矩阵是由这些东西来定义的:摄像头位置,它看向的方向,以及向上的up方向。由于“OpenGL中我们知道摄像机指向z轴负方向”,所以给图如下:
![f02fcb6a2f829e850699c6d9893bab56.png](https://img-blog.csdnimg.cn/img_convert/f02fcb6a2f829e850699c6d9893bab56.png)
那么我们知道实际上坐标系的方向是这样的,我们用(eye - center)就能得到z轴的方向,然后我们定义一个向上的方向
![8523e72c7793a9d9551b3887908c145b.png](https://img-blog.csdnimg.cn/img_convert/8523e72c7793a9d9551b3887908c145b.png)
也可以参考这个图:
![b8f566c9ddf398c22e2111a664a90e98.png](https://img-blog.csdnimg.cn/img_convert/b8f566c9ddf398c22e2111a664a90e98.png)
再根据之前的坐标变换知识,于是我们可以得到lookat矩阵:
- R - 右向量,也就是相机坐标系x在世界坐标系中的表示
- U - 上向量,也就是相机坐标系y在世界坐标系中的表示
- D - 方向向量,也就是相机坐标系z在世界坐标系中的表示
- P - 相机在世界坐标系中位置
我感觉也可以这样理解,Rotation、Translation其实是相机在世界坐标系中的变换:
其实我们用它来看物体也就是它这个变换的逆变换:
而相机的旋转矩阵的逆是它的转置,平移矩阵的逆也可以在就是把它移回去,这样也跟上面的lookat矩阵一样。写个代码:
void
Viewport 矩阵
我们再来求另一个常见矩阵,我们现在有模型都在[-1,1]*[-1,1]*[-1,1]正方体中,我们想把它映射到位置[x,x+w]*[y,y+h]*[0,d]中,我们的操作是:
- 平移:先把[-1,1]*[-1,1]*[-1,1]平移到[0,2]*[0,2]*[0,2]
- 缩放:[0,2]*[0,2]*[0,2]缩放到[0,1]*[0,1]*[0,1]
- 缩放:[0,1]*[0,1]*[0,1]缩放到[0,w]*[0,h]*[0,d]
- 平移:[0,w]*[0,h]*[0,d]移动到[x,x+w]*[y,y+h]*[0,d]
就跟窗口变换十分类似,我们可以来求得这个变换的矩阵:
计算得:
这个矩阵是OpenGL中的Viewport矩阵。
Perspective 矩阵
投影有两种:
正交:
![b5e6061f4ed3f6e29021283644f33db0.png](https://img-blog.csdnimg.cn/img_convert/b5e6061f4ed3f6e29021283644f33db0.png)
透视:
![d6b100166eb5662f1f515c2d2602a0c2.png](https://img-blog.csdnimg.cn/img_convert/d6b100166eb5662f1f515c2d2602a0c2.png)
我们都知道透视法则-近大远小,就像上图,平行的铁路公路在我们的眼睛里也是会在远处相交的。
![1263f5de91ca365966a31fdf08faede9.png](https://img-blog.csdnimg.cn/img_convert/1263f5de91ca365966a31fdf08faede9.png)
如果我们要将P点投影到 z=0 平面上的 P' 点,camera放在C点(0, 0, c),很容易可以按照比例算出 |AB|/|AC| = |OD|/|OC| 可知: x/(c-z) = x'/c,可知:
所以我们也可以得到投影矩阵:
参考:
- 摄像机
- 坐标系统
- glViewport
- Perspective projection