一、概述html
上一篇博客,3D游戏经常使用技巧Normal Mapping (法线贴图)原理解析——基础篇,讲了法线贴图的基本概念和使用方法。而法线贴图和通常的纹理贴图同样,都须要进行压缩,也须要生成mipmap。可是因为法线贴图存储的是法线信息,压缩和生成mipmap的方法天然会有所变化。app
如今已经许多用于法线贴图压缩和生成mipmap的工具,大部分商业游戏引擎也集成了相关方法,只须要点几下鼠标就能够完成。本文仅针对法线贴图的纹理压缩和mipmap的方法进行原理性的说明,至于在具体的工具中如何操做,能够参看相关工具的说明文档。工具
法线贴图压缩的中文资料仍是比较多的,也不太复杂;可是生成mipmap的方法中文资料很少,《Real-Time Rendering 3rd》讲解的比较详细,本文的这部份内容主要来源于这本书,若是想详细了解的,能够看原书,网上有电子版。spa
二、法线贴图的压缩3d
传统的jpg等压缩方式解压时间太长,且压缩比不固定,因此在实时渲染中通常采用DXTC及其改进方法,简单来讲,就是把4*4的像素当作一个Block,对其进行简化表示,详情参见百度百科http://baike.baidu.com/view/736449.htm。因为法线贴图存储的数据并非RGB信息而是法线方向,因此须要在通常纹理压缩的方法的基础上进行必定的改变。orm
压缩的第一步很简单,因为归一化的法线长度为1,且在切线空间下,法线的z份量不可能为负数,因此只须要存储x和y值便可。本文的压缩方法在这一步压缩的基础上,利用现有的纹理压缩方法,进行进一步压缩。htm
在支持DirectX10的显卡上,可使用BC5格式进行压缩。BC5的压缩方法内存状况如图1所示,该格式有两个颜色通道(R和G),每一个通道使用两个1Byte的值来表示,每一个像素使用3Bit在这两个颜色值之间进行插值。将法线贴图中每一个法线的x和y值利用BC5格式进行压缩,如图2所示。对每一个Block(16个像素)存储x的最大、小值和y的最大、小值,而后每一个像素利用3Bit进行插值,至关于在图2右图所示的8*8区域内取样(为了简化表示,图2只画了4*4点)。blog
图1 BC5压缩方法游戏
图2 法线贴图压缩示意图,右图框内应该是8*8个点,为了画图方便简单表示为4*4ip
对于不支持DirectX10的显卡,可使用DXT5格式进行压缩(DXT5为DirectX9.0的纹理压缩格式,若是连DirectX9.0都不支持,建议直接送博物馆),将法线的x和y值存储到纹理的alpha和Green通道便可。之因此是存储到这两个通道,而非其余通道,是由于每一个DXT5中每一个Block选择的两个参考像素alpha通道有8Bit,RGB通道分别为五、六、5Bit,因此使用alpha和Green通道能够得到较高精度。
三、法线贴图的mipmap
使用通常纹理mipmap方法生成的法线贴图对于漫反射表面基本没问题,可是在镜面表面会致使严重的视觉问题。对于漫反射表面来讲,光照的计算公式为l·n,l为光线方向的相反方向,n为法线,l·n1 + l·n2 + l·n3 + l·n4 = l·(n1 + n2 + n3 + n4) / 4,而mipmap则是事先计算(n1 + n2 + n3 + n4) / 4,因此对于漫反射表面,对法线贴图使用传统方式的mipmap基本没问题。为何是基本没问题而不是彻底没问题呢?由于这里存在一个近似,若l·n < 0,则光照值为0(光照不能为负),若将这个因素考虑进去,漫反射表面也会有问题,不过在实际当中这种状况表现不明显,因此能够认为基本没问题。
对于镜面表面来讲,当视线偏离反射光线方向的时候,光照强度会急剧降低,反映在公式中是由于其含有cosm(h·n)项(具体公式能够Google),而漫反射光照是线性变化,因此对于镜面表面,不能使用传统方法生成法线贴图的mipmap。法线贴图对于镜面反射的mipmap如图3所示,第一幅图中有4个像素,每一个像素有法线和镜面反射波瓣(红色的是法线,周围一圈是镜面反射波瓣,镜面反射波瓣用于表示不一样方向的反射强度)。图2中间部分,表示正确的mipmap状况,分别从4个像素合并为2个像素,从两个像素合并为1个像素。而现有的方法中,没有方法能够作到这样的mipmap,因此只能用其余方法进行近似。
图3 法线贴图的mipmap示意图
图2的底部左图,是使用通常纹理的mipmap方法对法线进行平均,能够看到这种方法产生出的镜面反射波瓣和正确的镜面反射波瓣差距很大,其根本缘由是使用线性方法对非线性的参数进行计算。图2底部图右图,每次在平均法线的同时,改变表面的光泽度(即改变镜面光公式中的m),虽然最终结果与正确的mipmap有一些差距,可是比通常纹理的mipmap的方法要好不少。
因此,对法线贴图的mipmap方法之一,就是在使用通常纹理的mipmap方法对法线进行平均的同时,每张mipmap都必须附带一张光泽贴图(gloss map),记录每一个像素点的光泽度(即m),m的计算原则就是让最后的镜面反射波瓣与正确的镜面反射波瓣最接近。固然,还有其余不少方法能获得不错的结果,具体能够参看《Real-Time Rendering 3rd》,或去搜索相关论文。
参考资料
[1]Akenine-Möller T, Haines E, Hoffman N. Real-time rendering 3 [M].