前面两节内容已经说完了所有的三种变换。也就是说我们现在程序里面既不需要glLookAt(),也不需要gluPerspective(),这些矩阵我们都可以自己写。然后,再用glMultMatrix()来调用这些矩阵,注意一点就是OpenGL是左乘,前面给出的矩阵都是右乘矩阵,所以调用的时候需要转置,摆放的位置也要注意。当然,如果用shader的话,这些函数也就用不到了,矩阵顺序也可以自己定义。这里所有的变换都是作用在顶点(Vertex)上的,但是还有一类数据需要进行变换,那就是顶点法线。我们在计算光照的时候,需要在顶点上设置顶点发现,顶点经过各种变换,法线肯定也要跟着变。不过法线的变化跟顶点有些许的不同,本文就介绍下法线变换。

  首先,我们需要知道法线的几个注意的地方:

  1. 法线向量是需要进行归一化的,它的长度必须为1.0。
  2. 法线向量是表示方向的,跟顶点不一样不是表示位置,所以法线向量只有三个分量,不存在齐次坐标。
  3. 法线向量的变换中,一般只有旋转变换和部分缩放变换。因为法线向量表示方向,平移后不变化,而且法线如果等轴缩放,归一化后也不变化,另外,法线主要是计算光照,透视变换也用不到。

  跟直觉违背的是,法线向量的变换与顶点向量的变换方式是不同的。那么如何变换法线呢?我们首先取出变换矩阵的左上角的3*3矩阵。因为法线向量只需要包含必要的旋转和缩放信息,也可以将物体从模型坐标系变换到眼(相机)坐标系。公式如下:

图1

  我们现在现在看看为何需要求逆后转置。如图2所示,我们如果直接将法线向量乘以M,就会出现中间的这种情况,其法线分布明显与表面不垂直,而最右边的图才是正确变换后的法向分布。

图2

  我们接下来证明一下公式。这里假设某一点处的法向量为n,切向量为t,由两者在曲面上的垂直关系可知:

图3

  假设顶点开始变换,最终的变换矩阵为M,那么变换后的切向量为t'=Mt。切向量可以通过几何分析来验证变换矩阵和顶点是一致的,这里就不详述了。那么我们可以得到变换后的n't'之间的关系:

图4

  我们根据上式可以得到中间两项GTM=I,所以我们得到最终的发现变换矩阵:

图5

  这里就介绍完所有的变换矩阵了,真是一个漫长的过程。其实在这些变换后还有一个视口变换,就是将光栅化后的图像映射到窗口中,但由于这一步时管线内部的操作,这次也就没提了。大家可以试着自己写一下各种矩阵,肯定对OpenGL视图和变换这块更加理解。

详解OpenGL中的各种变换(投影变换,模型变换,视图变换)(完)——法线变换的更多相关文章

  1. jQuery:详解jQuery中的事件(二)

    上一篇讲到jQuery中的事件,深入学习了加载DOM和事件绑定的相关知识,这篇主要深入讨论jQuery事件中的合成事件.事件冒泡和事件移除等内容. 接上篇jQuery:详解jQuery中的事件(一) ...

  2. 图文详解Unity3D中Material的Tiling和Offset是怎么回事

    图文详解Unity3D中Material的Tiling和Offset是怎么回事 Tiling和Offset概述 Tiling表示UV坐标的缩放倍数,Offset表示UV坐标的起始位置. 这样说当然是隔 ...

  3. 【转】详解C#中的反射

    原帖链接点这里:详解C#中的反射   反射(Reflection) 2008年01月02日 星期三 11:21 两个现实中的例子: 1.B超:大家体检的时候大概都做过B超吧,B超可以透过肚皮探测到你内 ...

  4. 详解Webwork中Action 调用的方法

    详解Webwork中Action 调用的方法 从三方面介绍webwork action调用相关知识: 1.Webwork 获取和包装 web 参数 2.这部分框架类关系 3.DefaultAction ...

  5. 【转】详解JavaScript中的this

    ref:http://blog.jobbole.com/39305/ 来源:foocoder 详解JavaScript中的this JavaScript中的this总是让人迷惑,应该是js众所周知的坑 ...

  6. 深入详解SQL中的Null

    深入详解SQL中的Null NULL 在计算机和编程世界中表示的是未知,不确定.虽然中文翻译为 “空”, 但此空(null)非彼空(empty). Null表示的是一种未知状态,未来状态,比如小明兜里 ...

  7. java 乱码详解_jsp中pageEncoding、charset=UTF -8"、request.setCharacterEncoding("UTF-8")

    http://blog.csdn.net/qinysong/article/details/1179480 java 乱码详解__jsp中pageEncoding.charset=UTF -8&quo ...

  8. 详解Objective-C中委托和协议

    Objective-C委托和协议本没有任何关系,协议如前所述,就是起到C++中纯虚类的作用,对于“委托”则和协议没有关系,只是我们经常利用协议还实现委托的机制,其实不用协议也完全可以实现委托. AD: ...

  9. 举例详解Python中的split()函数的使用方法

    这篇文章主要介绍了举例详解Python中的split()函数的使用方法,split()函数的使用是Python学习当中的基础知识,通常用于将字符串切片并转换为列表,需要的朋友可以参考下   函数:sp ...

随机推荐

  1. html5文章 -- 使用 jQuery Mobile 与 HTML5 开发 Web App ——开发原则 | Kayo's Melody

    最近专注研究 jQuery Mobile —— 一款很方便就可以把 Web App 包装成适合 Android 与 iPhone 等触屏移动设备的 Javascript 库,结合 jQuery Mob ...

  2. 我对Java的java.lang.Class这个类的深入理解

    类是对同一类事物的描述,字段具体的值只有到类实例化时才会指定,静态字段除外.所有的类也是同一类事物,用Class这个类来描述.Class类与String.Person等类是同一个级别的.java的字节 ...

  3. extjs Combobox动态加载数据问题,mode:local 还是remote

    var fabircTypeDs = new Ext.data.Store({ proxy: new Ext.data.HttpProxy({ url: 'province.do' }), reade ...

  4. Nova相关命令收集

    1. nova list 2. sudo nova-manage service list 8. 创建/删除浮动IP池 nova floating-ip-bulk-create 192.168.0.2 ...

  5. Excel 中单元格和范围的引用(即访问的表示方法)

    计算机中,无非是数据和数据的处理这两件事.Excel的工作表能存储大量数据,除了这些原始数据,我们还要用函数来处理这些数据,比如求和求积,求平均值,排序等等,并把处理结果也存在单元格里.在Excel中 ...

  6. HDU 1069 基础动态规划+排序

    题意 给出n种立方体石头 当且仅当一块石头的底部宽度长度都小于一块石头的时候才能放在上面 问最高能放多高?石头不限数目 然而同样一种石头采用同样的摆放方式 两快相同石头一定无法进行放置 所以 一块石头 ...

  7. [ZZ] GTX 280 GPU architecture

    http://anandtech.com/show/2549 Now that NVIDIA’s has announced its newest GPU architecture (the GeFo ...

  8. visual 2008中error PRJ0003 : 生成 cmd.exe 时出错

    visual 2008中error PRJ0003 : 生成 cmd.exe 时出错”,   和vs2008 sp1没关系 解决方案:工具—>选项—>项目和解决方案—>VC++目录, ...

  9. 1. Programming in C is fun!

    Programming in C is fun! #include <stdio.h> int main() { printf("Programming in C is fun! ...

  10. artDialog ( v 6.0.2 ) content 参数引入页面 html 内容

    /*! artDialog v6.0.2 | https://github.com/aui/artDialog */ 将页面某一隐藏的 div 的 html 内容传到 artdialog 的弹窗中,并 ...