兰伯特光照模型
一、必备知识点
1.两个颜色相乘
- 通常用于计算光照、材质混合、纹理混合等需求
- 它一种用于混合颜色叠加在一起的效果
- 计算结果 可以理解为两种颜色叠加在一起的效果
- 计算方式 通常使用颜色通道的值来执行逐通道的乘法
- 例子 颜色 A、B 都是 fixed4 类型的变量 颜色 A * 颜色 B =(A.r*B.r , A.g*B.g , A.b* B.b , A.a* B.a); 那么得到的这个结果就是 A、B 颜色看加后的结果
2.漫反射基本概念
漫反射(Diffuse Reflection)是光线撞击一个物体表面后以各个方向均匀地反射出去的过程在漫反射下,光线以无规律的方式散射,而不像镜面反射那样按照特定的角度反射。这种散射导致了物体表面看起来均匀而不闪烁的效果。
二、兰伯特光照模型的来历和原理
兰伯特(Lambert)光照模型,也称为朗伯反射模型,是由瑞士数学家约翰·海因里希·朗伯(Johann Heinrich Lambert)于 1768 年左右首次提出,朗伯是 18 世纪的一个杰出科学家,他在光学和数学领域作出了众多贡献。兰伯特光照模型描述了漫反射表面对光线的反射行为,它成为计算机图形学和渲染中重要的基础模型之一 原理: 兰伯特光照模型的理论是:
认为漫反射光的强度仅与入射光的方向和反射点处表面法线的夹角的余弦成正比
原理图
三、兰伯特光照模型的公式
公式: 漫反射的颜色 = 光源颜色 * 材质漫反射的颜色 * max(0,标准化后物体表面法向量 · 标准化后光源方向向量)
公式推导: 其中:
- 标准化后物体表面法线向量 · 标准化后光源方向的向量 得到的结果就是 cosθ
- max(0,cosθ)的目的是避免负数,对于模型背面部分,认为照不到光照,直接乘以 0,变为黑色

四、如何在 Shader 中公式中获取关键信息
1.光源颜色
1
| Light.cginc 内置文件中的 _LightColor0
|
2.光源的方向
1
| _WorldSpaceLightPos0 //光源在世界坐标下的位置
|
3.向量归一化
4.取最大值的方法
5.点乘的方法
6.兰伯特光照模型环境光变量(用于模拟环境光堆物体的影响,避免物体阴影部分完全黑暗)
1
| UNITY_LIGHTMODEL_AMBIENT.rgb
|
7.将法线从模型空间转换到世界空间
1
| UnityObjectToWorldNormal
|
五、逐顶点光照的实现
- 材质漫反射颜色属性声明
- 渲染标签 Tags 设置 将 LightMode 光照模式 设置为 ForWardBase 向前渲染(通常用于不透明物体的基本渲染)
- 引用内置文件 UnityCG.cginc、Lighting.cginc
- 结构体声明
- 基于基本公式实现逻辑
- 演示代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| Properties { _MainColor("MainColor",Color) = (1,1,1,1) } SubShader { Tags { "LightMode"="ForwardBase" } Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" #include "Lighting.cginc" fixed4 _MainColor; struct v2f { float4 pos:SV_POSITION; fixed3 color:COLOR; }; v2f vert (appdata_base v) { v2f v2fData; v2fData.pos = UnityObjectToClipPos(v.vertex); float3 normal = UnityObjectToWorldNormal(v.normal); float3 lightDir = normalize(_WorldSpaceLightPos0.xyz);
fixed3 color = _LightColor0.rgb * _MainColor * max(0,dot(normal,lightDir)); v2fData.color = UNITY_LIGHTMODEL_AMBIENT.rgb + color;
return v2fData; }
fixed4 frag (v2f i) : SV_Target { return fixed4(i.color.rgb,1); } ENDCG } }
|
- 实现效果

注意: 为了阴影不全黑,需要加上兰伯特环境光公共颜色公共变量
六、逐片元关照的实现
- 材质漫反射颜色属性声明
- 渲染标签 Tags 设置 将 LightMode 光照模式 设置为 ForWardBase 向前渲染(通常用于不透明物体的基本渲染)
- 引用内置文件 UnityCG.cginc、Lighting.cginc
- 结构体声明
- 基于基本公式实现逻辑
- 演示代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| Properties { _MainColor("MainColor",Color) = (1,1,1,1) } SubShader { Tags { "LightMode"="ForwardBase" } Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" #include "Lighting.cginc" float3 _MainColor; struct v2f { float4 pos:SV_POSITION; float3 normal:NORMAL; }; v2f vert (appdata_base v) { v2f v2fData; v2fData.pos =UnityObjectToClipPos(v.vertex); v2fData.normal = UnityObjectToWorldNormal(v.normal); return v2fData; }
fixed4 frag (v2f i) : SV_Target { float3 lightDir = normalize(_WorldSpaceLightPos0.xyz); fixed3 color = _MainColor.rgb * _LightColor0.rgb * max(0,dot(lightDir,i.normal)); color = UNITY_LIGHTMODEL_AMBIENT.rgb + color; return fixed4(color.rgb,1); } ENDCG } }
|
- 实现效果
