知識0からのUnityShader勉強

知識0からのUnityShader勉強

UnityのShaderをメインとして、0から学んでいくブログです。

【UnityShader】VertexShaderとFragmentShaderの基礎 #18

前回の成果

soramamenatan.hatenablog.com

今回やること

VertexShader(頂点シェーダー)とFragmentShaderを理解します。

tsumikiseisaku.com

tips.hecomi.com

事前準備

f:id:soramamenatan:20190823154453p:plain

以前までは、
Create/Shader/Standard Surface Shader
でShaderを作成していたのですが、今回は
Create/Shader/Unlit Shader
でShaderを作成してください。

ソースコード

Shader "Unlit/SimpleVertexFragment" {
    SubShader {
        Pass {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            float4 vert(float4 v:POSITION) : SV_POSITION {
                return UnityObjectToClipPos(v);
            }

            fixed4 frag() : COLOR {
                return fixed4(1.0f, 0.0f, 0.0f, 1.0f);
            }
            ENDCG
        }
    }
}

こちらは最小のVertexShader/FragmentShaderになります。
frag関数の中で赤色を返しているように見えます。

新しく出てきた箇所について、一つ一つ説明していこうと思います。

Pass

いつ、どのようにしてレンダリングするべきかを指定するものです。

具体的な内容は下記をご覧ください。

Unityでは、シェーダーと呼ばれるものに、実際には複数のシェーダーを含めることができます。何かがレンダリングされると、基本パスは頂点情報(メッシュ)が頂点関数(頂点シェーダー)によって処理され、画面空間での位置が計算され、ラスタライズに必要な追加データが計算されます。そのデータはフラグメント関数(別名フラグメントシェーダーまたはピクセルシェーダー)に渡されます。フラグメント関数は、各ポリゴンがカバーする画面上の各ピクセルに対して1回実行され、最終的に各ピクセルのデータを格納します。最終的に表示されます。

これが1つのパスです。メッシュ、頂点、ピクセルシェーダーの組み合わせで、ピクセルデータが書き込まれます。

https://forum.unity.com/threads/what-is-a-shader-pass.381970/:より引用

vertex vert, fragment frag

SurfaceShaderを定義する際に、

// pragma宣言 surfaceShaderを使用するよ 関数名
#pragma surface surf

とあったのですが、これと同じです。

// pragma宣言 vertexShaderを使用するよ 関数名
#pragma vertex vert

// pragma宣言 fragmentShaderを使用するよ 関数名
#pragma fragment frag

float4 vert(float4 v:POSITION) : SV_POSITION

これは頂点ごとに実行される頂点シェーダー関数です。
戻り値に頂点座標となるfloat4型もしくは、float4型を含む構造体を指定する必要があります。
そして、戻り値のセマンティクスにはSV_POSITIONもしくは、SV_POSITIONを含む構造体を指定する必要があります。

セマンティクス

入力変数(引数)と出力変数(戻り値)が何を意味するものかを示すものです。

入力

セマンティクス 用途
float4 POSITION モデルのローカル頂点座標
float3 NORMAL 頂点の法線
float4 TEXCOORD0 1つ目のUV座標
float4 TEXCOORD1 2つ目のUV座標
float4 TANGENT 接戦ベクトル
float4 COLOR 頂点毎の色

出力

セマンティクス 用途
float4 SV_POSITION MVP変換後の座標
float3 NORMAL MVP変換後の法線
float4 TEXCOORD0 1番目のテクスチャのUV座標
float4 TEXCOORD1 2番目のテクスチャのUV座標
float4 TANGENT 接戦ベクトル
floar4 COLOR0 線形補間された頂点の色
float4 COLOR1 線形補間された頂点の色
Any Any ユーザーが定義できるフィールド

※COLOR0とCOLOR1の違いは、COLOR1がFragmentShaderにデータを渡す際にappdata構造体を使用できなく、v2fを使う必要がある

answers.unity.com

UnityObjectToClipPos(v)

オブジェクト空間からカメラのクリップ座標へ頂点を変換するものです。

行なっていることは、

mul(UNITY_MATRIX_MVP, float4(pos, 1.0))

と同じです。

結果

f:id:soramamenatan:20190827201335p:plain

赤くなれば成功です。

ソースコードにコメント付与

Shader "Unlit/SimpleVertexFragment" {
    // Shaderの中身を記述
    SubShader {
        // レンダリングの方式
        Pass {
            // cg言語記述
            CGPROGRAM
            // vertexShaderの宣言
            #pragma vertex vert
            // fragmentShaderの宣言
            #pragma fragment frag

            // vert関数
            float4 vert(float4 v:POSITION) : SV_POSITION {
                // クリップ座標に変換
                return UnityObjectToClipPos(v);
            }

            // frag関数
            fixed4 frag() : COLOR {
                // 赤色にする
                return fixed4(1.0f, 0.0f, 0.0f, 1.0f);
            }
            // Shaderの記述終了
            ENDCG
        }
    }
}

今回はこれで終わりです。
ご視聴ありがとうございました!