【光照】Unity中的[经验模型]
【光照】Unity中的[经验模型]一、引言什么是经验光照模型在计算机图形学中光照模型是模拟光线与物体交互的数学方法。物理精确的光照模型如基于物理渲染PBR虽然真实但计算复杂、调参困难。相比之下经验模型Empirical Models基于观察和简化假设用较少的计算量获得“看起来不错”的效果。Unity作为游戏引擎大量使用了经验光照模型来平衡性能与视觉质量。本文将深入剖析Unity中常用的经验光照模型包括Lambert漫反射、Blinn-Phong高光反射并通过可运行的代码示例展示其实现原理。## 二、核心经验模型原理### 2.1 Lambert漫反射模型Lambert模型是最基础的经验漫反射模型它假设表面理想漫反射即向所有方向均匀反射光。其公式为C_diffuse C_light * C_material * max(0, dot(N, L))其中-C_diffuse最终漫反射颜色-C_light光源颜色-C_material材质颜色-N表面法线-L指向光源的方向向量归一化当dot(N, L) 0时表面背光结果为黑色。### 2.2 Blinn-Phong高光反射模型Blinn-Phong是对传统Phong模型的改进通过计算半角向量H来简化运算C_specular C_light * C_spec * pow(max(0, dot(N, H)), gloss)其中-H normalize(L V)V是视线方向-gloss光泽度高光指数越大越尖锐该模型避免了Phong中反射向量R的计算效率更高且效果接近。## 三、Unity Shader实现基础经验光照下面是一个完整的Unity Shader代码实现Lambert漫反射 Blinn-Phong高光反射的经验光照模型。glslShader Custom/ExperienceLighting { Properties { _MainTex (Albedo (RGB), 2D) white {} _Gloss (Glossiness, Range(0, 1)) 0.5 _SpecColor (Specular Color, Color) (1,1,1,1) } SubShader { Tags { RenderTypeOpaque } LOD 200 CGPROGRAM // 使用 Lambert BlinnPhong 光照函数 #pragma surface surf StandardBlinnPhong fullforwardshadows // 用户输入 sampler2D _MainTex; float _Gloss; fixed4 _SpecColor; struct Input { float2 uv_MainTex; }; // 自定义光照函数Lambert漫反射 BlinnPhong高光 inline fixed4 LightingStandardBlinnPhong (SurfaceOutput s, fixed3 lightDir, half3 viewDir, fixed atten) { // 漫反射部分Lambert模型 half3 halfDir normalize (lightDir viewDir); fixed diff max (0, dot (s.Normal, lightDir)); fixed4 c; c.rgb s.Albedo * _LightColor0.rgb * diff * atten; // 高光部分Blinn-Phong模型 float spec pow (max (0, dot (s.Normal, halfDir)), _Gloss * 128); // gloss映射到0-128 c.rgb _SpecColor.rgb * _LightColor0.rgb * spec * atten; c.a s.Alpha; return c; } void surf (Input IN, inout SurfaceOutput o) { fixed4 c tex2D (_MainTex, IN.uv_MainTex); o.Albedo c.rgb; o.Alpha c.a; } ENDCG } FallBack Diffuse}代码注释说明-LightingStandardBlinnPhong函数重写了Unity的标准光照合并了漫反射和高光。-diff计算Lambert漫反射系数。-spec使用Blinn-Phong公式_Gloss * 128将0-1范围映射到合理的光泽度范围。-atten是光源衰减因子支持点光源、聚光灯等。## 四、进阶多光源支持与顶点光照经验模型在多光源场景下需要额外处理。下面展示一个顶点光照版本支持最多4个光源glslShader Custom/VertexLightingExperience { Properties { _MainTex (Texture, 2D) white {} _Gloss (Gloss, Range(0,1)) 0.5 } SubShader { Pass { Tags { LightModeForwardBase } CGPROGRAM #pragma vertex vert #pragma fragment frag #include UnityCG.cginc #include Lighting.cginc struct appdata { float4 vertex : POSITION; float3 normal : NORMAL; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float3 worldNormal : TEXCOORD1; float3 worldPos : TEXCOORD2; float3 vertexLighting : TEXCOORD3; // 存储顶点光照结果 }; sampler2D _MainTex; float _Gloss; v2f vert (appdata v) { v2f o; o.uv v.uv; o.worldNormal UnityObjectToWorldNormal(v.normal); o.worldPos mul(unity_ObjectToWorld, v.vertex).xyz; // 顶点光照计算遍历最多4个光源 float3 vertexLight float3(0,0,0); #ifdef VERTEXLIGHT_ON for (int i 0; i 4; i) { float3 lightDir float3(unity_LightPosition[i].x, unity_LightPosition[i].y, unity_LightPosition[i].z) - o.worldPos; float distance length(lightDir); lightDir normalize(lightDir); float attenuation 1.0 / (1.0 distance * distance * unity_LightAtten[i].z); // 衰减 // Lambert漫反射 float diff max(0, dot(o.worldNormal, lightDir)); vertexLight unity_LightColor[i].rgb * diff * attenuation; } #endif o.vertexLighting vertexLight; return o; } fixed4 frag (v2f i) : SV_Target { fixed4 texColor tex2D(_MainTex, i.uv); // 主光源方向光使用BlinnPhong高光 float3 lightDir normalize(_WorldSpaceLightPos0.xyz); float3 viewDir normalize(_WorldSpaceCameraPos.xyz - i.worldPos); float3 halfDir normalize(lightDir viewDir); float diff max(0, dot(i.worldNormal, lightDir)); float spec pow(max(0, dot(i.worldNormal, halfDir)), _Gloss * 64); fixed3 color texColor.rgb * (_LightColor0.rgb * diff _LightColor0.rgb * spec); // 加上顶点光照漫反射 color texColor.rgb * i.vertexLighting; return fixed4(color, 1); } ENDCG } }}关键点解析-VERTEXLIGHT_ON宏控制顶点光照的启用。-unity_LightPosition、unity_LightColor、unity_LightAtten是Unity内置数组存储非方向光源信息。- 顶点光照只计算漫反射避免顶点处高光闪烁因为法线插值会失真。- 主光源通常是方向光在片段着色器中计算高光保证质量。## 五、经验模型的局限性尽管经验模型在性能上优势明显但也有明显缺点1.能量不守恒漫反射高光的总能量可能超过入射光物理不真实。2.无法模拟金属质感金属反射特性与绝缘体不同经验模型无法区分。3.微表面效果缺失无法表现粗糙度对反射的影响如PBR的粗糙度贴图。Unity从5.0开始引入PBRStandard Shader正是为了克服这些局限。但对于移动端、旧设备或艺术风格化的项目经验模型依然是首选。## 六、总结本文从原理到实践深入剖析了Unity中的经验光照模型-Lambert漫反射简单高效的漫反射近似公式max(0, dot(N,L))。-Blinn-Phong高光通过半角向量简化高光计算公式pow(dot(N,H), gloss)。- 提供了两个可运行Shader示例分别实现基础版本和多光源顶点光照版本。- 讨论了经验模型的优缺点帮助读者在项目中选择合适的光照方案。经验模型是图形学入门的基石理解它们能让你更深刻地掌握Unity光照系统也为学习PBR打下坚实基础。在实际开发中建议根据目标平台和视觉效果需求灵活选择或组合使用。

相关新闻