ShaderTips

シェーダーTips

主にUnityシェーダーについての記事を書いています。

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

フレネル反射とは?

フレネル反射とは、視線と法線が直角になる部分ほど反射成分が大きくなることで背景がより強く見える現象で、水やプラスチックなどの非金属よく見られます。

f:id:Ny_Program:20210716163545g:plain

フルネルの近似式

フレネルの式 - Wikipediaより引用

フルネルの近似式をシェーダーにするとこうなります。

half fresnel = _F0 + (1.0h - _F0) * pow(1.0h - i.vdotn, 5);

_F0はその物体でどれだけフレネル反射が出やすいかを表しており。Propertiesから設定できるようにします。

近似式でcosθだった部分は法線と視線ベクトルの内積です。

実装

Shader "Fresnel"
{
    Properties
    {
        [PowerSlider(0.1)] _F0 ("F0", Range(0.0, 1.0)) = 0.02
    }
    SubShader
    {

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            half _F0;

            struct appdata
            {
                float4 vertex : POSITION;
                half3 normal : NORMAL;
            };

            struct v2f
            {
                float4 vertex : SV_POSITION;
                half vdotn      : TEXCOORD1;
            };

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.vdotn = dot(normalize(ObjSpaceViewDir(v.vertex)), v.normal);
                return o;
            }
            
            fixed4 frag (v2f i) : SV_Target
            {
               half fresnel = _F0 + (1.0h - _F0) * pow(1.0h - i.vdotn, 5);
                return fresnel;
            }
            ENDCG
        }
    }
}

最後に

法線と視線ベクトルの内積計算ではオブジェクト空間で計算しました。 ついつい、脳死でワールド空間で計算しがちでしたが、法線の座標変換を行っていないので、こちらの方が良いですね。

数字の後に「h」がありますが、これはhalf型を表しています。

参考

【Unity】【シェーダ】フレネル反射の実装 - LIGHT11

フレネルの式 - Wikipedia

[Notes] cg Unity Shader learning basic grammar - Programmer Sought