shader 获取法线_Unity Shader-法线贴图(Normal)及其原理

简介

以前经常听说“模型不好看啊,怎么办啊?”答曰“加法线”,”做了个高模,准备烘一下法线贴图”,“有的美术特别屌,直接画法线贴图”.....法线贴图到底是个什么鬼,当年天真的我真的被这个图形学的奇淫杂技忽悠了,然而毕竟本人还算有点刨根问底的精神,决定研究一下法线贴图的原理以及Unity下的实现。本人才疏学浅,如有错误,欢迎指正。

法线贴图是目前游戏开发中最常见的贴图之一。我们知道,一般情况下,模型面数越高,可以表现的细节越多,效果也越好。但是,由于面数多了,顶点数多了,计算量也就上去了,效果永远是和性能成反比的。怎么样用尽可能简单模型来做出更好的效果就成了大家研究的方向之一。纹理映射是最早的一种,通过纹理直接贴在模型表面,提供了一些细节,但是普通的纹理贴图只是影响最终像素阶段输出的颜色值,不能让模型有一些凹凸之类的细节表现。而法线贴图就是为了解决上面的问题,给我们提供了通过低面数模型来模拟高面数模型的效果,增加细节层次感,效果与高模相差不多,但是大大降低了模型的面数。

法线贴图原理

要模拟一个圆球,要想越平滑,就需要更多的面数,否则会很容易地发现面和面之间的明显边界。最早时的GPU是没有fragement编程能力的,也就是说在这种情况下,在计算时需要逐顶点计算光照,然后每个像素的颜色在各个顶点的颜色之间插值,也就是高洛德着色,这种情况下,面数决定一切效果,没有什么好办法。而当像素着色器出现之后,我们可以逐像素来计算光照效果,这时候,在计算每个像素的光照时,会计算这个像素所在的面的法向量,而这个面的法向量也是由这个面周围的顶点法线(也就是我们之前vertex shader中出现的normal)插值得来的,当然,如果面数很低,那么效果也好不到哪里去。但是,逐像素计算光照时,我们每一个像素都会根据该点的法向量来计算最终该点的光照结果,那么,我们如果能够改变这个法线的方向,不是就可以改变这个点的光照结果了呢!那么,把纹理采样的思想用在这里,我们直接用一张图来存储法线(或者法线偏移值,见下文),逐像素计算时,在采样diffuse贴图的时候,再采样一张法线的贴图,就可以修改法线了,进而修改最终的效果。

为什么法线贴图会让我们感觉有凹凸感呢?看下面一张图,在现实世界中,你要相信你的眼睛,眼见为实还有点道理,在计算机世界中,一切以忽悠你为目的。在平面的情况下,我们感觉物体是凹陷还是凸起,很大一部分取决于这个面的亮度,像下面这张图,有了这种亮度的对比,我们就很容易感觉这个按钮有周围的一圈凸起。

如果还是没理解,再看一套图片,同样一张图片,旋转180度后的结果完全相反。不信可以去截图放到MSPaint里面转一下试试,反正我是试了....

既然一个面的光照条件(亮度)的改变,就可以让我们感觉这个面有凹凸感,那么上面说的,通过改变法线来改变面上某点的光照条件,进而忽悠观察者,让他们感觉这个面有凹凸感的方法就行得通了。

假如下面是我们的低面数模型,上面是我们的高面数模型,上面的模型在计算光照时,由于面数多,每个面的法线方向不同,所以各个面的光照计算结果都不同,就有凹凸的感觉了,而下面的低模,只有一个面,整个面的光照条件都是一致的,就没有凹凸的感觉了。我们如果把上面的高模的法线信息保存下来,类似纹理贴图那样,存在一张图里,再给低模使用,低模就可以有跟高模一样的法线,进而在计算光照时达到和高模类似的效果,这也就是常说的烘法线的原理。

凹凸贴图(Bump Map)

既然说了要研究法线贴图,所以肯定要从老一辈的开始,首先来看一下凹凸贴图(Bump Map)。Bump Map是最早的法线贴图实现方式,这也是制作上最容易的一种模式,可以直接通过一张灰度图,默认为黑色,越凸起的地方颜色越亮,这种就是可以直接在PhotoShop中画的法线,但是这种法线贴图的原理理解起来比较难,我只说一下我的理解,然后附上unity中的shader实现。这种技术现在貌似已经过时了,但是思想还是流传下来了,而且这种画灰度图,或者通过灰度图生成法线贴图的方式现在仍然在使用,Unity就支持这种直接通过灰度图生成法线贴图。

首先,通过灰度图来表现凹凸,那么,我们怎样判断一个点处在凹凸的边缘呢?答案是通过斜率,比如我要对(x,y)进行采样,怎样求这一点的斜率呢,学过数学的都知道,我们可以通过两点确定一条直线,进而求出这条直线的斜率。那么我们就可以对(x-1,y)和(x+1,y)两点进行采样,竖向也是一样,通过(x,y-1)和(x,y+1)进行采样,那么,我们就可以获得这一点上灰度值的变化,如果灰度值不变,说明该点不在边缘,如果灰度值有改变,那么说明该点在边缘,那么我们就可以根据

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值