如何制作法线图 step-by-step

时间:2024-03-11 17:34:36
看了某风的文章后不知道大家是不是对法线图(normal map)和深度图(depth map)的制作感到困惑呢?这里我就简单的说一下它的制作方法好了:



相关知识:
所 谓的法线或是深度图既是指那些专门用来存储材质表面的法线信息和深度信息所用到的贴图(Texture),无论你使用什么样的格式作为一个模型的材质 (jpg,bmp,png......)最终都会先进行解压在按照一个统一的颜色表达格式读入显卡,最终转变成段显存上的数据。很多游戏(64K的那个变 态比赛除外)都会为了减少读盘时间使用未经压缩的可以直接读取到显存的一种格式来存储,其中一个就是dds文件。dds文件中每一个像素的信息同显卡中表 述像素数据的格式完全一致,那就是一个float型的四维向量,每个分量表达的就是我们熟悉的RGBA颜色通道(如果你连这个都没听过的话那我就只能 orz了)。稍微提一下的就是dds也分各种格式,不同的格式为各个颜色通道分配了不同的比特数,例如有一个R32F单通道类型的dds中除R以外的所有 通道居然根本就没有分配到比特,如果你取值的话只能拿到0。还有就是整个这个向量所使用的比特数也有区别,最长的现在显卡可以支持的是128,越高的比特 数就能获得越高的精度和表达范围。
对于法线/深度贴图,一般使用32位,每通道8位的DXT5纹理格式就可以了——DXT5是一种经过压缩的 dds文件格式,但它却可以在硬件级别上进行解压,速度快的吓人。我们使用RGB三个通道分别存储法线在该贴图的切向空间下的单位化向量的三个分量,而最 后一个Alpha通道用来保存深度。
那么言归正传,让我们开始制作法线/深度贴图吧。

方法一:通过深度图生成法线图

Step1 配置导出工具:
如果想方便的将图片导成dds文件,nVidia的PhotoShop插件是个不错的选择,它恰好(之所以使用恰好是因为当初装它完全是为了导出dds而已)也支持通过深度图导出法线图,而且功能也很强大(最重要的是——免费)。
下面是该工具主页的地址,里面提供了下载地址:
http://developer.nvidia.com/object/photoshop_dds_plugins.html

Step2 绘制深度的灰度图:
先 把背景调成黑色,然后基本就是把越凹起来的地方画的越白,除了可以直接用画刷一点点按照原来图片的纹理自己手绘外,还有一个方法就是先将整张图片转为灰度 图(Image->Adjustments->Desaturate),然后调整对比度和亮度(Image->Adjustments ->Brightness/Contrast)也可以提取出类似于深度的纹理,再进行手动的修改就可以了,如果发现凹凸反了的话直接做个反色就行 了。这个方法对于制作一些带杂点的深度图非常好用。

注意: 灰度图中越白的地方说明这里的高度值越高,也就是越凹,在浏览该贴图时这个位置就越不透明,在带有颜色通道显示时该处颜色就越深,这两个状态看上去的效果 完全相反,所以需要注意。具体凹多少需要通过Shader中的参数控制,这里最后在Alpha通道中存储的是一个0.0f(纯黑)~1.0f(纯白)的 值,一般是用它乘上那个参数。当你使用DirectX Texture Tool来查看一个贴图的深度时(View->AlphaChannelOnly),你就会发现凹下去的地方是白的,象下面这张。
其实所谓的凹凸贴图应该是“凹贴图”,由于遮挡的逻辑是在PixelShader中进行,也就是光栅之后,虚拟位移无法跨图元的进行遮挡(听说DX10已经可以干这事了),于是就只能往下凹了,如图:
自己绘制时不用担心边缘颜色过渡的不圆滑导致法线变化不连续,导出工具可以在生成法线贴图时对深度图进行过滤,这里就是相册那架飞机机身上的条文的深度图,直接用线条工具对着以前的机身贴图画出来的,非常简陋。


Step3 导出生成dds:
注意:如果你要导出的dds是DXT纹理压缩的,那么它的长宽(单位:像素)必须是2的幂次方,也就是0,1,2,4,8,16......,而且长宽必须相等。
安装了PS的插件后你就可以在Fiel->Save As->Format中找到dds这个格式了,如图:
点保存后就会弹出新的窗口,不要被这个一大堆按钮的窗口给吓到,里面平常用的到德按钮也就这些我用蓝色方框圈出来的部分,如图:

关于MIPmaps这要说的就太多了,有兴趣的话大家自己查吧。在左上方的下拉框中选择我们需要使用的贴图格式后,点击NormalMapSettings按钮,打开以下窗口:
首先要做的就是把左上方的Convert to Tangent......那个选项打开,这样就告诉插件我们需要导出的是法线图而不是颜色了。
平时我们需要经常调整的是Height Generation中的那些属性。
注意:具体R和G是表达哪个方向总共和两个东西有关:
1.导出
模型时所生成的切向空间和纹理空间的关系。
2.Shader中使用的切向空间和纹理空间的关系和对R,G两个值的使用方式。

切向空间和纹理空间的关系,注意UV轴同Tangent以及Bin两轴方向不一定是一致的

为了避免方向错误,最简单的方法就是先制作一个简单的发现贴图放到程序中检查是否正确,看看哪个反了就把相应的调换或者取补就行了。如果你把Alpha值理解为高度图(凸的程度),那么
R和G的方向都取反就可以了
相关设置都可以通过左面的CheckBox完成,通过那个Wrap选项来相互替换R,G中的数据,也可以用下面的两个选项反转R或G的值(取补)。例如之前某风的文章中使用的那块石头就是在变换坐标系后对G取了负。
MinZ和Scale中的数值都是一些经验值,劝大家不动为妙,一般也用不上修改这些参数,以免法线角度过低导致效果变得很诡异。
现 在我们再看一下那个FilterType的那一大堆RadioButton。里面决定了生成每一个像素的法线信息所用的周围的高度信息的范围,这个值越 大,边缘就会过渡的越圆滑。下面是两个例子,左侧是使用4*4的取样,右面是9*9的,你可以看到边缘的厚度和锋利程度有明显的区别。

最后在点击Save导出前,不要忘记先点那个2DPreview预先查看一下结果在开始正式导出。

方法二:高模转低模

最常用的方法,很多时下的建模工具都自带了这方面的插件,也有工具例如nVidia的Melody(http://developer.nvidia.com/object/melody_home.html)专门用来干这事,相关的文章和文档有很多,我就不多废话了。