【UnityShader】VertexShaderとFragmentShaderの基礎 #18
前回の成果
今回やること
VertexShader(頂点シェーダー)とFragmentShaderを理解します。
事前準備
以前までは、
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を使う必要がある
UnityObjectToClipPos(v)
オブジェクト空間からカメラのクリップ座標へ頂点を変換するものです。
行なっていることは、
mul(UNITY_MATRIX_MVP, float4(pos, 1.0))
と同じです。
結果
赤くなれば成功です。
ソースコードにコメント付与
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 } } }
今回はこれで終わりです。
ご視聴ありがとうございました!