渲染篇:法线贴图

今天接着讲渲染基础:就是下面的法线贴图了。

什么是法线贴图?

法线贴图这个东西,只要搞渲染算法的肯定会遇到。简单来讲,法线就是指模型表面的凹凸感,而凹凸感的产生是因为模型表面像素的光照条件不一样产生的。比如下面这个图,边缘光照压暗了,所以给人有一种凹凸3D感觉。

但凹凸感跟法线贴图有什么关系?

在逐像素计算光照时,每一个像素都会根据该点的法向量来计算最终该点的光照结果,那么,我们如果能够改变这个法线的方向,就可以改变这个点的光照结果,进而影响模型表面凹凸感。比如,高模在计算光照时,每个面的法线方向不同,所以各个面的光照计算结果都不同,就有凹凸的感觉了,而有的低模只有一个面,整个面的光照条件都是一致的,就没有凹凸的感觉了。如果我们把高模的法线信息保存下来,类似纹理贴图那样,存在一张图里,再给低模使用,低模就可以有跟高模一样的法线,进而在计算光照时达到和高模类似的效果,这也就是常说的烘法线的原理。

知道了概念,再来看看实现。

最早的法线贴图实现方式是使用凹凸贴图(Bump Map),简单来讲就是给一张灰度图,默认为黑色,越凸起的地方颜色越亮,通过采样点之间斜率决定像素是否位于边缘,从而影响光照明暗,不过这种方式已经过时了,具体细节不再赘述。

Unity法线贴图一般都是存储在切线空间。这跟世界空间、模型空间类似,只不过这个空间稍有点不直观。大家只要知道这是为了解耦就行,比如最直观是将不同顶点的法线值存储在世界空间,理解和计算都方便,但是这样会有弊端,就是当模型发生旋转等变化时,同一顶点的法线值就会发生变化,也就是需要多份法线贴图,这显然是极其浪费的。如何保证同一模型共用一份法线贴图呢?答案就是将法线值存储在切线空间。切线空间的z轴就是顶点所在面的法线方向,该点的uv二维坐标系则用来表达该点的切线(tangent)和该点的次法线(binormal)方向,具体计算如下:

T = normalize(dx/du, dy/du, dz/du)

N = T × normalize(dx/dv, dy/dv, dz/dv)

B = N × T

OK,知道法线贴图存储的是切线空间法线值,那么就可以开始了。首先在顶点着色器中,存储模型的切线空间到世界空间的转换矩阵。

片元着色器采样法线贴图,映射计算,空间转换。

这中间有一步映射计算,大致就是因为法线贴图存储的值是有限范围(比如8bits是0~255),归一化就是0到1;而法线值是-1到1,所以需要乘以2减去1,只不过这里Unity给我们封装好了。

看下效果:

我们增大下法线强度。从法线贴图中获取到的是这个采样点对应的法线方向,光滑的部分法线方向都为垂直于表面竖直向上的方向,也就是(0,0,1)的方向,而有凹凸的地方,法线就会有偏移值,换句话说,我们让法线贴图采样出来的方向越偏离(0,0,1)方向,就会越加强法线的效果。

结果:

我们应用到前面文章讲过的BlinnPhong模型,增加法线贴图效果,看下对比:

从左到右分别是:直接贴图采样、BlinnPhong模型、增加法线贴图的BlinnPhong模型。

本节内容就介绍到这里,有问题欢迎留言或私聊~~~

欢迎关注我的微信公众号【unity大话东游】,更多的unity技术类和渲染类文章等着你哦!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值