作者:banli | 来源:互联网 | 2023-09-16 18:30
漫反射光照 详情参见:https://github.com/mrxandlingsa (冯乐乐) 兰伯特光照模型 (Lambert) 应用 :Lambert 模型较好地表现了粗糙表面上的光照现象,如石灰粉刷的墙壁、纸张等 公式:C(diffuse)=(C(light)*m(diffuse))*max(0,n,l) C(light):入射光线的颜色和强度 m(diffuse):材质的反射系数发v n:表面法线 l:光源方向 CG中saturate(x)函数可代替上述公式
1)Lambert光照的逐顶点光照实现
Shader "Unlit/Lambert" { Properties {_Diffuse ("Diffuse", Color) = (1, 1, 1, 1)//材质的漫反射颜色}SubShader {Pass { Tags { "LightMode"="ForwardBase" }CGPROGRAM#pragma vertex vert#pragma fragment frag#include "Lighting.cginc"fixed4 _Diffuse;struct a2v {float4 vertex : POSITION;float3 normal : NORMAL;};struct v2f {float4 pos : SV_POSITION;fixed3 color : COLOR;};v2f vert(a2v v) {v2f o;// Transform the vertex from object space to projection space//顶点位置的坐标转化到剪裁空间o.pos = UnityObjectToClipPos(v.vertex);// Get ambient term环境光fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;//公式应用是都在世界空间下进行// Transform the normal from object space to world space//世界坐标下法线向量并归一化fixed3 worldNormal = normalize(mul(v.normal, (float3x3)unity_WorldToObject));// Get the light direction in world space//世界坐标下的光源方向(单一光源)fixed3 worldLight = normalize(_WorldSpaceLightPos0.xyz);// Compute diffuse term//Lambert公式的应用(dot为2个向量的点积)fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal, worldLight));o.color = ambient + diffuse;return o;}fixed4 frag(v2f i) : SV_Target {return fixed4(i.color, 1.0);}ENDCG}}FallBack "Diffuse" }
``效果如上 2)逐像素的Lambert光照实现 之需要将世界空间下的法线传递给片元着色器 实现如下:
在这里插入代码片 struct{ float4 pos:SV_POSITION; float3 worldNormal:TEXCOORD0; } v2f vert( a2v v) { v2f o; // Transform the vertex from object space to projection space//顶点位置的坐标转化到剪裁空间o.pos = UnityObjectToClipPos( v.vertex) ; o.worldNormal= mul( v.normal,( float3x3) unity_WorldToObject) ; return o; } fixed4 frag( v2f i) : SV_Target { fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz; fixed worldNormal= normalize( i.worldNormal) ; fixed3 worldLight= normalize( _WorldSpaceLightPos0.xyz) ; fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate( dot( worldNormal, worldLight)) ; fixed3 color = ambient + diffuse; return fixed4( color, 1.0) ; }
效果如下 3)半兰伯特模型 公式: C(diffuse)=(C(light)*m(diffuse))(0.5(n,l)+0.5) 原理:将n·l的结果范围从[-1,1]映射到[0,1]的范围内。 只需要更改片元着色器的代码即可
fixed4 frag( v2f i) : SV_Target { // Get ambient termfixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz; // Get the normal in world spacefixed3 worldNormal = normalize( i.worldNormal) ; // Get the light direction in world spacefixed3 worldLightDir = normalize( _WorldSpaceLightPos0.xyz) ; // Compute diffuse termfixed halfLambert = dot( worldNormal, worldLightDir) * 0.5 + 0.5; fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * halfLambert; fixed3 color = ambient + diffuse; return fixed4( color, 1.0) ; }
不知道关于漫反射还有其他模型么?