【Unity】Projectorコンポーネントに対応したシェーダーの備忘録

はじめに

タイトル通り。Projectorで投影するためのシェーダーを書くにあたって躓いたところのまとめ。シェーダー素人が書いているのですべての記述がふわふわ。コードブロックの使い方よく分かってないのでコピペしたら改行とかおかしいかも。

シェーダーに書くもの

#include "UnityCG.cginc"
Pass
{
     CGPROGRAM
     #pragma vertex vert
     #pragma fragment frag

     #include "UnityCG.cginc"
     ・・・

これを書かないことはあんまりないと思うけど、一応。

struct v2f{}の中身
struct v2f
{
     ・・・
     float4 uv : TEXCOORD0;
     ・・・
};

大抵の場合、UVはxyの2軸の平面でしか扱わないのでfloat2で書いてあることが多い気がする。後述の関数?でUV座標扱うときにfloat4じゃないといけないっぽいのでfloat4で書いておく。
struct appdate{}の中にもuv : TEXCOORD0;書いてるけど、これはfloat2でも問題なく動いているように見える。どっちが何に使われているのかよく知らない。自分が書いたシェーダーの中ではそもそも使ってないのかもしれない。

float4x4 unity_Projector; float4x4 unity_ProjectorClip;
float4x4 unity_Projector;
float4x4 unity_ProjectorClip;

Propertiesで書いた変数とかのグローバル変数と一緒のとこに書くやつ。とりあえずfloat4x4 unity_Projector;だけあればなんとかなる。

v2f vert(appdata v){}の中身
v2f vert(appdata v)
{
     v2f o;
     o.vertex = UnityObjectToClipPos(v.vertex);
     o.uv = mul(unity_Projector, v.vertex) ;
     return o;
}

o.uv = mul(unity_Projector, v.vertex) ;←ここが大事(たぶん)。投影するためのUV座標をなんやかんやするやつ。

fixed4 frag(v2f i) : SV_Target{}の中身
fixed4 frag(v2f i) : SV_Target{
     ・・・
     float4 uv = UNITY_PROJ_COORD(i.uv);
     ・・・

わざわざ変数を作る必要はないが、とにかくUVをUNITY_PROJ_COORD()に突っ込んでおく。これでいい感じに投影されるようになる(たぶん)。
Textureのサンプリングに使うときはtex2Dproj(_Maintex, UNITY_PROJ_COORD(i.uv));みたいな感じで書くっぽい。StandardAssetの中に入ってるシェーダーにはそう書いてあったので。

おわりに

オブジェクトのUV座標を投影用にいろいろ計算するとこだけ書き換えればとりあえず動く。どういう理屈でなんの計算をやっているのかを解説するだけの知識はないので書いてないけど、↓の記事が参考になるかも。
amagamina.jp
someiyoshino.info