ゲームプログラミングに20年のキャリアがあるもののシェーダーをバリバリに書くみたいな経験が殆どなかった。
おそらくシェーダーに関する知識はシェーダーに興味があって本気で勉強している学生に劣るだろうが、そんな状態でもリファレンスを見ながら人の書いたシェーダーの不具合修正をしたり拡張をしたりはします。
(市販のゲームでもそういう事全然あります、結構いい加減なものだよ)
でも、機会があったらちゃんと勉強したいなって気持ちは持っていたので、
Unity勉強ついでにシェーダーも勉強したい。
それもホントに初心の初心の部分からだ。

「Shader Laboratory」というサイトに簡単な内容から高度な内容に至るまで、
色々とシェーダーコードを公開してくれている様子なので、
ここにあるコード一行づつ理解していくという地味な作業を行ってみた。
まずは頂点変換と指定カラーに塗りつぶすだけの超簡単シェーダーから。
Shader "ColorShader"
{
// マテリアルインスペクターで操作可能なプロパティ
Properties
{
_Color( "Color", color ) = (1.0, 1.0, 1.0, 1.0)
}
// 実際のシェーダー記述を行う部分
SubShader
{
// タグを記述して実際のレンダリングのタイミングなどを制御する
Tags
{
// 普通のモデルを描画するとレンダラーに伝える
"RenderType" = "Opaque"
}
// パスブロックで1回のジオメトリレンダリングを行う
Pass
{
// CGPROGRAM~ENDCGの区間はCg言語での記述だよという宣言
CGPROGRAM
// 頂点シェーダーの指定
#pragma vertex vert
// フラグメントシェーダーの指定
#pragma fragment frag
// 頂点シェーダーが受け取る構造体の定義
struct appdata
{
float4 vertex : POSITION;
};
// 頂点/フラグメントが使用する構造体
struct v2f
{
float4 pos : SV_POSITION;
};
// 頂点シェーダー
v2f vert( appdata v )
{
v2f o;
// Unityが提供する関数でMVP変換 ↓の計算と同じ意味
// o.pos = mul( UNITY_MATRIX_P, mul( UNITY_MATRIX_V, mul( unity_ObjectToWorld, v.vertex ) ) );
o.pos = UnityObjectToClipPos( v.vertex );
return o;
}
// Propertiesで指定した値を実際にうけとる
float4 _Color;
float4 frag( v2f i ) : SV_Target
{
// カラー値をそのまま返すだけ
return _Color;
}
ENDCG
}
}
}
シェーダーは数学的知識も必要だしとっつき難いしで慣れるまで時間かかりそうだ