学习目标
- 理解为什么需要法线贴图;
- 学习法线贴图如何保存;
- 学习法线贴图如何创建;
- 学习法线贴图中的法向量的坐标系统是如何与物体空间的三角形的坐标系统关联的;
- 学习如何在顶点和像素着色器中实现法线贴图。
1 使用法线贴图的原因
找到一种方法在光滑的平面上,显示出更多的细节(比如粗糙的砖块)。
如果使用曲面细分是可以增加实际的细节的,但是我们还是需要一种方法来指定新增加的顶点的法向量。如果直接根据光照来烘焙纹理,这种方法如果灯光移动后,效果就会出问题。
所以要使用法线贴图:
2 法线贴图
一个法线贴图是一张纹理,其每个通道保存x,y,z坐标值,所以每个像素保存了一个法线向量:
一个单位向量其每个组件值的值域为[−1, 1],我们可以经过下面的运算,将其转换到0-255:
如果要再将其准换回[−1, 1],就对每个通道执行:
我们不需要自己去做压缩操作,PhotoShop的插件可以帮忙把图像转化成法线贴图。但是在着色器中,我们需要自己做解压缩操作:
float3 normalT = gNormalMap.Sample(gTriLinearSam, pin.Tex);
normalT每个组件的值域为0 ≤ r, g, b ≤ 1;所以该函数已经为我们做了一半的解压缩操作,我们只需要再将其转换到[−1, 1]即可:
// Uncompress each component from [0,1] to [-1,1].
normalT = 2.0f*normalT - 1.0f;
Photoshop的插件可以在 https://developer.nvidia.com/nvidia-texture-tools-adobe-photoshop 下载到;还有其它一些创建法线贴图的工具:http://www.crazybump.com/ 和 http://shadermap.com/home/ ;还有一些工具可以从高分辨率模型上创建法线贴图:https://www.nvidia.com/object/melody_home.html 。
如果你要使用压缩纹理格式保存法线贴图,使用BC7 (DXGI_FORMAT_BC7_UNORM)格式是最好的效果,它可以减少由压缩法线贴图造成的错误。对于BC6和BC7格式,DirectX SDK有一