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)
联立 1,2,3得:
<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 欢迎交流
分享到:
相关推荐
平方取中法是一种在计算机图形学中用于确定两点间中点的快速算法,特别是在浮点数运算时。这种方法主要用于提高效率,避免了浮点数除法的运算,因为除法通常比乘法和加法慢。它适用于任何需要计算两个坐标点中点的...
4边疆危机与中法战争.pptx
matlab平方取中法、线性同余法、组合发生器生成三种伪随机数,并进行均匀性检验
通过研究“normals.zip”中的源代码,我们可以深入理解OpenGL中法线处理的实践应用,以及如何与光照模型、纹理映射和其他图形特性相结合,创建出逼真的3D场景。同时,这也是提升商业软件中图形用户界面(GUI)质量和...
### 知识点总结 #### 一、Java基础:类的定义与操作 **知识点概述:** 本部分内容涉及Java中最基本的概念之一——类的定义及其常用操作方法。具体包括类的创建、对象的实例化、属性与方法的定义以及一些基本的类...
总之,这篇教程深入浅出地讲解了Unity3D Shader中法线贴图的应用,适合对Shader有一定基础的Unity3D开发者进一步提升技能。通过学习,读者不仅可以掌握法线贴图的实现,还能理解自定义光照模型和Shader的编写,为...
标题和描述涉及的是一个纪念中法建交50周年的活动报名表,标签提及"中法",而内容主要是关于活动的参与方式、个人信息收集、费用标准以及付款详情,这些都是组织活动和财务管理的范畴,不属于IT专业知识。...
谱写新常态下中法经济合作新篇章:中法经济合作前景分析精品报告2020.pdf
北航中法工程师学院Bienvenue.pptx
纪念白求恩中法对照版.doc
《中法礼仪文化差异探析》 中国与法国,两者都是拥有深厚文化底蕴的国家,各自在礼仪方面都有着独特的规范和传统。中国的礼仪源自儒家文化,强调尊重长辈、谦逊有礼,而法国的礼仪则体现着浪漫与尊重个人的特质。...
中法战争、甲午中日战争.pdf
揉中法足三里最佳按摩方法是一种源自少林的基本功,它强调的是通过练习来强化气与筋骨的结合,从而达到“肌肉若一”的状态。这种方法不仅关注气的修炼,也注重筋膜和骨骼的锻炼,认为两者是相互促进的。《易筋经》中...
### 中山中法供水有限公司生产监控系统改造介绍 #### 改造背景与需求分析 中山中法供水有限公司作为中山市的主力供水企业,其供水能力高达每日50万立方米,承担着重要的供水任务。该公司的生产监控系统自1999年...
简评韩非法治思想(中法史).doc
未来,深化中法高等教育交流的关键在于不断创新合作方式,拓宽合作领域,比如加强职业教育和继续教育的合作,推动产学研一体化,促进创新创业教育,以及在新兴学科如人工智能、大数据等方面建立更多的合作平台。...
有想法走中法项目(收集结果).numbers
协商民主语境下中法立法协商比较分析.docx