3D游戏常用技巧Normal Mapping (法线贴图)原理解析——高级篇
1、概述
上一篇博客,3D游戏常用技巧Normal Mapping (法线贴图)原理解析——基础篇,讲了法线贴图的基本概念和使用方法。而法线贴图和一般的纹理贴图一样,都需要进行压缩,也需要生成mipmap。但是由于法线贴图存储的是法线信息,压缩和生成mipmap的方法自然会有所变化。
现在已经许多用于法线贴图压缩和生成mipmap的工具,大部分商业游戏引擎也集成了相关方法,只需要点几下鼠标就可以完成。本文仅针对法线贴图的纹理压缩和mipmap的方法进行原理性的说明,至于在具体的工具中如何操作,可以参看相关工具的说明文档。
法线贴图压缩的中文资料还是比较多的,也不太复杂;但是生成mipmap的方法中文资料不多,《Real-Time Rendering 3rd》讲解的比较详细,本文的这部分内容主要来源于这本书,如果想详细了解的,可以看原书,网上有电子版。
2、法线贴图的压缩
传统的jpg等压缩方式解压时间太长,且压缩比不固定,所以在实时渲染中一般采用DXTC及其改进方法,简单来说,就是把4*4的像素当做一个Block,对其进行简化表示,详情参见百度百科http://baike.baidu.com/view/736449.htm。由于法线贴图存储的数据并不是RGB信息而是法线方向,所以需要在一般纹理压缩的方法的基础上进行一定的改变。
压缩的第一步很简单,由于归一化的法线长度为1,且在切线空间下,法线的z分量不可能为负数,所以只需要存储x和y值即可。本文的压缩方法在这一步压缩的基础上,利用现有的纹理压缩方法,进行进一步压缩。
在支持DirectX10的显卡上,可以使用BC5格式进行压缩。BC5的压缩方法内存情况如图1所示,该格式有两个颜色通道(R和G),每个通道使用两个1Byte的值来表示,每个像素使用3Bit在这两个颜色值之间进行插值。将法线贴图中每个法线的x和y值利用BC5格式进行压缩,如图2所示。对每个Block(16个像素)存储x的最大、小值和y的最大、小值,然后每个像素利用3Bit进行插值,相当于在图2右图所示的8*8区域内取样(为了简化表示,图2只画了4*4点)。
图1 BC5压缩方法
图2 法线贴图压缩示意图,右图框内应该是8*8个点,为了画图方便简单表示为4*4
对于不支持DirectX10的显卡,可以使用DXT5格式进行压缩(DXT5为DirectX9.0的纹理压缩格式,如果连DirectX9.0都不支持,建议直接送博物馆),将法线的x和y值存储到纹理的alpha和Green通道即可。之所以是存储到这两个通道,而非其他通道,是因为每个DXT5中每个Block选择的两个参考像素alpha通道有8Bit,RGB通道分别为5、6、5Bit,所以使用alpha和Green通道可以获得较高精度。
3、法线贴图的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].
3D游戏常用技巧Normal Mapping (法线贴图)原理解析——高级篇的更多相关文章
- 3D游戏常用技巧Normal Mapping (法线贴图)原理解析——基础篇
http://www.cnblogs.com/wangchengfeng/p/3470310.html
- (转)Unity3D 游戏贴图(法线贴图,漫反射贴图,高光贴图)
原帖网址http://www.u3dpro.com/read.php?tid=207 感谢jdk900网友的辛苦编写 我们都知道,一个三维场景的画面的好坏,百分之四十取决于模型,百分之六十取决于贴图 ...
- 【转载】法线贴图Nomal mapping 原理
法线贴图多用在CG动画的渲染以及游戏画面的制作上,将具有高细节的模型通过映射烘焙出法线贴图,贴在低端模型的法线贴图通道上,使之拥有法线贴图的渲染效果,却可以大大降低渲染时需要的面数和计算内容,从而达到 ...
- shader复杂与深入:Normal Map(法线贴图)1
转自:http://www.zwqxin.com/archives/shaderglsl/review-normal-map-bump-map.htmlNormal Map法线贴图,想必每个学习计算机 ...
- 【Unity Shader】六、使用法线贴图(Normal Map)的Shader
学习资料: http://www.sikiedu.com/course/37/task/456/show# http://www.sikiedu.com/course/37/task/458/show ...
- Esfog_UnityShader教程_NormalMap法线贴图
咳咳,好久没有更新了,一来是这段时间很忙很忙,再来就是自己有些懒了,这个要不得啊,赶紧补上.在前面我们已经介绍过了漫反射和镜面反射,这两个是基本的光照类型,仅仅依靠它们就想制作出精美的效果是远远不够的 ...
- 【Unity Shaders】学习笔记——SurfaceShader(七)法线贴图
[Unity Shaders]学习笔记——SurfaceShader(七)法线贴图 转载请注明出处:http://www.cnblogs.com/-867259206/p/5627565.html 写 ...
- 一个有趣的模拟光照的shader(类似法线贴图)
最近使用unity,碰到到一个很有趣的例子.场景无光线,却模拟出了光照,效果挺好.其思路与法线贴图原理异曲同工. 原作者提供的效果印象深刻. 模型除了使用原来的diffuse贴图外,还用到了一张模拟记 ...
- 翻译:非常详细易懂的法线贴图(Normal Mapping)
翻译:非常详细易懂的法线贴图(Normal Mapping) 本文翻译自: Shaders » Lesson 6: Normal Mapping 作者: Matt DesLauriers 译者: Fr ...
随机推荐
- web_find和web_reg_find的用法和区别
一.web_find()函数 该函数的作用是“在页面中查找相应的内容”,常用参数及含义如下: web_find("web_find", //定义该查找函数的名称 "Rig ...
- C# 条形码识别
目录: 一.识别库 二.从一张图片中提取多个条形码 三.注意事项 从博客园学了很多,本着分享的目的,希望后来者遇到类似问题时,不必重复造轮子,早点下班回家^-^. 一.识别库 目前主流的识别库主要有Z ...
- IP地址计算和划分
一. B类地址 范围从128-191(第一串8位二进制10000000~10111111),如172.168.1.1,第一和第二段号码为网络号码,剩下的2段号码为本地计算机的号码.转换为2进 ...
- CSS3 媒体记
css3 媒体 Media Type 媒体类型 媒体类型是CSS2中一个非常有用的属性.通过媒体类型可以对不同的设备指定不同的样式. W3C共列出十种媒体类型,如表: 值 设备类型 all 所有设备 ...
- DOM操作在jQuery中的实用------文字提示和图片提示
关于文字提示想必是家喻户晓,操作呢说简单一点就是在超链接中加入title属性.但是在人机交互越来越倍受恩宠的年代,依靠浏览器自带的文字提示即title属性,提示效果的响应速度就(还是人艰不拆了吧~)s ...
- 【转载】Apache kafka原理与特性(0.8V)
http://blog.csdn.net/xiaolang85/article/details/37821209 前言: kafka是一个轻量级的/分布式的/具备replication能力的日志采集组 ...
- sql新手全套
--[数据库]gocreate database DB_MGG --添加数据库on(name=DB_MGG --逻辑名称,filename='C:\MDB\DB_MGG.mdf' --物理名称 逻 ...
- dreamweaver中用正则表达式查找替换批量删除 tppabs标签的方法
查找替换 正则表达式 \btppabs="h[^"]*" 后面不能有空格 你懂得的 选中右下角的 √[使用正则表达式] 替换全部
- Contoso 大学 - 10 - 高级 EF 应用场景
原文 Contoso 大学 - 10 - 高级 EF 应用场景 By Tom Dykstra, Tom Dykstra is a Senior Programming Writer on Micros ...
- linux中vsftpd登陆慢卡问题解决方法
1.修改服务器上的/etc/resolv.conf令其内容只有类似 nameserver 192.81.133.229 nameserver 114.114.114.114 出现问题的机器的resol ...