Unity Days

Unity や VR/AR に関すること。たまにblender。

Shader 勉強メモ 「サンプルを理解する2」

前々回に予告していたサンプルをやっていきます。

Unity - マニュアル: Vertex and fragment shader examples

法線情報を使ったシェーダーは前にやったので、スカイボックスを反射させるシェーダーから。 解説は追記する予定。

f:id:Dmiyamo3:20170311142914p:plain

Shader "Unlit/SkyReflection"
{
    SubShader
    {
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

            // vertで値を入力し、fragで利用する値を定義
            struct v2f {
                half3 worldRefl : TEXCOORD0;
                float4 pos : SV_POSITION;
            };

            v2f vert (float4 vertex : POSITION, float3 normal : NORMAL)
            {
                v2f o;
                // オブジェクト空間の頂点位置をクリップ空間に変換
                o.pos = UnityObjectToClipPos(vertex);
                // 定義済値、オブジェクト空間→ワールド空間へ変換する行列と
                // オブジェクト空間の頂点位置の行列積
                float3 worldPos = mul(_Object2World, vertex).xyz;
                // compute world space view direction
                float3 worldViewDir = normalize(UnityWorldSpaceViewDir(worldPos));
                // world space normal
                float3 worldNormal = UnityObjectToWorldNormal(normal);
                // world space reflection vector
                o.worldRefl = reflect(-worldViewDir, worldNormal);
                return o;
            }
        
            fixed4 frag (v2f i) : SV_Target
            {
                // sample the default reflection cubemap, using the reflection vector
                half4 skyData = UNITY_SAMPLE_TEXCUBE(unity_SpecCube0, i.worldRefl);
                // decode cubemap data into actual color
                half3 skyColor = DecodeHDR (skyData, unity_SpecCube0_HDR);
                // output it!
                fixed4 c = 0;
                c.rgb = skyColor;
                return c;
            }
            ENDCG
        }
    }
}

おまけ

ビルドインシェーダーの関数はドキュメントに書かれてないものがあるので、ソースコードを調べてみました。 Unity - Download Archive:ビルドインシェーダーのソースコードがダウンロードできます。 例えば、UnityObjectToWorldNormal()のコード。こんな感じになってます。

// Transforms normal from object to world space
inline float3 UnityObjectToWorldNormal( in float3 norm )
{
#ifdef UNITY_ASSUME_UNIFORM_SCALING
    return UnityObjectToWorldDir(norm);
#else
    // mul(IT_M, norm) => mul(norm, I_M) => {dot(norm, I_M.col0), dot(norm, I_M.col1), dot(norm, I_M.col2)}
    return normalize(mul(norm, (float3x3)unity_WorldToObject));
#endif
}

Shader関連の気になる記事と参考記事

Shader Debugger [ Unity ] と[ Visual Studio ] で [ DirectX 11 ] [Microsoft HLSL Shader Debugger ] [シェーダーのデバッガー] を使ってみる。00200 | Whaison JUGEM! StudyNoteBook .

空間とプラットフォームの狭間で - Unityの座標変換にまつわるお話 -

内蔵(ビルドイン)シェーダのソースコードの配布ページ - 強火で進め

Unity - マニュアル: ビルトインシェーダーヘルパー機能