(转)法线贴图Nomal mapping 原理

本文介绍了法线贴图技术的基本原理及应用。通过记录贴图上各点的法线方向,实现低成本高质量的3D渲染效果。适用于游戏开发与CG动画制作。

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

法线贴图多用在CG动画的渲染以及游戏画面的制作上,将具有高细节的模型通过映射烘焙出法线贴图,贴在低端模型的法线贴图通道上,使之拥有法线贴图的渲染效果,却可以大大降低渲染时需要的面数和计算内容,从而达到优化动画渲染和游戏渲染的效果。
 
现在好多3d网游都没有法线贴图啊,呵呵,《giant》就没有。

维基百科:
法线贴图

法线贴图
 什么是法线贴图技术呢?这是一种用来实现3D效果的一种技术,要想理解这种技术还请您听我慢慢道来。

  我们知道,在游戏中经常会有这样的情况,就是一个平面——这个平面在现实中并不是一个“平”面,例如砖墙的表面带有石质浮雕等等。这样的情况如果要求游戏开发人员将复杂的3D细节都做出来是不现实的,因为即使不计较在建模时候的复杂度,过多的3D细节也同样会大量消耗显示芯片的性能,让游戏根本没有可玩性。


                如何利用贴图实现凹凸效果呢?

  可行的方法就是将这个平面用一个贴图覆盖,用贴图的纹理实现一定的凹凸效果。但是这种方法实现的效果并不是很好,因为如果视角一变化,看起来就会像一张简单的画有图案的平面了。

  后来,聪明的游戏开发者想出了一种方法,就是在贴图过程中对贴图进行一定的处理,从而保证了在视角变换以后仍然保证有较为明显的凹凸效果。

  光与影,法线贴图技术的物理学基础

  我们知道,人之所以能够对景物看出立体感的主要原因是因为人有两只眼睛。两只眼睛看的景象是不同的,所以人们才能分辨出立体感来。但是,由于电脑的屏幕是一个平面,分辨3D效果就只能靠光影效果来实现了。

  举个简单的例子,这就像我们画素描的时候,为了不让一个球体看起来像是一个圆圈,必须让球体的一些区域是亮的,一些区域是暗的。而且从亮部转向暗部的时候是一个均匀的按照物理模型特点的过渡,这样画出来的球体才像个球体,电脑为我们绘制的过程也是一样。


因为有明暗,我们才能将平面理解成立体

  基于这个道理,我们就不难理解可以通过贴图局部的亮暗变化来实现假的3D效果。换一种说法就是说我们可以通过在贴图上的局部做一些亮暗的变化来做到一种假的3D效果。


光照因角度不同而呈现不同的明暗

  那么如何实时的对贴图进行转换呢?如果要实现虚拟的光影变换,我们最起码需要知道在一个平面上真正的凹凸的情况,这样才能让显示芯片进行运算,生成一种假的凹凸的效果。

  显然,记录真实的凹凸模型是得不偿失的——如果那样的话就没有任何意义了,我们需要用一种非常简单的方法来记录一个贴图的凹凸情况,于是就诞生了一种全新的方法,法线贴图技术。

  接下来,我们再回到我们刚才谈到的法线贴图的话题上。

  法线贴图就是记录了一个需要进行光影变换的贴图上的各个点的凹凸情况的贴图,显示芯片根据这个贴图的内容,来实时的生成新的有过光影变化的贴图,从而实现立体效果。

  那么,究竟是怎样利用法线贴图记录一个平面或者说是一个贴图的凹凸情况呢?我们知道,物体表面产生明暗变化的直接原因,就是光线照射角度的不同,光线垂直于平面的地方就亮,光线斜射到平面的地方就暗,光线照不到的地方就更暗(应该是黑色,但是由于环境光照所以不会有阴影是真正的黑色)。

  借色彩之值存法线之向,巧妙的存储

  学过初中物理的朋友一定还都记得,表示光线射向平面的角度时通常使用光线和该点法线角度来表示。这也就意味着,如果我们将一个贴图上所有点的法线记录起来的话,就不难再利用这些信息实现后期的假的凹凸效果了。

  记录这些法线的载体就被我们称为法线贴图。为什么称之为贴图呢?我们知道,一条法线是一个三维向量,一个三维向量由X、Y、Z等3个分量组成,于是人们想出了一个聪明的方法,就是以这3个分量当作红绿蓝3个颜色的值存储,这样的话就生成一张新的贴图了,这就是法线贴图的来历。


采用色彩通道存储法线向量

  法线贴图其实并不是真正的贴图,所以也不会直接贴到物体的表面,它所起的作用就是记录每个点上的法线的方向。所以这个贴图如果看起来也会比较诡异,经常呈现一种偏蓝紫色的样子。


法线贴图的生成过程


Doom3中的一张纹理贴图和这张贴图对应的法线贴图

  『小提示-05:事实上,真正的法线贴图并不是记录贴图上每个点的法线的绝对角度,而是记录的是相对于平面的一个差值。这样的话,随着平面的3D变换都能够实现即时的法线运算了。』

  传统纹理压缩,法线贴图不再适用

  采用法线贴图技术的优势就是利用很少的资源实现了效果非常好的凹凸效果,而且可以利用我们在开篇的时候提到的纹理压缩技术对法线贴图进行压缩,进一步节省资源。


前面的那张圆球图案的法线贴图

### 用法和参数说明 `torch.normal()` 是 PyTorch 中用于生成服从正态分布的随机数的函数。根据不同的参数组合,可以灵活地控制均值、标准差以及输出张量的形状。 #### 参数说明 1. **mean**:表示正态分布的均值。可以是一个标量(float)或一个张量(Tensor)。如果是一个张量,则每个元素将作为对应位置上的随机数的均值。 2. **std**:表示正态分布的标准差。同样可以是一个标量或一个张量。如果是一个张量,则每个元素将作为对应位置上的随机数的标准差。 3. **size**:定义输出张量的形状。只有在指定 `mean` 和 `std` 为标量时,才需要提供此参数。如果未提供,输出张量的形状将与 `mean` 和 `std` 的形状一致 [^2]。 4. **generator**:可选参数,用于指定一个随机数生成器。可以通过设置种子来实现结果的可重复性 [^3]。 5. **out**:可选参数,用于指定一个输出张量,生成的结果将存储在此张量中 [^3]。 #### 使用方式 - **单个随机数生成** 如果希望生成一个服从特定均值和标准差的单个随机数,可以直接传入 `mean` 和 `std` 的标量值,并通过 `size=(1,)` 指定形状: ```python import torch random_value = torch.normal(mean=0.0, std=1.0, size=(1,)) print(random_value) ``` - **张量形状匹配的随机数生成** 当 `mean` 和 `std` 是张量时,输出张量的形状会与这两个张量的形状保持一致。例如,创建一个形状为 (3, 3) 的张量,其中每个元素服从均值为 0、标准差为 1 的正态分布: ```python mean_tensor = torch.zeros(3, 3) std_tensor = torch.ones(3, 3) random_tensor = torch.normal(mean_tensor, std_tensor) print(random_tensor) ``` - **固定形状的随机数生成** 如果需要生成特定形状的张量,且 `mean` 和 `std` 为标量,则必须使用 `size` 参数指定形状。例如,生成一个形状为 (2, 2) 的张量: ```python random_value = torch.normal(mean=0.0, std=1.0, size=(2, 2)) print(random_value) ``` - **使用随机数生成器** 为了确保实验的可重复性,可以使用 `generator` 参数并设置固定的随机种子。例如,使用 `manual_seed(42)` 来初始化生成器: ```python generator = torch.Generator().manual_seed(42) random_value_with_generator = torch.normal(mean=0.0, std=1.0, size=(2, 2), generator=generator) print(random_value_with_generator) ``` - **指定输出张量** 可以通过 `out` 参数将生成的随机数直接写入预先分配好的张量中。例如: ```python out_tensor = torch.empty(3, 3) torch.normal(mean_tensor, std_tensor, out=out_tensor) print(out_tensor) ``` #### 特例 当仅提供一个标量值作为 `mean` 或 `std` 时,该值会被共享到所有生成的随机数中。例如,以下代码生成了一个形状为 (10,) 的张量,其中每个元素的均值和标准差分别为 1 到 10 和 1 到 0.1: ```python torch.normal(means=torch.arange(1, 11), std=torch.arange(1, 0, -0.1)) ``` 输出结果类似于: ``` 1.5104 1.6955 2.4895 4.9185 4.9895 6.9155 7.3683 8.1836 8.7164 9.8916 [torch.FloatTensor of size 10] ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值