您的位置:首页 > 移动开发 > Unity3D

Unity|ShaderLab笔记整理-二(逐顶点漫反射+环境光)

2017-06-12 18:45 369 查看

· 光照模型

一:什么是光照模型?
光照模型就是一个公式,用来计算光在某点所反映出的光照效果

二:标准光照模型
每个点受光照影响,大概分为以下4个部分
1)自发光:Emissive(一般认为自发光是均匀的)
2)高光反射:Specular(speculer像镜子,亮)
3)漫反射:Diffuse(diffuse向四周散射,无高亮点)
4)环境光:Ambient(没被直接照亮的物体也有亮度,受环境光影,模拟间接光照)
三:标准光照的伪公式
SurfaceColor = Emissive + Specular + Diffuse + Ambient
*以上四种光照都是用来模拟光照效果的*


· 漫反射(兰伯特光照模型):物体被照射后,光会均匀的照亮这个物体

漫反射光照计算:漫反射光的强度近似地服从于Lambert定律,即漫反射光的光强仅与入射光的方向和反射点处表面法向夹角的余弦成正比。

初级漫反射公式:Diffuse = lightColor(直射光颜色) * Cos夹角(入射光与顶点法线夹角)

当三角函数cos夹角值为0°,cos(0)= 1 迎光面亮度最强,
当三角函数cos夹角值为90°,cos(90)=0 迎光面亮度最弱,
当三角函数cos夹角值为180°,cos(180)=-1 背光面最强,

~注:点积值为负,光照无任何物理意义,当负值和其他项加在一起会引起错误,为了处理此类问题,
此时引入CG语言中的max函数,将结果映射为大于等于0,意味着如果点积值如果小于0,则它将被设成0。

所以,当三角函数cos夹角值为180°,cos(180)=-1,直射光与该夹角值结果为负值时,
我们引入max(a,b);取ab的最大值,保证颜色值的正确,故:

进阶漫反射公式:Diffuse =  入射光颜色 * max(0,Cos夹角(入射光与顶点法线夹角))

Cos夹角则是通过数学运算:点积 获取
Cos夹角 = 光方向 点积 法线方向

兰伯特光照模型:Diffuse =  入射光颜色 * max(0,光方向 点积 法线方向(入射光与顶点法线夹角))

解析漫反射公式:
当入射光线与顶点法线重合时,夹角为0 也就是【Cos夹角 = 0°】此时三角函数值为1,光垂直于物体表面,也就是光照亮度最强的时候
当入射光线与顶点法线夹角发生变化,随着夹角在【0°<Cos夹角<90°】区间,三角函数值:0<值<1之间,光照亮度随角度增大而减弱


· 引入光照变量及光照参数

因为用到Unity光照变量,需要引入Unity内建的光照文件->#include "Lighting.cginc"
并在pass中加入标签:告诉GPU渲染路径以正向渲染模式进行。
Tags{"Lightmode = ForwardBase"}
如下:


pass
{
//ForwardBase 正向渲染
Tags{"Lightmode = ForwardBase"}
CGPROGRAM
//引入unity内建光照文件
#include"Lighting.cginc"
........
}


· 综上所述,顶点函数中的默认漫反射实现如下:

//逐顶点光照
v2f vert(a2v v) {
v2f f;
//顶点位置从模型空间转换到裁剪空间空间也称为(投影空间)
f.position = mul(UNITY_MATRIX_MVP,v.vertex);

//光方向(_WorldSpaceLightPos0.xyz 世界空间中灯光位置就等于灯光方向并归一化)
fixed3 lightDir = normalize(_WorldSpaceLightPos0.xyz);

//法线方向(顶点法线与3x3矩阵相乘后再归一化)
fixed3 normalDir = normalize(mul(v.normal,(float3x3)_World2Object));

//漫反射光照
fixed3 diffuse = _LightColor0.rgb * max(dot(lightDir,normalDir),0);
f.color = diffuse;
return f;
}


· 增加漫反射颜色

第一步:增加Properties属性
Properties{
_DiffuseColor("Diffuse Color",color) = (1,1,1,1)
}
第二步:在CG语段中增加漫反射颜色的调用变量
fixed4 _DiffuseColor;

第三步:在顶点函数中,将最终漫反射光照公式乘以颜色变量(颜色的混合的方式,用乘法表现)
fixed3 diffuse = _LightColor.rgb * max(dot(lightDir,normalDir),0) * _DiffuseColor;
f.color = diffuse;
return f;

总结:此时的漫反射颜色随着方向光的明暗和_DiffuseColor颜色值变化


· 增加环境光影响(在顶点函数中引入Unity宏-ambient环境光)

//逐顶点光照
v2f vert(a2v v) {
v2f f;
//顶点位置从模型空间转换到裁减空间也叫投影空间
f.position = mul(UNITY_MATRIX_MVP,v.vertex);

//引入宏,UNITY_LIGHTMODE_AMBIENT(环境光)
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT;

//光方向(_WorldSpaceLightPos0.xyz 世界空间中灯光位置就等于灯光方向)
fixed3 lightDir = normalize(_WorldSpaceLightPos0.xyz);

//法线方向(顶点法线与3x3矩阵相乘后再归一化)
fixed3 normalDir = normalize(mul(v.normal,(float3x3)_World2Object));

//漫反射光照+ambient
fixed3 diffuse = _LightColor0.rgb * max(dot(lightDir,normalDir),0);
//漫反射+环境光(颜色叠加,用加法,亮度变化)
f.color = diffuse + ambient;
return f;
}


知识点总结(计算机图形效果如果看起来是对的,那就是对的!)

光照模型

漫反射光照的计算公式

引入Unity光照变量

逐顶点光照计算

Add-Properties属性值color

增加环境光影响

拓展

Lambert光照是一个用来模拟粗糙表面对光线的漫反射现象的经验模型,对于纸张、粗糙墙壁常用
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: