unity shader光照模型与光照贴图

一、渲染总是围绕一个基础问题:如何决定一个像素的颜色;

宏观来说,渲染包含两大部分:决定一个像素的可见性,决定这个像素的光照计算

光照模型:用于决定在一个像素上进行怎样的光照计算。

我们必须要明白我们是如何看到一个物体的,我们在现实生活中看到某一物体的颜色并不是这个物体真正拥有的颜色,而是它所反射的(Reflected)颜色。换句话说,那些不能被物体所吸收(Absorb)的颜色(被拒绝的颜色)就是我们能够感知到的物体的颜色,所以最终的颜色要由光源的颜色以及物体的颜色来共同决定。

二、光照相关术语

如何测量一个光源发射出了多少光,辐照度:就是对光的量化

光线与物体相交的结果:散射和吸收

散射有两种:折射和反射,在光照模型中分为两种,

高光反射部分:表示物体表面是如何反射光线的。

漫反射:表示有多少光线会被折射、吸收和散射出表面。

出射度:计算出射光线的数量和方向

着色:根据材质属性(如漫反射属性等)、光源信息(光源方向,辐照度等),使用一个等式计算沿某个观察方向的出射度的过程。我们也把这个等式称为光照模型。(Lighting Model)

三、标准光照模型与光照贴图

把进入到摄像机内部的光线分为4个部分:

自发光(emissive)部分:使用Cemissive表示,这个部分用于描述当给定一个方向时,一个表面本身会向该方向发射多少辐射量。需要注意的是:如果没有使用全局光照,这些自发光的表面并不会真的照亮周围的物体,而只是让它本身看起来更亮而已。

高光反射(specular)部分:使用Cspecular表示。这个部分白哦是当光线从光源照射到模型表面时,表面会在完全镜面反射方向散射多少辐射量。

漫反射(diffuse)部分:使用Cdiffuse表示,用于描述,当光线从光源照射到模型表面时,该表面会向每个方向散射多少辐射量。

环境光(ambient)部分:使用Cambient表示,用于描述其它所有的间接光照。

两个主要的光照漫反射和高光反射都是使用的冯氏光照模型,下面的光照模型主要借鉴于:OpenGL基础光照

漫反射光照符合兰伯特定律:

环境光照本身不能提供最有趣的结果,但是漫反射光照就能开始对物体产生显著的视觉影响了。漫反射光照使物体上与光线方向越接近的片段能从光源处获得更多的亮度。为了能够更好的理解漫反射光照,请看下图:


图左上方有一个光源,它所发出的光线落在物体的一个片段上。我们需要测量这个光线是以什么角度接触到这个片段的。如果光线垂直于物体表面,这束光对物体的影响会最大化(译注:更亮)。为了测量光线和片段的角度,我们使用一个叫做法向量(Normal Vector)的东西,它是垂直于片段表面的一个向量(这里以黄色箭头表示),我们在后面再讲这个东西。这两个向量之间的角度很容易就能够通过点乘计算出来

反射光线的强度与表面法线和光源方向之间的夹角的余弦值成正比。
Cdiffuse=(Clight*mdiffuse)max(0,n*l);  //截取到0防止顶点被从背后发射的光线照亮
需要四个参数:入射光线的颜色和强度,材质的漫反射系数,表面法线以及光源方向。
Cg中的saturate(x)函数:为了防止点积结果为负值
把x截取在[0,1]范围内,如果x是一个矢量,那么会对它的每一个分量进行这样的操作。
兰伯特模型和半兰伯特模型的用法区别,对于兰伯特模型,光线无法到达的地方会成为全黑的,模型将失去细节表现。

高光反射:

和漫反射光照一样,镜面光照也是依据光的方向向量和物体的法向量来决定的,但是它也依赖于观察方向,例如玩家是从什么方向看着这个片段的。镜面光照是基于光的反射特性。如果我们想象物体表面像一面镜子一样,那么,无论我们从哪里去看那个表面所反射的光,镜面光照都会达到最大化。你可以从下面的图片看到效果:


我们通过反射法向量周围光的方向来计算反射向量。然后我们计算反射向量和视线方向的角度差,如果夹角越小,那么镜面光的影响就会越大。它的作用效果就是,当我们去看光被物体所反射的那个方向的时候,我们会看到一个高光。

光照贴图主要由两种,漫反射贴图和高光贴图,分别对应两种光照模型,关于两种贴图的内容细节请参考:OpenGL光照贴图

四、逐像素/逐顶点

在哪计算光照模型?

逐顶点光照在顶点着色器中计算,phone着色技术。

逐像素光照在片元着色器中计算,高洛德着色技术。

由于顶点数目远远小于像素数目,所以逐顶点光照的计算量往往要小于逐像素光照。

使用逐顶点计算的高光是有问题的,因为高光反射部分不是线性的,而顶点着色器中计算光照再线性插值的过程是线性的。

由于逐顶点光照会在渲染图元内部对顶点颜色进行插值,这会导致渲染图元内部的颜色总是暗于顶点处的颜色,这在某些情况下会产生明显的棱角现象。

五、逐顶点光照->逐像素光照

将光照模型的计算从vert函数移到frag函数中,并修改顶点着色器的输出结构体

在Diffuse光照模型中,需要把输出结构体中的颜色变量去除,添加顶点在世界空间中的法线,因为这个顶点传入片元着色器时被转换为裁剪空间的顶点坐标了,所以要在顶点计算出该法线,用于lambert公式的dot()计算。

在Specular光照模型中,需要把颜色变量去除,添加顶点在世界空间中的法线,以及顶点在世界空间中的坐标,用于计算摄像机的观察向量。

至于逐顶点和逐像素的光照区别,这里有一篇文章讲述的还不错:逐顶点还是逐光照。

六、光照计算中使用到的unity内置函数

这些内置函数由UnityCG.cginc提供,使用之前要提前包含该文件。


本文转自:CSDN - 莫之(qq_36383623的博客),转载此文目的在于传递更多信息,版权归原作者所有。
原文链接:https://blog.csdn.net/qq_36383623/article/details/86189075

最新文章