总结:计算机图形学更适合精通高等数学和线性代数的美術理论生
文章目录
- 虚拟照相机观察变换
- 相机的控制
- 【世界坐标系 - > 相机坐标系】
- 总 - 投影变换
- 【正交投影】 - Orthographic Projection
- 视景体(裁剪体)
- 投影规范化(Projection Normalization)
- 【透视投影】 - Perspective Projection
- 【视椎体】怎么理解:
- 两种定义透视投影视见体
- 类似于正交投影的棱台视见体 【frustum】
- 利用视域(FoV,Field of View)定义的视见体 【perspective】
- 投影规范化
- 【四种正方体对比】:模型变换 ,正交投影,棱台指定视见体的透视投影 ,视域指定视见体的透视投影
虚拟照相机观察变换
-
投影线相交于投影中心(COP:Center of Projection),而COP对应于人眼或者相机镜头,从COP点发出投影光线将物体投影在投影平面上而成像。
-
只要顶点着色器输出的顶点位于裁剪体(或视见体)内部,那么这些顶点会被送入绘制流水线后面的光栅化模块。
【说人话就是东西如果在视野内,那么就画出来】
相机的控制
如果我们加入自定义的相机姿态,那么对相机的控制则尤为重要,因为相机的位置和朝向将决定怎么发出投影射线而将物体投影到投影平面上。
-
设置照相机的位置和方向,该操作由模-视变换来完成,当顶点经过该变换之后将位于相机坐标系中
-
使用投影变换,也就是说把指定的投影(正交投影或透视投影)应用到顶点上。并将默认的视见体内部对象变换到指定的裁剪立方体的内部
【世界坐标系 - > 相机坐标系】
所谓变换就是设置一个矩阵,然后乘以三维顶点的坐标(考虑齐次坐标系),得到变换之后的坐标值。
模-视变换是建模变换和观察变换的级联
- 建模变换矩阵 将对象变换到世界坐标
(一般来说,建模变换矩阵是单位阵,我们不需要额外处理。即 m o d e l M a t r i x = I 4 modelMatrix=I_4 modelMatrix=I4)- 观察变换 将世界坐标转换到相机坐标
对于照相机来说,其初始方向通常指向z轴负方向,这样才能看见位于相机前方的模型。
考虑一个位于原点的对象,由于照相机初始位置也在原点,方向指向z轴负方向,
如果该对象需要在z轴正方向的投影平面(在OpenGL中通常是近裁剪平面)上成像,那么必须要将相机沿着z轴正方向往后移动一定距离。
- 相机移动之后的位置称为观察参考点(VRP,View Reference Pint)
考虑采用规范化变换(Normalization Transformation)来表示相机坐标系并指定相机的位置
-
观察平面法向量(VPN:View-plane Normal)
-
观察正向向量(VUP:View-up Vector)
其中VPN指定了相机的胶片平面,而平面是由其法向量决定的。如果只是指定了VPN,相机还可以绕VPN旋转,此时我们再加上VUP,就能完全固定一个相机的位置了。
-
视点 :相机位置 e = ( e y e x , e y e y , e y e z ) e=(eye_x,eye_y,eye_z ) e=(eyex,eyey,eyez)
-
参考点 :相机指向的另一个点 a = ( a x , a y , a z ) a=(a_x,a_y,a_z ) a=(ax,ay,az)
那么 V P N = e − a VPN = e-a VPN=e−a
归一化(normalize): n = V P N ∣ V P N ∣ \mathbf{n}= \frac{VPN}{|VPN|} n=∣VPN∣VPN
正是因为归一化,后面点积这个向量,便直接得出该新坐标轴上的投影(其实除以了一个 1)
相机看向的是 ( 0 , 0 , 0 ) (0,0,0) (0,0,0)
相机的上方即VUP 一直是 ( 0 , 1 , 0 ) (0,1,0) (0,1,0)
那么做叉积×即可得出VPN
设VUP,VPN归一化后为 u \mathbf{u} u , v \mathbf{v} v
通过采用u,n,v即可定义出相机的观察变换矩阵:
viewMatrix = [ u 1 u 2 u 3 0 v 1 v 2 v 3 0 n 1 n 2 n 3 0 0 0 0 1 ] \text{viewMatrix} = \begin{bmatrix} u_1 & u_2 & u_3 & 0 \\ v_1 & v_2 & v_3 & 0 \\ n_1 & n_2 & n_3 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} viewMatrix= u1v1n10u2v2n20u3v3n300001
还需要将相机从坐标原点移动到视点 (因为标架是eye在原点旋转的 —— 向量投影)
平移矩阵:
T = [ 1 0 0 − x 0 1 0 − y 0 0 1 − z 0 0 0 1 ] T = \begin{bmatrix} 1 & 0 & 0 & -x \\ 0 & 1 & 0 & -y \\ 0 & 0 & 1 & -z \\ 0 & 0 & 0 & 1 \end{bmatrix} T= 100001000010−x−y−z1
(这里的 x y z 其实就是 eye的反,不过在新的标架下,eye也要变换。(做点积,上面归一化有提及原理))
所以最终的相机观察矩阵 viewMatrix :
[ u x u y u z − x u x − y u y − z u z v x v y v z − x v x − y v y − z v z n x n y n z − x n x − y n y − z n z 0 0 0 1 ] \begin{bmatrix} u_x & u_y & u_z & -x u_x - y u_y - z u_z \\ v_x & v_y & v_z & -x v_x - y v_y - z v_z \\ n_x & n_y & n_z & -x n_x - y n_y - z n_z \\ 0 & 0 & 0 & 1 \end{bmatrix} uxvxnx0uyvyny0uzvznz0−xux−yuy−zuz−xvx−yvy−zvz−xnx−yny−znz1
总 - 投影变换
在经过三维物体的模-视变换后,场景中的三维物体即被放在了相机能够观察到的位置。
而投影变换的目的则是定义一个视景体(View Volume),使得视景体外多余的部分被裁减掉,最终进入到投影平面上的只是视景体内的部分。
投影包含正交投影(Orthographic Projection)和透视投影(Perspective Project)两种。
【正交投影】 - Orthographic Projection
将在世界坐标系所有单位的 z 坐标变为 0 ,那他们就在 x 轴和 y轴所在的平面上了
或者将 x 轴和 y轴所在的平面 平移,移动到哪里,就只能看到哪里的“切面”
那么假如有一个球,你只要不切到这个球,那么你看到的永远是一个圆。
视景体(裁剪体)
投影规范化(Projection Normalization)
在OpenGL的渲染管线中定义了一个标准视景体 :
x = ± 1 ; y = ± 1 ; z = ± 1 x=±1;y=±1;z=±1 x=±1;y=±1;z=±1
(使用的投影矩阵)
【透视投影】 - Perspective Projection
人类看到的,相机拍到的二维平面却能看出三维的效果
如下图
比如左上角的正方体,红色边应该是平行的,但是无限延长,会交于一点:
你可以去楼道观察两边的墙壁,或者拍张照比划比划。
【视椎体】怎么理解:
这就是视椎体(Frustum):
表示相机能看到的区域。
(你可以用左右手张开地挡在自己的头前方模拟这个视野,其实汽车车灯照明效果就是这样的)
相比于正交投影的视景体,对于透视投影,我们也需要设置一个视景体来裁剪三维物体如下,
也就是说在视景体内部的三维物体才能被投影到投影平面上,剩下超出的部分则被裁减掉。
在透视投影中,由于投影中心在理想情况下是一个点,所以形成的视景体构成一个截头椎体(Frustum)。
两种定义透视投影视见体
类似于正交投影的棱台视见体 【frustum】
利用视域(FoV,Field of View)定义的视见体 【perspective】
投影规范化
【四种正方体对比】:模型变换 ,正交投影,棱台指定视见体的透视投影 ,视域指定视见体的透视投影
类:各种参数放在一起喽
相机视角及运动轨迹:
观察:
- 左上 : 模型变换
- 右上 : 正交投影
- 左下 : 棱台指定视见体的透视投影
- 右下 : 视域指定视见体的透视投影
我们不断加大 scale,对于 模型变换 来说,是增大尺寸,即靠近物体甚至穿透。由于相机始终看向中心,最终会穿过中点看回来。如图,现在看到的是背面。
而对于 正交投影来说 ,是“减小”可视空间(“选择更小的区域并铺满窗口”,即只看这区域,即放大了)。减为负的,可视空间"反向放大",看到的即如图,x和y都变为 -x -y
对于下面两个透视投影,左边棱台可见看起来更大一点,正是因为near离得近。
(见本文的“两种定义透视投影视见体”)