Shader 勉強メモ 「サンプルを理解する2」
前々回に予告していたサンプルをやっていきます。
Unity - マニュアル: Vertex and fragment shader examples
法線情報を使ったシェーダーは前にやったので、スカイボックスを反射させるシェーダーから。 解説は追記する予定。
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関連の気になる記事と参考記事
空間とプラットフォームの狭間で - Unityの座標変換にまつわるお話 -