【Unity Shader】(6)凹凸映射 实现材质的 法线贴图 和 高度图(Normal Map And Height Map)

本文详细介绍了在Unity Shader中如何使用法线贴图和高度图来实现凹凸映射。通过凹凸映射的概念、两种方法(高度纹理和法线纹理)以及在切线空间和世界空间下计算法线的步骤,展示了如何在Shader中添加属性、定义结构体、编写顶点和片元着色器,从而达到增强模型细节的效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在Unity Shader中用法线贴图和高度图来实现凹凸映射


1、凹凸映射概念

凹凸映射,在不改变顶点位置的前提下,修改模型表面的法线方向,为模型提供更多的细节。

2、凹凸映射的 2 种方法

  • 高度纹理(Height Map)

使用一张高度纹理来模拟表面位移(Displacement),然后得到一个修改后的法线值。此方法也叫做高度映射(Height Mapping)
颜色越浅,越向外凸;颜色越深,越向内凹。能明确表面的凹凸信息,缺点是计算复杂。

  • 法线纹理(Normal Map)

使用一张法线纹理来直接存储表面法线。此方法也叫做法线映射(Normal Mapping)。用于存储表面的法线向量,法线向量的取值范围为 [ -1 , 1] 。但是像素分量的取值范围是 [ 0 , 1],因此需要进行以下两个映射:

1

  • 贴图属性

  • UnpackNormal是unity内置的函数(在后面⑥定义片元着色器中会出现)。当我们把贴图纹理设置为Normal map类型时,该函数可以得到正确的法线方向。
    不仅如此,Unity还可以根据不同平台来调整Normal的细节,使用UnpackNormal函数针对不同压缩格式对法线纹理进行正确采样。(目前存在DXT1、DXT5、DXT5nm的格式,DXT3以及被弃用——Tech-Artists
    可以在UnityCG.cginc之中找到UnpackNormal的具体定义:

inline fixed3 UnpackNormal(fixed4 packednormal)
{
   
#if defined(UNITY_NO_DXT5nm)
    return packednormal.xyz * 2 - 1;
#else
    return UnpackNormalmapRGorAG(packednormal);
#endif
}

代码中可以看到我们可爱的Unity并不能识别除了DXT5nm以外的贴图格式,因此翻阅官方文档然后直接Ctrl-F搜索DXT得到如下结果:

5
说明在unity之中可以有2个选择,包括XYZ和DXT5nm,且更改法线编码时,最好直接在Unity的项目设置中,而不是在CG Shader代码中,否则解码成本会增加。

  • 根据下图可以看到,如果我们把类型设置为Normal map,将会出现Create from Grayscale的选项。这个选项的主要作用是可以将我们的先前讲到的 高度图 转换为 法线贴图,方便我们进行法线处理。
    不仅如此,Unity给予了我们两种滤波器:
    ①Sharp——使用Sobel滤波来生成法线
    ②Smooth

4

3、法线纹理的坐标空间

  • 模型空间的法线纹理(Object-Space Normal Map)

对于先前的纹理映射和纹理贴图之中,我们可以直到,要在CG语言中实现相应效果,不可或缺的是纹理的坐标空间(是ObjectSpace还是WorldSpace?)。而对于法线纹理的坐标空间来说,有个直接点的想法是——将修改后的模型空间中的表面法线存储在一张纹理中。(这样一来就可以结合前面“纹理贴图”一样实现凹凸效果。代码部分会加以证明。)这种纹理被称为——模型空间的法线纹理(Object-Space Normal Map)。

  • 模型顶点的切线空间(Tangent Space)

然而,实际上我们真正使用的是——模型顶点的切线空间(Tangent Space)。具体解释如下:
对于模型的每一个顶点,都有属于自己的切线空间,这个切线空间的原点就是顶点本身。
Z轴是顶点的法线方向 n
X轴是顶点的切线方向 t
Y轴是由顶点的切线和法线叉积而得

2



代码开始

在切线空间下计算

① 在Properties属性下添加Bump法线纹理的属性,以及用于控制凹凸程度的属性
Properties{
   
	_Color("Base Color",Color) = (1,1,1,1)
	_MainTex("Main Tex",2D) = "white" {
   }
	_BumpMap("Normal Map", 2D) = "bump"{
   }
	_BumpScale ("Bump Scale",Float) = 1.0
	_Specular("Specular",Color) = (1,1,1,
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值