【Unity】【シェーダ】フレネル反射と金属

金属におけるフレネル反射の考え方とシェーダにおける実装についてまとめました。

すべての物質はフレネル反射をする

フレネル反射とは、視線と法線が直角になる部分ほど反射率が大きくなる現象で、
水やプラスチックなどの物体でわかりやすく見られる物理現象です。

light11.hatenadiary.com

上記でわかりやすくと書いたのは、実は金属もわかりづらいけどフレネル反射をするためです。
次の資料を見ると、銅やアルミもフレネル反射をしていることがわかります。

f:id:halya_11:20181215120201p:plain:w500
https://blog.selfshadow.com/publications/s2012-shading-course/hoffman/s2012_pbs_physics_math_notes.pdf より

つまり、金属はフレネル反射の計算式の {F_{0}}の値が大きい物質、と捉えることができそうです。

f:id:halya_11:20181215121352p:plain
フレネル反射の記事 より

シェーダで表現する

シェーダでは_Metalnessみたいなプロパティを入力値として、 {F_{0}}は0.02(水)から0.95(銅)を
float f0 = lerp(0.02, 0.95, _Metalness)とかしたらいいのかなと思いました。

が、その処理負荷を掛けるくらいなら_Metalnessをそのまま {F_{0}}の値に入れちゃっても大して変わらなそうです。

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
        }
    }
}

使いやすくするならインスペクタから物質の種類を選んで {F_{0}}を入れられるようにしたりでしょうか。

関連

light11.hatenadiary.com

参考

フレネルの式 - Wikipedia

https://blog.selfshadow.com/publications/s2012-shading-course/hoffman/s2012_pbs_physics_math_notes.pdf