金属におけるフレネル反射の考え方とシェーダにおける実装についてまとめました。
すべての物質はフレネル反射をする
フレネル反射とは、視線と法線が直角になる部分ほど反射率が大きくなる現象で、
水やプラスチックなどの物体でわかりやすく見られる物理現象です。
上記でわかりやすくと書いたのは、実は金属もわかりづらいけどフレネル反射をするためです。
次の資料を見ると、銅やアルミもフレネル反射をしていることがわかります。
つまり、金属はフレネル反射の計算式のの値が大きい物質、と捉えることができそうです。
フレネル反射の記事 より
シェーダで表現する
シェーダでは_Metalness
みたいなプロパティを入力値として、は0.02(水)から0.95(銅)を
float f0 = lerp(0.02, 0.95, _Metalness)
とかしたらいいのかなと思いました。
が、その処理負荷を掛けるくらいなら_Metalness
をそのままの値に入れちゃっても大して変わらなそうです。
Shader "FresnelReflection" { Properties { _Metalness ("Metalness", Range(0, 1)) = 0 } SubShader { Tags { "RenderType"="Opaque" } 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; half vdotn : TEXCOORD1; }; float _Metalness; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); half3 viewDir = normalize(ObjSpaceViewDir(v.vertex)); o.vdotn = dot(viewDir, v.normal.xyz); return o; } fixed4 frag (v2f i) : SV_Target { // 金属性に応じてF0を変える half f0 = _Metalness; half fresnel = f0 + (1.0h - f0) * pow(1.0h - i.vdotn, 5); return fresnel; } ENDCG } } }
使いやすくするならインスペクタから物質の種類を選んでを入れられるようにしたりでしょうか。