【Unity】幾何減衰
マイクロファセット(微細表面)
マイクロファセットとは物体の表面には目では見えない凹凸のことです。
幾何減衰
マイクロファセットにより入射光が遮断される(シャドウイング)ことがあります。
同様に反射光もマイクロファセットにより遮断されます(マスキング)。 幾何減衰はこのマイクロファセットによる光の遮断による反射光の成分の減衰を計算するものです。
幾何減衰にはいくつか種類があるようですが、今回はHeight-Correlated Smithモデルを使用します。
実装
Shader "SmithGGXCorrelated" { Properties { _MainTex ("Texture", 2D) = "white" {} _Roughness("Roughness", Range(0.0, 1.0)) = 0.5 } SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; half3 normal : NORMAL; }; struct v2f { float4 vertex : SV_POSITION; half3 worldNormal : TEXCOORD2; half3 viewDir : TEXCOORD3; }; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz; o.worldNormal = UnityObjectToWorldNormal(v.normal); o.viewDir = UnityWorldSpaceViewDir(worldPos); return o; } sampler2D _MainTex; float _Roughness; float3 _LightColor0; // 幾何減衰(V項) マイクロファセットの凹凸に遮れた反射光 inline float V_SmithGGXCorrelated(float ndotl, float ndotv, float alpha) { float lambdaV = ndotl * (ndotv * (1 - alpha) + alpha); float lambdaL = ndotv * (ndotl * (1 - alpha) + alpha); return 0.5f / (lambdaV + lambdaL + 0.0001); } fixed4 frag (v2f i) : SV_Target { half3 normal = normalize(i.worldNormal); half3 viewDir = normalize(i.viewDir); half ndotv = abs(dot(normal, viewDir)); float ndotl = max(0, dot(normal, _WorldSpaceLightPos0.xyz)); float alpha = _Roughness * _Roughness; half V = V_SmithGGXCorrelated(_Roughness,ndotv,alpha); return fixed4(V * _LightColor0.rgb,1); } ENDCG } } }
白色のキューブに緑色のライトを当てています。 右に行くほど_Roughness(粗さ)をあげています。 マイクロファセットにより入射光と反射光が遮断される為、右に行くほどライトの色(緑色)が消えています。