TA百人计划学习笔记 1.2.3.1 P矩阵补充
2024-01-09 18:30:09
- 源视频 图形学投影矩阵推导_哔哩哔哩_bilibili
- 正交投影
- 透视投影
- 博客 https://www.cnblogs.com/bluebean/p/5276111.htm (步骤很清楚)
- 视锥体
- 如图,近截面与远截面之间构成的这个四棱台就是视锥体,而透视投影矩阵的任务就是把位于视锥体内的物体的顶点X,Y,Z坐标映射到[-1,1]范围。这就相当于把这个四棱台扭曲变形成一个立方体。这个立方体叫做规则观察体 (Canonical View Volume, CVV)。如下图:
- 变换方法或规则:
- 如下图,有一点P,位于视锥体内,设坐标为(x,y,z).分别对x,y坐标和z坐标的变换到[-1,1]的方式进行讨论:
- 1.x,y坐标的变换方式:
- ?
- (1)连接视点eye与P点与近裁剪面交于P’点
- (2)设近裁剪面的宽度为W,高度为H,P’点的x坐标范围是[-W/2,W/2],y坐标范围是[-H/2,H/2],然后分别线性映射至[-1,1]内即可。
- ?
- 2.z坐标的变换方式
- z坐标的范围是N至F,需要映射到[-1,1],映射方法暂时按下,不做想法。
- 1.x,y坐标的变换方式:
- 如下图,有一点P,位于视锥体内,设坐标为(x,y,z).分别对x,y坐标和z坐标的变换到[-1,1]的方式进行讨论:
- 透视投影函数形式
- void Matrix4X4::initPersProjMatrix(float FOV, const float aspect, float zNear, float zFar)
- 透视投影矩阵构建函数的参数:
- Fov:纵向的视角大小
- ?
- aspect:裁剪面的宽高比
- zNear:近裁剪面离摄像机的距离,图中的n
- zFar:远裁剪面离摄像机的距离,图中的f
- ?
- Fov:纵向的视角大小
- 通过这几个参数和三角函数的数学知识可以求得近裁剪面的高度,参考上图:
- 求得点P在近裁剪面的投影点P’的坐标
- 1.根据相似三角形对应边长度的比率相同,由图可得
- 其中
- 2.x’,y’的范围沿原点对称,只要将他们分别除以W/2,H/2,即可以使范围位于[-1,1]内。前面已求得W,H,因此:
- 3.假设
- 4.我们最后需要的坐标点P’’即是
- 1.根据相似三角形对应边长度的比率相同,由图可得
- 推导矩阵
- 然后为了自动化的得到这个结果,我们使用矩阵这种数学工具,将一个矩阵乘以一个向量,得到一个新的向量,使得我们所有的运算步骤和运算数据蕴藏在矩阵和乘法中。下面的工作就是寻找到一个矩阵使得:
- 我们发现求解
- 很难找出合适的m00、m02,因为左边x和z是以加法的形式相邻,右边z确成为了x的分母。
- 解决方法:将右边的以四维列向量表示的坐标每一项乘以z,所以有:
- 所以可以求得矩阵为
- 解决方法:将右边的以四维列向量表示的坐标每一项乘以z,所以有:
- 最后求得投影矩阵为
- 将这样的矩阵乘以视锥体内的一个顶点坐标,得到一个新的向量,再将这个向量的每个分量除以第四个分量(w)(这一步叫做透视除法,在gpu渲染管线中位于顶点着色器处理之后,由硬件自动完成, 之后就得到了规则立方观察体中的新的坐标。
- 注意:z坐标的映射方式的获得,最后我们是为了方便矩阵乘法的操作反向求得了z坐标与cvv中的z坐标的映射方式:
- ?
- 可见两者的映射并不是线性的, 如下图所示;
- 上图为 深度缓存中的深度值DepthValue和物体距离摄像机深度ZValue的关系图;DepthValue=(z''+1)/2,将深度值从范围(-1,1)转换到(0,1)。
- 可见两者的映射并不是线性的, 如下图所示;
- ?
- 然后为了自动化的得到这个结果,我们使用矩阵这种数学工具,将一个矩阵乘以一个向量,得到一个新的向量,使得我们所有的运算步骤和运算数据蕴藏在矩阵和乘法中。下面的工作就是寻找到一个矩阵使得:
- 代码示例:
- 代码
- void Matrix4X4::initPersProjMatrix(float FOV, const float aspect, float zNear, float zFar)
- {
- const float zRange = zNear - zFar;
- const float tanHalfFOV = tanf(ToRadian(FOV / 2.0f));
- elements[0][0] = 1.0f / (tanHalfFOV * aspect);
- elements[0][1] = 0.0f;
- elements[0][2] = 0.0f;
- elements[0][3] = 0.0;6
- elements[1][0] = 0.0f;
- elements[1][1] = 1.0f / tanHalfFOV;
- elements[1][2] = 0.0f;
- elements[1][3] = 0.0;7
- elements[2][0] = 0.0f;
- elements[2][1] = 0.0f;
- elements[2][2] = (-zNear - zFar) / zRange;
- elements[2][3] = 2.0f * zFar*zNear / zRange;8
- elements[3][0] = 0.0f;
- elements[3][1] = 0.0f;
- elements[3][2] = 1.0f;
- elements[3][3] = 0.0;9
- }
- 视锥体
文章来源:https://blog.csdn.net/weixin_57856130/article/details/135457568
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!