当前位置: 首页 > news >正文

Unity法线贴图原理理解(为什么存在切线空间?存的值是什么?)

Unity法线贴图原理理解(为什么存在切线空间?存的值是什么?)

  • 写在前面
    • 1、为什么用法线贴图?
    • 2、用什么存法线?
    • 3、法线向量为什么存在切线空间?法线贴图存得是什么?
    • 4、法线贴图为什么会偏蓝?
    • 5、如何生成法线贴图?
    • 6、怎样用法线贴图计算光照?
  • 写在后面

写在前面

最近写Shader使用到了法线贴图,一直没搞懂为什么法线贴图是存在切线空间的?以及法线贴图里到底存的是什么?
看来了网上很多博客以及《Unity Shader入门精要》都没太明白。
我当时很疑惑的点是:法线贴图存储的是模型在切线空间下的法线方向。而切线空间z轴是顶点的法线方向,x轴是顶点的切线方向,y轴由法线和切线叉积的副切线。法线贴图到底存的是什么呢?切线空间都把法线拿去当z轴了,还不所有法线都是(0,0,1)了嘛
最终在https://www.gxlsystem.com/hulianwang-1859689.html中得到了比较合理的解释。
下面是真的上面的引用再加上个人的理解,若有错误欢迎讨论。

1、为什么用法线贴图?

精细的模型虽然光照的效果很好,但是凹凸面太多,导致光照计算量太大。而粗模的凹凸面太少,导致光照效果不好。因为光照效果是受模型法线方向影响的,精模凹凸面多->面的法线方向越多样->光照效果好,粗模凹凸面少->面的法线方向多样少->光照效果不好->导致看起来没有凹凸感。
所以人们想到,能不能把高模的法线存起来用在低模上,从而让低模实现类似高模的光照效果。所以发明了法线贴图用来存高模的法线信息。

2、用什么存法线?

法线向量的3个分量xyz正好对应图片的三通道rgb,所以想到用图片去存法线信息,所以这张存了法线信息的图片就叫法线贴图。

3、法线向量为什么存在切线空间?法线贴图存得是什么?

法线用什么坐标系去存呢?
有三种选择方式:世界坐标系、模型坐标系、切线坐标系
世界坐标系:
法线向量相对于世界原点,那么法线向量与模型本身位置,如果模型换个位置,或则换个场景,就出出错,所以不行。
模型坐标系:
法线相对于模型原点,那么如果模型不动,但某个三角形网格变了,面上的法线向量本应该变了。但是模型原点坐标没变,法线向量是相对于模型原点的,所以法线实际是不会变,这就有问题了。并且由于模型空间下的法线向量是相对于这个模型原点的,不同模型的模型坐标系是不一样的,所以也导致这些模型空间下的法线只能应用于这个模型,换一个模型就不行了。
切线坐标系:
既然世界坐标和模型坐标都不太好,那么人们就想能不能让法线依赖于向量既不依赖于场景又不依赖于模型,而是依赖于模型上的面呢?当面变的时候,法线跟着变。从而让法线始终保持处于这个面的上方。人们为了实现这个目标,提出了切线空间。
坐标系定义:对于粗模 (注意是粗模!!!) 的每个顶点,它都有自己的切线空间,这个切线空间的原点就是该原点本身,而z轴是顶点的法线方向,x轴是顶点的切线方向,y轴由法线和切线叉积而得,称为副切线(bitangent)。
切线坐标系储存的值:
储存的是精模法线向量从模型坐标系转到粗模的切线坐标系的向量。也就是用粗模的切线空间储存精模的法线。

这样,由于每个表面顶点都有自己的切线空间,这个切线空间是以粗模顶点的法线方向为z轴,顶点的切线方向为x轴,副切线为y轴,储存的是精模的法线向量。因此这个精模的法线是相对当前粗模该顶点的切线空间的法线,这里我们假设值为(0,0,1),即精模法线与粗模法线重合(因为粗模法线是z轴嘛)。如果粗模发生变化,这时粗模顶点法线和切线变化,那么这个切线空间变了。此时的(0,0,1)依然代表这个变化后的粗模的顶点法线方向,也就是说你只要知道变化后的粗模的法线方向,那么对应的精模的法线也就是这个法线,那么应用在粗模的光照效果依然是精模的光照效果。
这里我画一个示意图,图上的红绿蓝坐标系就是粗模的切线空间。这里我们假设来自于精模的四个四边形变成粗模的一个四边形。我画的粉色框就是精模的四边形,这时这个四边形顶点的法线就是精模法线向量,然后把这个坐标系放到粗模切线坐标系,此时这个法线向量的值就是法线贴图的值。
在这里插入图片描述

4、法线贴图为什么会偏蓝?

因为法线向量各个分量xyz取值区间是[-1,1],而rgb颜色分量范围是0-1,所以需要映射一下:rgb = (xyz + 1) / 2。
上面提到了法线贴图存的值是精模法线向量从模型坐标系转到粗模的切线坐标系的向量。比如说粗模的三角形数量相对于粗模来说没有减少,也就是粗模和精模是同一个模型。这时因为切线空间的z轴是粗模的法向量,由于假设粗模和精模是同一个模型法线是完全相同的,也就是精模的所有法线向量就是z轴,即值为(0,0,1)。这时的法线贴图所有值都是rgb=(0.5,0.5,1),也就淡蓝色。因此只要粗模相对于精模三角形数量和为没有太大变化,那法线贴图大多数颜色就是(0.5,0.5,1)淡蓝色。

5、如何生成法线贴图?

这个问题也就是再说,如何让精模模型空间下的法线转到粗模切线空间下。也就是我们需要一个变化矩阵让精模法线经过变化矩阵变化的粗模切线空间。
这里直接给结论:从一个空间T变换到空间N的变换矩阵,就是T空间的三个基向量xyz在N空间下的表示。

结论来自https://zhuanlan.zhihu.com/p/361417740

因此从切线空间->模型空间:相当于切线空间中三个基坐标(TBN,T为切线、B为副切线、N为法线)在模型空间三个基坐标上的投影(XYZ)。因此变换矩阵为
在这里插入图片描述
同理从模型空间->切线空间是切线空间->模型空间的转置,因为是逆向操作
在这里插入图片描述
这样我们就得到了从模型空间->切线空间变换矩阵。再用模型空间的法线左乘这个变换矩阵就能得到切线空间的法线了。
注意:因为粗模一个三角面需要对应多个精模的三角面,因此多个法线向量就可以共享一个低模切线坐标系。

6、怎样用法线贴图计算光照?

因为法线贴图是切线空间的,但是光照是在世界空间计算的,因此要计算光照有两种方式。法一:把光照方向和视角法线转到切线空间去计算。法二:把法线从切线空间转到世界空间去计算。
这里我们主要讲法二,把法线贴图中法线转到世界空间去计算光照。
首先我们就要获得从切线空间->世界空间的变换矩阵
切线空间->世界空间:使用法线贴图,如果光照在世界空间中计算,就需要把法线从切线空间转换到世界空间。Matrix = 切线空间三分量在世界空间的表示。
在这里插入图片描述
矩阵再乘上切线空间下的法线,获得世界空间法线。
在这里插入图片描述
对应shader的代码,o.tangent.w是副切线的方向性的。

//粗模顶点法线
float3 worldNormal = mul((float3x3)unity_ObjectToWorld,o.normal);
//粗模顶点切线
float3 worldTangent = mul((float3x3)unity_ObjectToWorld,o.tangent.xyz);
//粗模顶点副切线
float3 worldBinormal = cross(worldNormal,worldTangent)*o.tangent.w;
//切线空间->世界空间的变换矩阵
r.matrixRow1 = float3(worldTangent.x,worldBinormal.x,worldNormal.x);
r.matrixRow2 = float3(worldTangent.y,worldBinormal.y,worldNormal.y);
r.matrixRow3 = float3(worldTangent.z,worldBinormal.z,worldNormal.z);

有了切线空间->世界空间的变换矩阵,我们就只需要把法线贴图的法线向量左乘这个矩阵就能得到世界空间下的法线向量。主要要反映射一下,因为贴图是rgb[0,1]而法线范围是[-1,1]。

//对法线纹理进行采样,取出其值,这是在切线空间的法线
fixed4 bumpColor = tex2D(_BumpTexture,o.uvNormalTexture);
//解出法线纹理,这是对法线纹理的采样结果的一个反映射操作, normal.xy = packednormal.xy * 2 - 1;
fixed3 bump = UnpackNormal(bumpColor);
bump *= _BumpScale;
//得到副切线
bump.z = sqrt(1 - max(0, dot(bump.xy, bump.xy)));
//法线向量从切线空间转到世界空间
bump = fixed3(dot(o.matrixRow1,bump),dot(o.matrixRow2,bump),dot(o.matrixRow3,bump));

这样我的就得到了法线贴图,然后用这张法线贴图去做漫反射光照即可。

fixed3 diffuseColor = _LightColor0.rgb*mainTextureColor.rgb*max(0,dot(normalize(bump),normalize(_WorldSpaceLightPos0.xyz)));

完整代码
见https://blog.csdn.net/iiiiiiimp/article/details/125505828中的Phong光照模型(顶点片元Shader、表面体Shader)
在这里插入图片描述

写在后面

看来一天的博客,才有点弄明白了。由此可见《深海》的图形学技术功底。大家去看看《深海》吧!博主当时哭得好惨!听说12亿才回本!!!
在这里插入图片描述

相关文章:

Unity法线贴图原理理解(为什么存在切线空间?存的值是什么?)

Unity法线贴图原理理解(为什么存在切线空间?存的值是什么?)写在前面1、为什么用法线贴图?2、用什么存法线?3、法线向量为什么存在切线空间?法线贴图存得是什么?4、法线贴图为什么会偏蓝&#xf…...

【JavaWeb】传输层协议——UDP + TCP

目录 UDP协议 UDP协议结构 UDP的特点 TCP协议 TCP协议结构 TCP的特点 TCP的十个核心机制 确认应答 超时重传 连接管理 滑动窗口 流量控制 阻塞控制 延迟应答 捎带应答 粘包问题 异常处理 UDP协议 UDP协议结构 源端口:存储的是发送方的端口号。 目的…...

C++ 中是用来修饰:内置类型变量、自定义对象、成员函数、返回值、函数参数

const 是 constant 的缩写,本意是不变的,不易改变的意思。在 C 中是用来修饰内置类型变量,自定义对象,成员函数,返回值,函数参数。 一. const修饰 普通类型的变量 const int a 7; int b a; // 正确 …...

av 146 002

61. 一个新的敏捷项目经理正试图确定团队该如何执行一个发布计划的进度。哪种工具可以更深入地了解团队的进展? A. 发布计划系统 B. 产品路线图。 C. 看板。 D. 燃尽图 62. 你的项目发起人找到你,让你知道他正在考虑给你项目中的一位高级工程师颁发1000美元的现…...

小红书用户画像 | 小红书数据平台

小红书的用户画像是小红书品牌营销的必备技能,也是小红书推广种草的一个重要前提。通过对小红书用户画像进行分析,对品牌进行精准营销,实现更高的流量转化。 2022小红书粉丝人群画像 千瓜数据在2022年发布的千瓜活跃用户画像趋势报告中分析了…...

【STM32笔记】低功耗模式下GPIO、外设、时钟省电配置避坑

【STM32笔记】低功耗模式下GPIO、外设、时钟省电配置避坑 前文: blog.csdn.net/weixin_53403301/article/details/128216064 【STM32笔记】HAL库低功耗模式配置(ADC唤醒无法使用、低功耗模式无法烧录解决方案) blog.csdn.net/weixin_534033…...

Linux内存分区(swap)

目录 1、使用物理分区创建内存交换分区 2、使用文件创建内存交换文件 当硬件的设备资源充足的话,那么swap是不会被我们的系统所使用到的,所以swap会被利用到的时刻通常就是物理内存不足的情况 我们知道CPU所读取的数据都来自于内存,那么当…...

第六章——抽样分布

文章目录1、统计量的定义2、常用的统计量3、经验分布函数4、正态总体常用统计量的分布4.1、卡方分布4.1.1、卡方分布的定义4.1.2、卡方分布的性质4.2、t分布4.2.1、t分布的定义4.2.2、t分布的性质4.3、F分布4.3.1、F分布的定义4.3.2、F分布的性质5、正态总体的样本均值与样本方…...

蓝桥云课-声网编程赛(声网编程竞赛7月专场)题解

比赛题目快速链接:https://www.lanqiao.cn/contests/lqENT02/challenges/ 让时钟转起来(考点:css:transform) // index.js function main() {// 题解前理解一个东西:// 时针每过一小时,转30 原…...

Java高手速成 | Java web 实训之投票系统

01、投票系统的案例需求 在本篇中,我们将制作一个投票系统,让学生给自己喜爱的老师投票。该系统由1个界面组成,系统运行,出现投票界面,如图所示: ▍显示效果 在这个界面中,标题为:“欢迎给教师投票”;在界面上有一个表格,显示了各位教师的编号、姓名、得票数;其中…...

排序的基本概念

按数据存储介质:内部排序和外部排序按比较器个数:串行排序和并行排序按主要操作:比较排序和基数排序插入排序:基本思想:每步将一个待排序的对象,按其关键码大小,插入到前面已经排好序的一组对象…...

面试笔试资料--Java

这里写自定义目录标题1.同步和异步有何异同?在什么情况下分别使用他们?举例说明1.同步和异步有何异同?在什么情况下分别使用他们?举例说明 1.1概念 Java中交互方式分为同步和异步两种:   同步交互:指发送…...

基于TC377的MACL-ADC General配置解读

目录标题一、MACL-ADC General1.Config Variant与AdcConfigSet2. AdcGeneral3.AdcPublishedInformation二、最终对应达芬奇生成内容一、MACL-ADC General 1.Config Variant与AdcConfigSet Config Variant :变体配置,默认选择VariantPostBuild就好了&…...

error: src refspec master does not match any.处理方案

问题描述 在使用git bash指令将项目上传到github时,总是遇到一些错误无法解决。 下面是我遇到的一个问题 error: src refspec master does not match any. error: failed to push some refs to XXXX.git 原因分析: 错误:SRC ReFSPEC主控器不…...

防火墙有关iptables的知识点

基本概念 什么是防火墙 在计算中,防火墙是基于预定安全规则来监视和控制传入和传出网络流量的网络安全系统。该计算机流入流出的所有网络通信均要经过此防火墙。防火墙对流经它的网络通信进行扫描,这样能够过滤掉一些攻击,以免其在目标计算机…...

路肩石水渠机在施工公路项目中工艺特点的匹配

新建公路路肩项目在目前公路项目中的技术手段和实现方式,大多数依靠机械设备来机械来进行,还有一部分通过人工传统的预制作业和安装模式来进行,两种工艺特点的对比来说对于补充完善建设手段和效果实现有很重要的意义. 其中采用了机械设备进行一次成型制作的过程,按照设计需求匹…...

JS 动态爱心(HTML+CSS+JS)

✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…...

钉钉配置事件订阅(Python)

钉钉配置事件订阅 0.需求分析 需要实现钉钉企业通讯录同步至企业微信通讯录,这就需要用到钉钉的事件与回调 1.配置应用 登陆开放平台 https://open-dev.dingtalk.com/去企业内部开发里面,先创建个应用,后面都借用这个应用来调接口 创建完…...

Linux-Udev机制

一:Udev概述 udev 是一个用户空间的设备管理器,用于为事件设置处理程序。作为守护进程, udev 接收的事件主要由 linux 内核生成,这些事件是外部设备产生的物理事件。总之, udev 探测外设和热插拔,将设备控制权传递给内核,例如加载内核模块或设备固件。udev 是一个用户空…...

ERP是什么?中小商户有必要用吗?秦丝、金蝶、管家婆哪家强?

ERP系统刚开始传入中国的时候,基本上只有超大型或大型企业有条件实施,不过最近几年随着小微企业、中小商户的信息化需求不断增长,ERP软件已慢慢被普遍使用。但是仍然有不少中小商户,还没搞清楚ERP到底是什么,看到大家都…...

pytorch离线安装

windows下离线安装pytorch,很多内网机,无法连接外网,只能下载whl文件进行离线安装下载pytorch,地址https://download.pytorch.org/whl/torch_stable.html我是windows,Python37,没有gpu,所以选择…...

数据结构-算法的时间复杂度(1.1)

目录 1. 算法效率 2. 时间复杂度 2.1 时间复杂度的概念 2.2 大O的渐进表示法 2.3 举例说明: 写在最后: 1. 算法效率 我们该如何判断一个算法的好坏? 衡量一个算法的好坏,是从时间和空间两个维度比较的, 而今天…...

Cygwin安装与Mingw

共同点:window下编译环境 区别:cygwin(gnu windows)模拟Linux编译环境, mingw模拟window编译环境,生成.exe可执行文件 目录 Cygwin安装 一、官网下载 二、双击安装 三、选择安装路径后,到连接方式如图 四、添加连…...

教育舆情监测方案有哪些,TOOM讲解教育舆情的应对与处理?

教育舆情方案是针对教育领域的舆情事件或问题而制定的应对方案。其主要目的是通过有效的信息收集、分析、处理和传播,帮助教育机构或相关组织及时掌握和应对公众舆论的发展趋势,维护良好的舆情形象和声誉,教育舆情监测方案有哪些,…...

c语言操作文件

1、文件缓冲区 文件缓冲区的目的:提高访问效率 提高磁盘使用寿命 刷新就是将当前缓冲区数据全部提交。 不刷新时,程序在崩溃时缓冲区内容无法输出(有些情形会带来错误) 文件缓冲区的四种刷新方式 行刷新(遇到换行符…...

【C语言】初识指针

目录 一、指针是什么 二、指针和指针类型 三、野指针 四、指针运算 五、指针和数组 六、二级指针 七、指针数组 一、指针是什么 指针就是内存地址,指针变量是用来存放内存地址的变量,在同一CPU构架下,不同类型的指针变量所占用的存储单元长度…...

FFMPEG自学一 音视频解封装

一、音视频包含哪些数据对于一个mp4文件我们可以通过音视频分析软件打开查看内部信息。从两图可以看出mp4文件一般包含 音频流 视频流等。对于上面的字段大致分析如下Format编码方式AVC现在大部分视频都是这种编码方式,即H264。CodecId编码器idavc1H264封装有2种格式…...

HoloLens 2 丨打包丨MRTK丨Unity丨新手教学

HoloLens 2打包流程制作前言开发工具介绍Visual Studio 2019MRTK插件或示例程序下载打包流程介绍Unity操作修改Visual Studio修改Hololens 修改Hololens 密码忘记总结前言 提示:今日功能介绍 使用 MRTK制作hololens 2的打包流程制作的新手教学。 开发工具介绍 这…...

AcWing语法基础课笔记 第四章 C++中的数组

第四章 C中的数组 程序 逻辑 数据,数组是存储数据的强而有力的手段。 ——闫学灿 一维数组 数组的定义 数组的定义方式和变量类似。 数组的初始化 在main函数内部,未初始化的数组中的元素是随机的。 访问数组元素 通过下标访问数…...

UTF小结

运行测试 编辑测试 运行模式:程序集Platform平台选择 Any Platforms编辑模式:程序集Platform平台选择 Editor 特性 Test、UnityTest特性:测试方法需要添加Test或UnityTest特性,测试方法是公有的SetUp、TearDown特性&#xff1a…...

简约网站模板/app怎么开发出来的

“便笺”是Win10里内置的一项小功能,不过很多人对它并不了解。其实Win10的“便笺”(Sticky Notes),无论在颜值还是功能性方面,都可以堪称同类软件中的佼佼者。尤其是1809版之后的便笺3.0,更是融入了很多新功能,妥妥的记…...

中小型网站建设怎么样/十大短视频平台排行榜

http://www.cocoachina.com/ios/20140409/8127.html...

广州 建设 招聘信息网站/我赢网seo优化网站

🍅 作者简介:哪吒,CSDN2021博客之星亚军🏆、新星计划导师✌、博客专家💪 🍅 哪吒多年工作总结:Java学习路线总结,搬砖工逆袭Java架构师 🍅 关注公众号【哪吒编程】,回复1024,获取Java学习路线思维导图、大厂面试真题、加入万粉计划交流群、一起学习进步 目录 一…...

高端企业网站制作/饥饿营销案例

猫咪智能检测仪01产地:德国设备简介运用五色光谱原理,通过100W临床数据,360种皮肤解决方案,从皮肤病理维度、敏感维度、皱纹维度、毛孔维度、色斑维度、粉刺维度、紫质维度7大问题维度进行AI分析,并提供护肤解决方案。…...

门户网站建设 请示/外贸网站建设流程

黄河科技学院课程编号代码设置及说明.doc黄河科技学院课程编号代码设置及说明为了配合专业培养计划的修订工作,便于计算机管理,现将我校所开的全部课程(包括必修课、选修课、辅修专业所开课程以及课外培养项目)进行统一编号,具体编号要求和说…...

杭州网站建设设计制作/关键词百度指数查询

被tkj大爷艹爆了5555整套模拟赛都是神仙思路题 那么这题题解 还有一个神仙做法,zory巨神在考场上找规律AC,自己都不会证。。我证明了一下(然而这货还是不认可自己的做法) 按照分割点的思路,我们for循环一次,每次找到比当前点小且最…...