UnityのShader勉強2 基本の形
はじめに
頂点/フラグメントシェーダーを使う際の基本の形をおさらいします。
ぶっちゃけ詳しい説明は他サイトを見たほうがよいです。
参考:
Unity のシェーダの基礎を勉強してみたのでやる気出してまとめてみた - 凹みTips
基本の形
まずは頂点/フラグメントシェーダーの基本の形です。
Create>Shader>UnlitShaderにてShaderを作成するとこんな感じになります。
Shader "Unlit/TestShader" { Properties { _MainTex ("Texture", 2D) = "white" {} } SubShader { Tags { "RenderType"="Opaque" } LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag // make fog work #pragma multi_compile_fog #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; UNITY_FOG_COORDS(1) float4 vertex : SV_POSITION; }; sampler2D _MainTex; float4 _MainTex_ST; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); UNITY_TRANSFER_FOG(o,o.vertex); return o; } fixed4 frag (v2f i) : SV_Target { // sample the texture fixed4 col = tex2D(_MainTex, i.uv); // apply fog UNITY_APPLY_FOG(i.fogCoord, col); return col; } ENDCG } } }
これをマテリアルにあててゲームオブジェクトに与えるとこうなります。
(spriteのみ画像がないと表示されないため白塗りのspriteを適用)
見事に真っ白です。
このままではわかりずらいので、コードを書き換えて少なくします。
Shader "Unlit/TestShader" { SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag struct appdata { float4 vertex : POSITION; }; struct v2f { float4 vertex : SV_POSITION; }; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); return o; } fixed4 frag () : SV_Target { fixed4 col = fixed4(1,1,1,1); return col; } ENDCG } } }
(見た目は変わらないので割愛)
SubShaderやPassの説明は省略します。
重要なのは
CGPROGRAM #pragma vertex vert #pragma fragment frag struct appdata { float4 vertex : POSITION; }; struct v2f { float4 vertex : SV_POSITION; }; v2f vert(appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); return o; } fixed4 frag() : SV_Target { fixed4 col = fixed4(1,0,0,1); return col; } ENDCG
の部分です。
上下にあるCGPROGRAM~ENDCG内に処理を書きます。
そして
#pragma vertex vert
#pragma fragment frag
この二つが頂点の位置決める関数とピクセルに塗る色を決める関数を指示します。
この場合はvert関数 frag関数を使用すると指示しています。
vert関数の説明の前にappdataとv2fを少し考えます。
struct appdata { float4 vertex : POSITION; }; struct v2f { float4 vertex : SV_POSITION; };
struct appdataにてモデルから頂点やUV、法線などの情報を受け取ります。
モデルなどは三次元情報なのでディスプレイに表示させるために変換します。
struct v2f では変換後の情報を保持します。
今回は頂点情報のみを取得しています。
POSITIONは頂点情報
SV_POSITIONは変換後の頂点情報です。
詳しくは
(ちなみに名前は何でもよくて、v2fはvertex To Fragmentの略らしく慣習的にこの名前によくします。appdataをInputに変えたり人それぞれ好みのつけ方をしています。)
これらをどう使うかは
v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); return o; }
appdataで受け取った値を、変換してv2fで返します。
o.vertex=UnityObjectToClipPos(v.vertex);
これは変換用の関数です。
最後にピクセルに色を塗ります。
fixed4 frag () : SV_Target { fixed4 col = fixed4(1,1,1,1); return col; }
フラグメントでは範囲内のピクセルすべてにこの関数を実行して値を返します。
:〇〇では返した値をどうするかという意味で、ほとんどはSV_Targetを指定します。
これは色を塗ってくれという命令です。
fixedとは浮動小数点のデータタイプでc#でいうところのfloatにあたります。
なにもつけなければそのまま値は一つですが、語尾に4がつけば値を4つ持ちます。
他にはfloat、half、fixed,intが使えます。
どれを選ぶかは精度や用途によって使い分け精度が高いほど負荷が高くなります。
高精度 | float |
中精度 | half |
低精度 | fixed |
intは整数で配列のインデックスやカウンターにも使えますが、あまりみかけません。
詳しくは
テクスチャを扱うデータタイプは別記事で書きます。
さて、さきほど返していたfixed4(1,1,1,1)ですがrgbaの値です。
すべてが1なので白になります。
これを(1,0,0,1)にすると
はい、真っ赤になりました。
おわり
今回はここまでにします。
次回は外部からの入力です。