不如醉里风吹尽,又是一天未学习。西山日下雨足稀,又是一周未学习。垂死病中惊坐起,又是一月未学习

最近迷上了骑砍,游戏一玩啥都不管,做什么事都意兴阑珊。

一、法线的概念

三维模型是用一个一个的点构成的,在前面的各种空间变换中,对顶点的位置信息进行了各种计算,但是要想构成一个模型光知道顶点的位置信息是不够的,有一个问题就是,如果我们用几个点构成了一个平面之后,我们该怎么确定哪一面是平面的正面?

法线就是为了确定模型的正面是朝向哪里而存在的。法线(normal)是定义一个点的朝向的信息,它是一个矢量信息,所以也被称为法矢量(normal vector)。当我们变换一个模型的时候,也必须要变换模型的顶点法线,用来在后续的渲染步骤中计算光照,法线可以说是shader中最重要的信息之一,法线出错会导致各种奇怪的显示问题。而如果利用好法线,则可以在shader中实现各种炫酷的效果。

在大部分建模软件当中都可以调出模型的法线信息查看,法线在maya中的显示效果如下:

模型上那些像刺猬一样的线就是顶点法线的显示。

法线有一个特殊的空间为切线空间,切线矢量(tangent vector)也是顶点带有的一个信息。构成一个三维坐标空间的要素是原点和三个互相垂直的矢量。每个顶点有其自身的切线空间,也就是说每个顶点都是自身切线空间的原点,而法线这个矢量就是它的切线空间的Z轴。它的X轴和Y轴是怎么定义的?

在理解切线空间之前必须先理解一下纹理空间,如果想要把一张图片贴到3D模型上面,就必须要把模型的每个位置对应到图片上,等于是把一个物体的皮扒下来展平在图片上。这个图片所在的空间就是纹理空间,纹理空间是一个二维空间,每一个三维模型的顶点都在纹理空间有一个确定的坐标。

在切线空间中,原点就是顶点本身,Z轴就是顶点的法线,X轴和Y轴就是Z轴的两条切线,但是Z轴的切线其实是有无数条的,要如何确定我们要的切线是哪两根切线?一般来说切线空间的Y轴要和纹理空间的Y轴对齐,如上图。而X轴则是由已知的Z轴和Y轴的叉积求出的。

上图示意了当三维模型的UV映射在纹理空间出现变化之后,模型每个点的切线如何变化。

二、法线的变换

一般来说,一个坐标空间下的点可以用同一个4x4变换矩阵变换到另一个坐标空间,一个坐标空间下的绝大部分方向矢量都可以用同一个3x3的变换矩阵来变换坐标空间。比如模型的一个轴向是一个矢量信息,而一个平行光的光照方向也是一个矢量信息,这两个信息在从世界空间变换到摄像机空间的时候,就可以使用同一个变换矩阵来变换。很多时候点和矢量的变换矩阵是相同的,只是点收到平移影响,所以使用4x4变换矩阵,而矢量只需要3x3变换矩阵。对点和切线进行变换时使用的就是同一个矩阵,但是在变换法线的时候则不能和顶点使用同一个矩阵,因为有可能会破坏法线的垂直性。

我们对法线的要求是不论处于任何空间之时,它必须与模型表面垂直,不能随便乱指。空间坐标的变换矩阵影响力就太强,除了平移旋转还有缩放,用过的人都觉得很伤。变换空间时如果是统一缩放,那么最后的效果一切正常,如果有一个轴不能坚定立场,整个模型就像是放错了地方。

此处祭出法宝书,借一张图示意这个效果。

可见空间变换矩阵不仅拉长了你的点,还拉长了你的边。就算是一条矢量,也要把你拉长。

与顶点相同的变换矩阵不能用,吓得我这个学渣不敢动,推导真正的法线变换矩阵的过程知识量太重,越看觉得越发头痛。首先,在坐标空间A中一个点a的法线Na必须要和切线Ta垂直,所以Na和Ta点积的结果为0 。给定点a从坐标空间A变换到坐标空间B的变换矩阵M a->b ,我们已经知道点a的切线Ta和点a使用同一个变换矩阵,所以Ta和M a->b 进行叉积得到在坐标空间B中的切线T b 。

有了坐标空间B中的切线T b以后,就可以找出和T b 的叉积为0(也就是互相垂直)的法线Nb了。

我们想要找到一个矩阵G来直接变换法线Na ,要求得出的结果就是那个和切线T b相垂直的N b 。这个式子可以写成:

在矩阵乘法中有这样一条定律:a·b=(a^T)* b,这里的a^T指示矩阵a的转置。所以有:

又因为定律:

所以:

再根据矩阵乘法的结合律,可以得出:

再根据:“a·b=(a^T)* b,这里的a^T指示矩阵a的转置。”可以得出:

因为Ta 和Na的点积结果为0 ,所以上面式子中的(M a->b ^T ) *G = I 。

根据上面的推导,可以得出结论:使用原变换矩阵的逆转置矩阵来变换法线就可以得到正确的结果。

求变换法线的矩阵G又有几种不同的情景:

  1. 原变换矩阵只包含旋转变换,那么这个变换矩阵就是正交矩阵,根据定律:正交矩阵的逆矩阵就是它的转置矩阵。可以知道G就是原变换矩阵。所以可以直接使用原变换矩阵对法线进行变换。

  2. 变换只包含旋转和统一缩放,则只需要与缩放值k进行计算 : (1/k)Ma->b 来得出法线变换矩阵G。

  3. 变换中包含了非统一缩放,那就必须要老老实实求解逆矩阵来得出G。

Shader学习(9)法线和切线空间的定义和变换演示相关推荐

  1. UnityShader切线空间学习

    此处连接凹凸感文章现在需要应用在立体的形状上 1.可视化切线空间 /// <summary> /// 可视化切线空间 /// </summary> public class T ...

  2. 切线空间、法线贴图、TBN矩阵

    目录 1 法线贴图 1.1 为什么需要? 1.2 怎么做法线映射? 2 切线空间 2.1 为什么需要切线空间? 2.2 切线空间是什么? 2.3 TBN矩阵 2.4 TBN矩阵计算 3 光照计算是在` ...

  3. 处理顶点——通过切线空间的凹凸映射添加逐像素细节

    问题 虽然前一个教程中具有不变法线的平面物体工作良好,但如果对一个曲面或有转角的表面进行凹凸映射仍会遇到麻烦. 主要问题是包含在凹凸映射中的偏离法线是在切线空间中的,这意味着它与默认法线有联系. 为了 ...

  4. Shader学习23——描边+辉光

    研究了一下Post Processing,简单尝试了一下剑辉光效果 image.png 其实shader基本没啥变化,就是在描边的shader基础上加了点位置判断. 首先我们设置好Post Proce ...

  5. UE4 无需切线空间应用凹凸贴图

    Unreal Engine 4.9 照亮环境 凹凸贴图(Bump mapping) 最早由一名图形程序员发明(1978 James Blinn),它通过调整后的着色计算 来创建凹凸表面的假象,无需增加 ...

  6. OpenGL核心技术之切线空间

    笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者;已出版书籍:<手把手教你架构3D游戏引擎>电子工业出版社和<Unity3D实战核心技术详解 ...

  7. Unity Shader - 切线空间的法线贴图应用(T2W W2T)

    法线贴图 法线贴图(或是法线纹理)其实就是一张图片中的RGB通道分别存储着法线方向的纹理(有些为了数据压缩将X,Y存储在RG通道,Z是通过1-dot(xy,xy)来近似计算). 它的由来是因为高模运行 ...

  8. Unity Shader入门精要第四章:学习Shader 所需的数学基础--坐标空间

    Unity系列文章目录 文章目录 Unity系列文章目录 前言 一.4.6.1 为什么要使用这么多不同的坐标空间 二.4.6.3 顶点的坐标空间变换过程 4.6.4 模型空间 4.6.6 观察空间 4 ...

  9. OpenGL 法线贴图 切线空间 整理

    1. What`s Bump Mapping? Bump Mapping通过改变几何体表面各点的法线,使本来是平的东西看起来有凹凸的效果,是一种欺骗眼睛的技术:). 我们知道,如果几何体表面有高低不平 ...

最新文章

  1. windows下rpc框架thrift的环境配置
  2. springcloud 并发_SpringCloud-Zuul高并发请求下的限流处理
  3. 【MaxCompute】学习笔记常用查询sql
  4. 机器学习(三)——预备知识(学习率与激活函数)
  5. [导入]PHP通用分页类
  6. rip协议中周期性广播路由信息的报文_RIP路由理论知识详解(一)
  7. Python语言实现用requests和正则表达式方法爬取猫眼电影排行榜前100部电影
  8. 疏通马桶的工具有哪些 疏通马桶的技巧
  9. C++赋值操作符重载
  10. java 自动发微博_使用node搭建自动发图文微博机器人
  11. python论文降重_论文怕被查重怎么办?你的降重神器来了|简明python教程|python入门|python教程...
  12. window双网卡上网
  13. vuecli3代码压缩混淆
  14. 详解pytorch fold和unfold用法
  15. Java入门 二维数组、一维数组、多维数组的解析(第十三天)
  16. 用户注册及APP使用隐私协议
  17. reshape2揉数据
  18. matlab 画xos函数,振荡积分的数值计算与Matlab实现
  19. 如何查看网页操作中调用的js方法
  20. QUIC 协议是如何在蚂蚁集团落地的?

热门文章

  1. 《Android进阶之光》续作内容简介
  2. 深度阐述数据建模及可视化系统技术方案
  3. css动画(详解带图)
  4. Kali Linux换更新源及更新软件和系统教程
  5. Android 获取手机通讯录信息 — 头像、姓名和A-Z的快速查询
  6. ACM气球膨胀问题C++实现
  7. python 使用random函数实现randint函数的功能
  8. c语言long作用,c语言long类型是什么意思_后端开发
  9. 服务器文件同步异常检测,Sersync实现触发式文件同步
  10. ChatGPT老板撒钱救难:百万美元帮硅谷银行受害公司,不要借条不用承诺,能还时再还...