一、空间变换问题的求解
当用矢量来描述空间中的一点时,求解空间点变换的具体方式问题,就变成了求矩阵的问题了。对于空间中的一个刚体(Rigid-Body)或一个点来说,其空间位置的变换矩阵一般都可以由平移(Translation)矩阵和旋转(Rotation)矩阵通过变换的级联(concatenation)来得到。而平移和旋转矩阵的表达方式是现成的(实际上也是通过下面介绍的方法来推导得到的),因此在应用时,空间点的变换矩阵通过相关矩阵的连乘就可以得到,这类变换问题还是比较简单的。而对于更一般性的问题,就需要有一般性的解决方法。这里,希望通过对平面阴影的生成的讨论,能初步得到解决此类问题的一般性思路。
( 图 一 )
物体在平面上投射阴影是最简单的一种阴影生成方法。假设投影平面坐标方程为y=0(如图 一),在光源L照射下,物体上任一点V在投影平面上的坐标为P;那么物体所有顶点在投影平面上相应的投影点P,就构成了物体的阴影形状。因此,只要求出平面投影的变换矩阵M就可以在平面y=0上得到物体的阴影形状了。根据已知条件和等比三角形的性质,可以得到V与P的相应坐标关系式:
(Px-Lx)/(Vx-Lx) = Ly/(Ly-Vy) => Px= (LyVx-LyLx+LxLy-LxVy)/(Ly-Vy) => Px= (LyVx-LxVy)/(Ly-Vy) (1式)
同理可得:Pz= (LyVz-LzVy)/(Ly-Vy) (2式)
并且根据已知条件有:Py = 0 (3式)
现在的问题是,如何根据以上的1~3式得到矩阵M?
先假设矩阵M为:
a11 a12 a13 a14
a21 a22 a23 a24
a31 a32 a33 a34
a41 a42 a43 a44
设有向量 q1= (a11, a21, a31, a41)T, q2= (a12, a22, a32, a42)T, q3= (a13, a23, a33, a43)T, q4= (a14, a24, a34, a44)T
则 M = (q1, q2, q3, q4)
因为 P = MV
所以有: Vxq1 + Vyq2 + Vzq3 + q4 = (Px, Py, Pz, 1)T (4式)
将1~3式代入4式得:
Vxq1 + Vyq2 + Vzq3 + q4 = ((LyVx-LxVy)/(Ly-Vy), 0, (LyVz-LzVy)/(Ly-Vy), 1)T (5式)
5式可以看作四维向量齐次变换的结果,因此又可以得到:
Vxq1 + Vyq2 + Vzq3 + q4 = ((LyVx-LxVy), 0, (LyVz-LzVy), (Ly-Vy))T (6式)
把6式直接用列向量表达出来,会看得更清楚一些。下面详细讨论:
对于 (LyVx-LxVy) 来说,只包含了Vx和Vy项,因此Vz对应的q3的a13,和q4的a14都可以设为0;因为与Vx相乘的是Ly,所以a11可以设为Ly;同理得a12为-Lx。
以此类推就可以得到矩阵M为:
Ly -Lx 0 0
0 0 0 0
0 -Lz Ly 0
0 -1 0 -Ly
要想根据空间点的变换方程直接得出相应的变换矩阵,往往会比较困难,而经过4式的转换就使问题变得简单了很多。三维空间的变换用四维向量来表达,有时可以简化问题的求解过程,这一点从5式到6式的转化中可以体现出来——正是由于有了第四维的出现,使原先比较复杂的包含除法的表达式简化了许多。
上面例子是一种特殊情况,在这种情况中,投影平面就是坐标系OXZ平面。那么对任一平面的投影(如图 二)又应该如何计算?
对于这一更一般化的问题,上例的解决方法仍是适用的。
( 图 二 )
在图二中,物体上任一点V在投影平面上的投影P,一定既在LV所确定的直线上,又在投影平面上。可以列出向量方程组:
NP + d = 0 (7式) 平面方程,N为平面法向量,d为常量
P-L = t(V-L) (8式) 直线的参数方程,t为标量
根据8式有:P = t(V-L) + L
所以 tN(V-L) + NL = NP = -d => t = (-d - NL)/(N(V-L)) (9式)
将9式代入8式得:
P = (-d - NL)(V-L)/(N(V-L)) + L
P = L - (d+NL)(V-L)/(N(V-L)) (10式)
在10式中,L为矢量,分子中的V-L也为矢量,(d+NL)/(N(V-L)) 为标量值,为简化问题可将其设为k.则有:
P = L - k(V-L)
据此得到相应的坐标表式:
Px = Lx - k(Vx-Lx) Py = Ly - k(Vy-Ly) Pz = Lz - k(Vz-Lz)
再用上面提到的方法可得到矩阵:
-k 0 0 (k+1)Lx
0 -k 0 (k+1)Ly
0 0 -k (k+1)Lz
0 0 0 1
将k代入化简后可以得到矩阵T:
-(d+NL) 0 0 (d+NV)Lx
0 -(d+NL) 0 (d+NV)Ly
0 0 -(d+NL) (d+NV)Lz
0 0 0 N(V-L)
设P'为P齐次化之前的向量,显然有 P' = TV 但矩阵T并不是要求的M。因为,如果变换矩阵要根据V的不同重新计算的话,就失去意义了。
为此需要进一步讨论。
因为 P' = TV = T(Vx, Vy, Vz, 1)T,
所以,将所得结果中的NV用坐标形式展开得到 P'x = (NxLx-d-NL)Vx + NyLxVy + NzLxVz + dLx
也就是说,当a11= NxLx-d-NL,a12 = NyLx,a13 = NzLx,a14 = dLx 时也可以得到相同的结果,并且此时矩阵中将不再有向量V出现。
以此类推可得到最终要求的M。
回顾以上的讨论可知,对一般的三维空间变换问题的求解可以遵循以下流程:
1. 根据变换前后空间向量间的几何关系列出向量方程
2. 解方程,得到未知量的向量表达式
3. 根据向量表达式列出自变量与应变量间的坐标关系式
4. 用列向量组表示要求的变换矩阵,并根据坐标关系式列出相应的向量方程
5. 化简(如有分式表达,可利用第四维w化简)
6. 确定待求矩阵各元素。这一步所得结果不是唯一的,需要根据具体情况作相应分析,力求所得矩阵符合要求,并能使矩阵与矢量相乘的计算量最小。
用上面讨论的方法也可以求其它的问题,比如求透视投影的矩阵问题等。
另外,在讨论比较复杂的问题之前,先将问题特殊化,研究其相应解法,也会对解决一般性问题提供好的解决方案。
二、平面投影阴影的几个问题
在实际的应用中,平面投影生成阴影不太会被用到,因为它有许多缺陷:
1. 不能生成自阴影
2. 这一算法只适用于物体在平面上的投影
3. 阴影边缘过于尖锐(sharp),不象现实中阴影有一种模糊的过渡。解决这一问题的办法之一是,把原来的一个点光源看作是分布在一个小范围内的若干个点光源组成的光源组。同一物体在此光源组中的每个光源的照射下,都生成一个单独的纹理,最终的阴影明暗度是对这几个纹理同时进行采样,然后对多个采样结果求平均值得到的,以生成所谓的软阴影(soft shadow)。
4. 效率太低。效率低的原因有两个,一个是按照上面的算法,一个物体在生成平面阴影时,所有顶点(不论是其受光面还是背光面)都会参与运算,也就意味着物体在平面上的阴影区会被反复重复涂描。解决这一问题的办法是根据三角面法向量与光向量的点乘结果,来剔除背光面,从而提高运算效率。效率低的第二个原因是,每帧都要重新计算物体阴影区域,对静止的物体也不例外。解决这一问题的办法是,先将物体在光源L下的阴影投射到一个平面A上生成相应的纹理,再在对实际接收阴影投射的平面B进行光栅化时,从A纹理中进行采样,从而将A平面纹理覆盖到平面B上。其中的关键是平面B的UV坐标要实时生成,可以想象把构成平面B的各顶点,投影到平面A上,在A上所对应点的x,y值(在-1~1之间)经过转化后就是相应的UV值,而所用的投影矩阵就是光源L将物体投影到平面A上的转换矩阵。这样一来只要在光源发生移动时,才对平面A上的纹理进行重新描绘,从而减少运算量。