光照模型

记录一下学习过的光照模型的公式,顺便记录记录相关代码,预防哪天需要找轮子的时候还要在线搜索。

兰伯特光照模型

$ Diffuse_{漫反射颜色} = Color_{直射光颜色} * Color_{材质颜色}* max(0,\theta _{光和法线})$

左边是兰伯特,右边是 Unity built in Standard,并且左边只有 albedo,右边还有 normal、MetalMask AO。
lambert

1
2
3
4
5
6
7
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
fixed3 worldNormal = normalize(i.worldNormal);
fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
fixed4 texColor = tex2D(_MainTex, i.uv);
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal, worldLightDir));
fixed3 color = ambient + diffuse + texColor;
return fixed4(color, 1.0);

半兰伯特模型

$ Diffuse_{漫反射颜色} = Color_{直射光颜色} * Color_{材质颜色}* (dot(light_{光源方向},light_{法线方向}) * 0.5 + 0.5) $

half_lambert

最左边是半兰伯特,中间是兰伯特,右边是 standard。

1
2
3
4
5
6
7
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
fixed3 worldNormal = normalize(i.worldNormal);
fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
fixed4 texColor = tex2D(_MainTex, i.uv);
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal, worldLightDir));
fixed3 color = ambient + diffuse + texColor;
return fixed4(color, 1.0);

Phong模型

$ Color = Light_{ambient} + Light_{Diffuse} + Light_{Specular}$

$ Light_{Specular = Light_{光源} * Specular_{高光颜色} * Max(0, V_{视线} * R_{反射方向})^{M_{材质光泽度}}}$

phong

1
2
3
4
5
6
7
8
9
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
fixed3 worldNormal = normalize(i.worldNormal);
fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal, worldLightDir));
fixed3 reflectDir = normalize(reflect(-worldLightDir, worldNormal));
fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos.xyz);
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(reflectDir, viewDir)), _Gloss);
fixed3 texColor = tex2D(_MainTex,i.uv);
return fixed4(ambient + diffuse + specular + texColor, 1.0);

Blinn-Phong 模型

$ Color = Light_{ambient} + Light_{Diffuse} + Light_{Specular}$

$ Light_{Specular = Light_{光源} * Specular_{高光颜色} * Max(0, N_{法线} * H_{新矢量})^{M_{材质光泽度}}}$

$ H_{新矢量} = \frac {V_{视角方向} + L_{光源防线}}{\left | V_{视角方向} + L_{光源方向} \right | }$

Blinn-Phong

左边是 Blinn-Phong,中间是 Phong,右边是 Standard

参数调整区别可能不大,不过也能很明显的看的出 Blinn-Phong 的金属光泽比较明显一点。

参考链接

BSDF 和 BRDF

BRDF(双向反射分布函数)

  • 全称: Bidirectional Reflectance Distribution Function
  • 功能: 它只描述物体表面的反射行为。它定义了当光线从一个入射方向照射到物体表面某点时,光线如何被反射到各个出射方向。
  • 关键限制: 它假设物体是不透明的。这意味着所有照射到表面的光都被反射了,没有光穿透物体。
  • 通俗理解: BRDF 回答的问题是:“一束光从某个角度打到一个不透明的表面上(比如木头、墙壁、金属),它会被反射到哪些方向?每个方向的亮度是多少?”

BSDF(双向散射分布函数)

  • 全称: Bidirectional Scattering Distribution Function
  • 功能: 它是一个更综合的模型,同时描述了物体表面的反射和透射行为。
  • 涵盖范围: BSDF 是 BRDF 和 BTDF 的集合。
    • BRDF: 处理反射部分(光从表面上方入射,反射回表面上方)。
    • BTDF(双向透射分布函数): 处理透射部分(光从表面上方入射,穿透到表面下方)。BTDF 是 BSDF 的另一个组成部分。
  • 通俗理解: BSDF 回答的问题是:“一束光从某个角度打到一个表面上(可能是透明的,比如玻璃、水、塑料),它会被反射到哪些方向?同时,它又会如何被折射/透射到物体的另一侧?”

主要区别对比表

特性 BRDF BSDF
全称 双向反射分布函数 双向散射分布函数
描述现象 仅反射 反射 + 透射(散射)
适用材质 不透明材质(如金属、石材、不透明塑料) 透明、半透明材质(如玻璃、水、玉石、薄膜)以及不透明材质
关系 是 BSDF 的一个子集 是 BRDF 和 BTDF 的父集/统称
光的去向 光只在入射点所在的同一侧半球空间分布 光在入射点两侧的半球空间都有分布(反射侧和透射侧)