`
javahigh1
  • 浏览: 1267144 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

3D变换中法向量变换矩阵的推导

 
阅读更多

3D变换中法向量变换矩阵的推导<?XML:NAMESPACE PREFIX = O />

潘李亮 2003-11-23

xheartblue@etang.com

在一个3D几何管道中,输入的顶点要经过一系列的变换,最终变换到一个投影空间里来,去掉最后的一个Z-坐标后就是一个规格化的2D的屏幕坐标。变换通常分成两个步骤,一是视图/模型变换(D3D里把这个分开成了两个变换世界变换和视图变换),二是投影变换Project.

当我们不去为一个顶点指定一个法向量的时候,一个多边形的顶点的法向量会由系统自动计算生成,计算的方法是由交成这个顶点的两条边做个叉积(叉积的时候注意叉积的方向),这个步骤通常在变换到视图空间后进行的。所以通常情况下我们是没有必要关心法向量是如何变换到视空间中来的。(为何是视图空间?而不是投影完成后的投影空间?原因是光照等计算都是在需要视图空间中的参数进行的。投影空间中的坐标只是为了裁剪和Z-Test用的)。

那么何时需要我们自己去关心法向量是如何变换的呢?这个谁也说不上来。但是肯定是需要的,比如你自己写一个Vertex Shader的时候,也许你需要用到法向量,这时就需要你用正确的变换方法把它变换到视图空间中来------当然你自己如果要写一个软件渲染器的话……。下面我先来用数学公式严密的推导出变换公式,再来解释一些其他的误区。

假设:我们的Model View变换矩阵为<?XML:NAMESPACE PREFIX = V /><shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f"><stroke joinstyle="miter"></stroke><formulas><f eqn="if lineDrawn pixelLineWidth 0"></f><f eqn="sum @0 1 0"></f><f eqn="sum 0 0 @1"></f><f eqn="prod @2 1 2"></f><f eqn="prod @3 21600 pixelWidth"></f><f eqn="prod @3 21600 pixelHeight"></f><f eqn="sum @0 0 1"></f><f eqn="prod @6 1 2"></f><f eqn="prod @7 21600 pixelWidth"></f><f eqn="sum @8 21600 0"></f><f eqn="prod @7 21600 pixelHeight"></f><f eqn="sum @10 21600 0"></f></formulas><path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"></path><lock v:ext="edit" aspectratio="t"></lock></shapetype><shape id="_x0000_i1025" style="WIDTH: 9pt; HEIGHT: 17.25pt" type="#_x0000_t75" o:ole=""><imagedata src="file:///C:/DOCUME~1/stanly/LOCALS~1/Temp/msoclip1/06/clip_image001.wmz" o:title=""></imagedata></shape> <shape id="_x0000_i1026" style="WIDTH: 26.25pt; HEIGHT: 18pt" type="#_x0000_t75" o:ole=""><imagedata src="file:///C:/DOCUME~1/stanly/LOCALS~1/Temp/msoclip1/06/clip_image003.wmz" o:title=""></imagedata></shape> ,<shape id="_x0000_i1027" style="WIDTH: 9pt; HEIGHT: 17.25pt" type="#_x0000_t75" o:ole=""><imagedata src="file:///C:/DOCUME~1/stanly/LOCALS~1/Temp/msoclip1/06/clip_image001.wmz" o:title=""></imagedata></shape> <shape id="_x0000_i1028" style="WIDTH: 14.25pt; HEIGHT: 14.25pt" type="#_x0000_t75" o:ole=""><imagedata src="file:///C:/DOCUME~1/stanly/LOCALS~1/Temp/msoclip1/06/clip_image006.wmz" o:title=""></imagedata></shape> 为世界空间中的法向量,<shape id="_x0000_i1029" style="WIDTH: 27pt; HEIGHT: 17.25pt" type="#_x0000_t75" o:ole=""><imagedata src="file:///C:/DOCUME~1/stanly/LOCALS~1/Temp/msoclip1/06/clip_image008.wmz" o:title=""></imagedata></shape> 为世界空间中的两个顶点,两个顶点所在的平面和<shape id="_x0000_i1030" style="WIDTH: 14.25pt; HEIGHT: 14.25pt" type="#_x0000_t75" o:ole=""><imagedata src="file:///C:/DOCUME~1/stanly/LOCALS~1/Temp/msoclip1/06/clip_image006.wmz" o:title=""></imagedata></shape> 垂直。则我们很快就有如下的关系<shape id="_x0000_i1031" style="WIDTH: 81pt; HEIGHT: 17.25pt" type="#_x0000_t75" o:ole=""><imagedata src="file:///C:/DOCUME~1/stanly/LOCALS~1/Temp/msoclip1/06/clip_image011.wmz" o:title=""></imagedata></shape> ,即<shape id="_x0000_i1032" style="WIDTH: 33pt; HEIGHT: 17.25pt" type="#_x0000_t75" o:ole=""><imagedata src="file:///C:/DOCUME~1/stanly/LOCALS~1/Temp/msoclip1/06/clip_image013.wmz" o:title=""></imagedata></shape> <shape id="_x0000_i1033" style="WIDTH: 14.25pt; HEIGHT: 14.25pt" type="#_x0000_t75" o:ole=""><imagedata src="file:///C:/DOCUME~1/stanly/LOCALS~1/Temp/msoclip1/06/clip_image015.wmz" o:title=""></imagedata></shape> 的点积为零。在这里提醒大家一下。点积也可以看做是一种运算。所以我们把它写<shape id="_x0000_i1034" style="WIDTH: 90.75pt; HEIGHT: 18pt" type="#_x0000_t75" o:ole=""><imagedata src="file:///C:/DOCUME~1/stanly/LOCALS~1/Temp/msoclip1/06/clip_image017.wmz" o:title=""></imagedata></shape> ---------1)。(<shape id="_x0000_i1035" style="WIDTH: 12.75pt; HEIGHT: 14.25pt" type="#_x0000_t75" o:ole=""><imagedata src="file:///C:/DOCUME~1/stanly/LOCALS~1/Temp/msoclip1/06/clip_image019.wmz" o:title=""></imagedata></shape> 在这里表示矩阵相乘, <shape id="_x0000_i1036" style="WIDTH: 48pt; HEIGHT: 18pt" type="#_x0000_t75" o:ole=""><imagedata src="file:///C:/DOCUME~1/stanly/LOCALS~1/Temp/msoclip1/06/clip_image021.wmz" o:title=""></imagedata></shape> <shape id="_x0000_i1037" style="WIDTH: 75.75pt; HEIGHT: 19.5pt" type="#_x0000_t75" o:ole=""><imagedata src="file:///C:/DOCUME~1/stanly/LOCALS~1/Temp/msoclip1/06/clip_image023.wmz" o:title=""></imagedata></shape> 的转置矩阵,下同)。

如果我们标记<shape id="_x0000_i1038" style="WIDTH: 47.25pt; HEIGHT: 18.75pt" type="#_x0000_t75" o:ole=""><imagedata src="file:///C:/DOCUME~1/stanly/LOCALS~1/Temp/msoclip1/06/clip_image025.wmz" o:title=""></imagedata></shape> <shape id="_x0000_i1039" style="WIDTH: 45.75pt; HEIGHT: 18.75pt" type="#_x0000_t75" o:ole=""><imagedata src="file:///C:/DOCUME~1/stanly/LOCALS~1/Temp/msoclip1/06/clip_image027.wmz" o:title=""></imagedata></shape> 变换到视空间中的点和对应的法向量,同理我们也有<shape id="_x0000_i1040" style="WIDTH: 141pt; HEIGHT: 19.5pt" type="#_x0000_t75" o:ole=""><imagedata src="file:///C:/DOCUME~1/stanly/LOCALS~1/Temp/msoclip1/06/clip_image029.wmz" o:title=""></imagedata></shape> --------2

<shape id="_x0000_i1047" style="WIDTH: 263.25pt; HEIGHT: 20.25pt" type="#_x0000_t75" o:ole=""><imagedata src="file:///C:/DOCUME~1/stanly/LOCALS~1/Temp/msoclip1/06/clip_image031.wmz" o:title=""></imagedata></shape> ----------3

联立 123得:

<shape id="_x0000_i1046" style="WIDTH: 285.75pt; HEIGHT: 101.25pt" type="#_x0000_t75" o:ole=""><imagedata src="file:///C:/DOCUME~1/stanly/LOCALS~1/Temp/msoclip1/06/clip_image033.wmz" o:title=""></imagedata></shape>

到这里我们已经得到法向量的变换公式为 <shape id="_x0000_i1041" style="WIDTH: 45pt; HEIGHT: 20.25pt" type="#_x0000_t75" o:ole=""><imagedata src="file:///C:/DOCUME~1/stanly/LOCALS~1/Temp/msoclip1/06/clip_image035.wmz" o:title=""></imagedata></shape> 。其中<shape id="_x0000_i1042" style="WIDTH: 24pt; HEIGHT: 18pt" type="#_x0000_t75" o:ole=""><imagedata src="file:///C:/DOCUME~1/stanly/LOCALS~1/Temp/msoclip1/06/clip_image037.wmz" o:title=""></imagedata></shape> Model View变换矩阵。(注意,不要把投影矩阵也乘上去)。

我们在使用法向量变换的时候最大的一个误区就是直接把Model View变换矩阵<shape id="_x0000_i1043" style="WIDTH: 24pt; HEIGHT: 18pt" type="#_x0000_t75" o:ole=""><imagedata src="file:///C:/DOCUME~1/stanly/LOCALS~1/Temp/msoclip1/06/clip_image037.wmz" o:title=""></imagedata></shape> 当成法向量变换矩阵使用,而且肯定有人还曾经认为这是正确的,他们的理由有两个:一是法向量也是一个Vector。而Vertics表示的也是一个Vector。为什么不是同一个矩阵?二是我用 Model View矩阵去变换法向量的时候,结果看上去的也是正确的。对于第一种理由,我只能告诉你:法向量表示的是一个方向,而顶点表示的是一个位置,是不同的东西。对于第二种理由,主要是大家差不多都忘记了线性代数。如果一个变换矩阵只包含旋转的话,它一定是个正交的矩阵,即:<shape id="_x0000_i1044" style="WIDTH: 62.25pt; HEIGHT: 20.25pt" type="#_x0000_t75" o:ole=""><imagedata src="file:///C:/DOCUME~1/stanly/LOCALS~1/Temp/msoclip1/06/clip_image040.wmz" o:title=""></imagedata></shape> 而且,这时还有<shape id="_x0000_i1045" style="WIDTH: 69.75pt; HEIGHT: 20.25pt" type="#_x0000_t75" o:ole=""><imagedata src="file:///C:/DOCUME~1/stanly/LOCALS~1/Temp/msoclip1/06/clip_image042.wmz" o:title=""></imagedata></shape> 的关系。结合一下可知在一个只包含旋转的变换里。法向量的变换矩阵的确就是Model View矩阵。但是如果变换中包含非正交的因素,如:平移、错切等。那情况就不一样。即使你看到了所谓的正确的结果。那也是近似正确的,至少在理论上,它就是不正确的^_^

Reference :

Real-Time Rendering

心蓝---潘李亮:2003-12-7完成

Stanly Lee.2003-12-7

Email:xheartblue@etang.com

主页:http://gamehunter.3322.net/xpertsoft/

QQ:81496744 欢迎交流

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics