前面两节内容已经说完了所有的三种变换。也就是说我们现在程序里面既不需要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. QT快捷键

    F1使用方法:选中某一类或函数,按下F1,出现帮助文档 F2使用方法:选中某一类或函数,按下F2,迅速定位到该类或函数声明的地方或被调用的地方 Ctrl+鼠标滚轮的使用方法:按住Ctrl,使鼠标滚轮旋 ...

  2. Ctrl+Shift+F12切换最大化编辑器

    常用快捷键(keymaps:Default情况下) Esc键编辑器(从工具窗口) F1帮助千万别按,很卡! F2(Shift+F2)下/上高亮错误或警告快速定位 F3向下查找关键字出现位置 F4查找变 ...

  3. 短语密码(blowfish_secret)的设置

    简单的说,phpmyadmin就是一种mysql的管理工具,安装该工具后,即可以通过web形式直接管理mysql数据,而不需要通过执行系统命令来管理,非常适合对数据库操作命令不熟悉的数据库管理者,下面 ...

  4. 【转】Windows7系统下硬盘安装全新更高版本Windows7

    原文地址:http://jingyan.baidu.com/article/656db918aee053e381249c06.html 1.下载windows7 7600 ISO镜像(RC或RTM), ...

  5. ps命令交叉编译

    busybox中的ps命令是针对于嵌入式的,其中一些选项并不完整.因此需要将源码下载下来,进行交叉编译 官方下载地址 github下载地址 含有configure,我在此使用的是这个源码包,官方的包在 ...

  6. [IT新应用]存储入门-文件级存储及块级别存储的选择

    http://www.techrepublic.com/blog/the-enterprise-cloud/block-level-storage-vs-file-level-storage-a-co ...

  7. 设计和实现OLAP解决方案

    设计和实现OLAP解决方案   第一讲 简介首先,啥叫数据仓库? 数据仓库就是数据的仓库!用外文说叫Data Warehouse,简称DW. 是不是哐当倒下一片啊,要不咱换个专业点的说法? 数据仓库是 ...

  8. C#winform使用+=和-=订阅事件和移除事件订阅

    1.C#winform中使用+=和-=订阅事件和移除事件订阅 2.可以使用+=给一个控件订阅多个事件,触发事件时按顺序执行,直到使用-=移除事件订阅为止.

  9. CSS布局总结

    三种布局模型: 1.flow 标准流布局 2.float 浮动布局 3.layer 层叠布局 关于(flow) 标准流布局 浏览器默认的布局方式就是标准流布局.对于标准流布局下的的块元素和行内元素的特 ...

  10. Converting from Decimal Notation to Binary Notation for Fractions

    COMPUTER ORGANIZATION AND ARCHITECTURE DESIGNING FOR PERFORMANCE NINTH EDITION Therefore, the conver ...