§7.1给对象加入细节
为您接下去要制作的游戏中会使用到Normal Mapping(法线映射) shaders,对表面有很多的结构和小细节的物体,比如管道,电缆这些需要用上百万的才能显示所有细节的情况,使用Normal Mapping(法线映射) shaders能大大改善三维物体的表现(见图7-1 )。You will often see Normal Mapping examples on Internet sites that compare totally ridiculous looking objects and bad textures with a super high resolution Normal Mapped object。我试着use real object from a real game(这本书后面的Racer游戏会用到),因为diffuse纹理有一点阴影效果,所以没有Normal Mapping效果也不错。通过这种方式,您可以不使用Normal Mapping,但物体看上去仍不错。使用Normal Mapping能使物体看起来更好,即使只有1000多边形,看起来也非常平滑。
想要得到更好的效果还能使用Parallax Mapping(视差映射),Offset Mapping或Displacement Mapping(位移映射, Shader Model 4支持,但代价昂贵)。这些技术较为复杂,除了diffuse贴图和Normal Map贴图外还需要额外的height map(高度图)。但使用Normal Mapping已经足够好了。
如果您有一块带shader功能的图形卡,Normal Mapping并不难实现。在老的GeForce 3 (shader1.1版)也能工作,就现今支持Pixel Shader 2.0的硬件可以更好地实现反光,效果会更好。通过前一章的学习你已经有了基本的基础,包括如何创造shader、如何转换顶点、像素如何最终显示在屏幕上。
Normal Mapping 需要额外的纹理。diffuse纹理是用来显示基本的材质,颜色等等。Normal Map纹理通过提供顶点向量添加更多的3D细节。
请注意,如果您打开仙人掌的三维模型的kaktusseg.dds和kaktussegnormal.dds贴图,会发现kaktussegnormal.dds看上去不同,这是因为正Normal Map是压缩的,并已经被Alpha和红色通道反转,这样可以在没失去很多细节的前提下把纹理压缩至1:4,看起来仍不错。More details about this technique in a second - just remember that internally the Normal Map texture looks like the texture in 图7-2;the compressed version just stores the data differently。
计算每个像素的光线是要用到Normal Mapping 纹理中的数据,Normal Map中的每一个像素代表了多边形表面的法线向量。这一数据是储存在正切空间,可参见图7-4。从贴图中的颜色数据获得法线向量要用到公式(each r, g and b value-0.5)/0.5(见图7-3),Normal Map中的RGB颜色数据以浮点数的形式被用在公式里,要将RGB颜色数据转换成浮点数,只需除以255,这在Pixel Shader里是自动完成的。比起位图文件的字节数据,浮点数更容易使用。
Normal Map中最多的颜色是淡蓝(RGB 128,128,255),这意味着大多数向量是向上的,即vector3(0,0,1)。如果整个纹理都是浅蓝色的,这意味着每个向量都朝上,那么,Normal Map将没有任何效果。
这些Normal Map像素通常存放在切线空间,这意味着法线数据和多边形表面是有联系的。这是所谓的切空间,通过每个顶点的切线和binormal向量你才能建立切线矩阵,而binormal可以通过叉乘法线向量和切线向量得到(见图7-4) 。在上一章,你只有每一点的位置,法线和纹理坐标数据,这些数据对Normal Mapping来说是不够的,您至少需要每个顶点的切线矢量去建立这个切线矩阵,如果没有切线数据的话Normal Mapping 图像显示将不正确。
你可以把切向和binormal 向量看成指向下一个顶点x和y方向的向量, but they are still octagonal (in a 90 degree angle) to the normal vector。这意味着,即使您的三维模型没有任何切线数据,您也可以遍历所有顶点自己创建(不容易,但是可行的)。
问题
问题是,往往顶点可用于一个以上的多边形,有时纹理坐标合并得也不好。对diffuse mapping来说这问题不大,因为您只使用法线向量计算光线,但如果你通过切线空间转换每个像素的法线,就要求数据必须配合。这意味最好在三维程序中生成切线数据,三维程序知道如何在Normal Mapping shader中更好地使用哪些切线和输出法线。在vertex shader中你只能访问到目前您正在处理的顶点,而不能访问下一个顶点,或建立一个新的向量指向下一个顶点。这意味着,将有效的切线数据传送到vertex shader(顶点着色引擎)是很重要的。如果你只是定义了支持切线的vertex input structure,也不意味着应用程序能够处理有效的切线数据。通常您在内容管道有.x或.fbx文件,它没有任何切线的数据(见图7-5 ) 。
这意味着你仅有法线数据而没有切线数据,这样就无法为Normal Mapping创建切线空间。对于简单的对象比如这个苹果问题不大,但如何模型有更多的曲线和纹理坐标就会出现显示错误。图7-6显示的就是切线错误的苹果模型。
Asteroids(小行星)!
要建立一个象图7-1一样的3D模型并不容易,一个精细模型,可能会有几百万的多边形,建模往往会花掉很多时间,你可能还会花很多时间优化shader以便能让您的游戏引擎能在同一时间内高帧速率显示许多对象。为了简化问题,你将只使用一些很酷的小行星模型,其中有几百万多边形的精细版本,也有1000多个多边形的低精度版本。这些模型将被用于在下一章的Rocket Commander游戏。
为了进一步优化性能,也制作了500,200,甚至50个多边形的小行星,Normal Maps在高低精度版本中都能用。在性能测试中200个多边形的版本是最有效率的,它几乎和50个多边形版本的一样快,但看起来更好。500个多边形的版本不见得看好多少,特别是对低端电脑上用时较长。因此,我们使用1000个多边形和200个多边形版本的小行星(见图7-7)。
图7-8显示了小行星使用的三个纹理。因为所有小行星模型使用parallax mapping shader(视差映射着色),您需要为每个对象建立一个diffuse(散射),normal(法线),height(高度)贴图。正如前面所提到的,法线贴图被压缩,这意味着将看到红色而不是默认的蓝色法线贴图。压缩的法线贴图是红色的是因为红色通道完全是白色、而储存在原始红色通道中的Alpha通道是不可见。更多详情请参阅下一章的parallaxmapping.fx shader和打开Normal Mapping 纹理。
我在2005年写了一个名为normalmapcompressor的小工具(见图7-9),可以从我的博客http://abi.exdream.com上下载。它可以用来压缩Normal Mapping 纹理,你将可节省75%的磁盘和纹理空间,而质量下降得很少。这是真的很酷,在使用Normal Mapping或parallax mapping时可解决很多显卡内存不足引起的问题。而在过去,你只有diffuse纹理和小如128×128,256×256的分辨率,有时512×512更常见。
以每通道(rgba)32位、未经压缩位图的形式储存的分辨率为128×128的纹理要占128*128*4个字节=64KB的空间,而同样尺寸压缩为dxt1 DDS的文件只有8kB大小,一个JPG文件只有约5到10KB。256 × 256分辨率大小则为128×128的四倍(未压缩256KB,dxt1为32KB,JPEG格式约20KB),若512×512,再次四倍,即便如此,未压缩的贴图大小也仅有1MB。
但今天的纹理尺寸普遍都有1024×1024, 2048×2048,甚至4096×4096更为常见。即使你只用1024×1024的贴图,未压缩diffuse贴图也要占用4MB的空间,因为你也需要Normal Mapping贴图和height贴图实现Shader效果,只是一个单一的纹理就要高达12MB的空间。如果您的游戏使用了数百个不同的纹理,这是完全不切实际的。你必须使用压缩纹理和只有加载需要的数据。这就是为什么console游戏往往会重新加载关卡的数据和一般不要使用非常高的纹理,如果不这样做,对Xbox 360和老的显卡来说会消耗太多显存。
diffuse纹理可以很容易地压缩为dxt1,rgba节省8倍空间,RGB可节省6倍。如果您使用需要Alpha数据的透明物体,您可以使用dxt5,比起未压缩rgba数据可节省4倍。你也许会说“为什么不使用.jpg或.png文件?”“好,您可以为节省磁盘空间使用.jpg文件,但在显存中仍需要解压缩文件并将其存储在显存中。使用dds文件的好处是因为DXT格式更好地兼容了今天的图形硬件和节省显存。
对Normal Maps来说,最主要的问题是DXT压缩算法是针对颜色数据设计的,绿色通道占用大部分的压缩空间,因为绿色的颜色更明显。蓝色通道对Normal Maps并不重要,因为它通常是十分明亮的,(见图7-3) ,但红色通道经过dxt1压缩后看起来就像crap,特别是在Pixel Shader 1.1中,你不能再次将法线归一化,许多情况下向量长度将完全错误,Normal Map的照明看起来有错误,而且很暗(见图7-10)。
It is really hard to explain without switching the compression on and off,屏幕上视觉效果的不同非常明显。Normalmap compressor通过dxt5和将红色通道储存在Alpha通道内的方法解决了这个问题,因为红色通道都是白的,这使得绿色和蓝色有更好一点的压缩比。In the shader you just have to switch the red and alpha channel and you are good to go。如果你仔细观察normalmap compressor (图7-9),你可以看到,红色通道具有最高的variation(左侧的imformation面板),这意味着红色通道具有最不同的颜色观和variation。蓝色通道通常很低。
对于diffuse贴图和高度贴图,您可以使用dxt1。如果你只是使用Normal Mapping,你不需要的高度贴图,可以节省更多的显存。现在1024×1024的diffuse贴图只需要512KB,1MB用于法线(dxt5需要两倍多的空间),和可选的512 KB的高度贴图,如果需要,如果您使用mip-mapping,还要增加25%的空间。用去2~2.5 MB空间,看起来就能与未压缩1024×1024的12 MB大小的纹理几乎一样好了。使用Normal Mapping或parallax mapping效果往往看上去太锐化,你可以像我在Rocket Commander游戏中的那样,用512 × 512的纹理代替1024 × 1024的纹理,能避免锐化问题。令人吃惊的是,Rocket Commander游戏包括两个音道,许多声音效果,5个小行星模型,五个item模型,火箭模型等,纹理和特殊效果和四个关卡,只有不到10MB(译者注:?源文件有60MB,安装文件16MB)。对Xbox 360再大一点,因为不能播放mp3文件,但它还是很不错,以少于15 MB大小的支持1920×1080的分辨率( HDTV ),比大多数Xbox 360上的商业游戏看起来更清晰。
接下来的章节,本书会继续讨论如何使用为自定义的三维数据使用Normal Mapping效果,使用Normal Map后图像看起来很棒,而且因为使用了压缩技术并没用占据太多的纹理空间。
发布时间:2008/9/12 下午1:05:49 阅读次数:9302