webgl投影矩阵推导(正射投影、透视投影)

文章介绍了WebGL中用于定义可视空间的两种方法:正射投影和透视投影。正射投影保持物体大小不变,产生长方体可视空间;透视投影模拟人眼效果,物体随距离变小,形成锥体可视空间。文章详细推导了两种投影的矩阵变换过程。
摘要由CSDN通过智能技术生成


前言

在webgl中,三维空间中的所有物体不是会都被绘制出来,只有当它在可视范围内时,才会进行绘制。因为不在可视范围中的物体即使绘制也不会在屏幕上显示。除了水平和垂直范围内的限制,WebGL还限制观察者的可视深度,即"能够看多远"。水平视角、垂直视角、可视深度,三者定义了可视空间。常用的可线空间分为两种:

  • 正射投影(orthographic projection)产生的长方体状可视空间
  • 透视投影(perspective projection)产生的锥体状可视空间

正射投影

经过正射投影后,场景中的物体大小尺寸都不会改变,即物体大小与其所在的位置没有关系,如下图所示:物体投影线与投影面保持垂直

在这里插入图片描述

正射投影的可视空间如下。其中前后两个面分别称近裁剪面远裁剪面,处于可视空间外的物体不会被渲染到屏幕上。

在这里插入图片描述

正射投影要做的事情就是将可视空间的坐标转换至 [-1, 1]的立方体空间中。下面我们来进行正射投影矩阵的推导,假设进行投影转换前坐标为(x,y,z),正射投影转换后坐标为(x‘,y’,z‘),left、right、top、bottom分别简写为l、r、t、b,近裁剪面near和原裁剪面far分别简写为n,f:

  • x => x’
    在这里插入图片描述

  • y => y’

在这里插入图片描述

  • z => z’

在这里插入图片描述

由于z方向实际是指向屏幕内的(左手坐标系),因此最终的表达式为z的系数需要乘以-1

将投影矩阵转换为表达式形式:
在这里插入图片描述
在这里插入图片描述
将:

  • x’ = 2x / (r-l) - (r+l) / r-l
  • y’ = 2y / (t-b) - (t+b) / t-b
  • z’ = -2z / (f-n) - (f+n) / f-n
  • w’ = 1

代入得正射投影矩阵👇
在这里插入图片描述

透视投影

与正射投影不同,透视投影符合人眼的实际效果:物体的形状与物体所处的位置有关,近处的物体大、远处的东西小,这样效果赋予了照片深度感,或称透视感

如下图所示,由于近裁剪面的存在,透视投影实际是一个被裁切了一块的锥体,也就是一个梯状空间。

在这里插入图片描述

透视投影变换矩阵分为两步:首先,将锥体空间转换到矩形空间,这里参考了这篇文章:链接。之后,按照正射投影原则将其投影至[-1,1]的立方空间内

  • 锥体空间 => 长方体空间

在这里插入图片描述

现在我们的目的是将锥体空间内坐标为(x,y,z)的 P 投影至由红色近平面构成的长方体可视空间中,图中的 P‘ 为在长方体空间中的坐标(x’, y’, z’)

首先考虑 x 和 y坐标:
在这里插入图片描述
上图为从x轴方向看向yz平面,很容易由相似三角形得:

在这里插入图片描述
也就是说
在这里插入图片描述
-代表第三行未知,接下来是关键的一步,按照webgl中齐次坐标的概念(x,y,z,1)与(kx,ky,kz,k)是等价的

将上个式子的右侧增加一项1,则:
在这里插入图片描述
转化为矩阵运算的形式就是:

在这里插入图片描述

只观察第三行:假设它们系数为a b c d

  • 当P’位于远平面,上式中右侧x y 的系数为 f:ax + by -cf +d = f * f
  • 当P’位于近平面(上式):ax + by -cn +d = n * n

可得 a = b = 0, c= n+f, d=nf,推导证明新的z坐标的值与其原x y 坐标没有关系,梯形空间转向长方体空间的转换矩阵为:

在这里插入图片描述

  • 透视投影矩阵

在进行一次正射投影即可得最终的透视矩阵

在这里插入图片描述
结果为👇

在这里插入图片描述

由于透视投影中没有直接给出top、bottom、left、right,因此需要使用视角α和宽高比aspect表示:

  • t = n * tan(α/2)
  • b = -t
  • r = n * aspect * tan(α/2)
  • l = -r

最终的正射投影矩阵👇
在这里插入图片描述

总结

  • 正射投影矩阵

在这里插入图片描述

  • 透视投影矩阵
    以上为这两天工作的简单记录,耐心定位问题后多参考文档一般都能解决。但其实在整个过程中最耗时的是捋整体的逻辑流程,毕竟不是自己从头开发的项目,尤其是要在加需求的同时改遗留的bug,不过这也算是一种锻炼了,加油吧。
  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值