最近は誰でもシェーダーが書ける時代になりました。処理を軽くするためのルールがあるようなのでそのいくつかをメモしておきます。(今後も増える予定です。)ピクセルシェーダー(フラグメントシェーダー)は1ピクセル毎に処理されるため、ちょっとの不手際で、爆発的に処理が重くなります。単純計算ですが、1920x1080の解像度の場合、1フレーム毎に2,073,600回、処理が走ることになります。1フレーム毎に1回実行されるUnity C#のupdate関数の比ではないです。
というわけでメモ。
Ifを使わない
If文は重い。というわけで以下を使います。
lerp(x, y, s)
xにはsが0の時に欲しい数値またはベクトル
yにはsが1の時に欲しい数値またはベクトル
sには1か0を入れます。
これによって、あたかもIF文かのような挙動を実現できます。
仕組み
lerpは線形補完関数といって以下の式になります。
x*(1-s) + y*s
ここで、sは0~1までの少数値で、「重み」(何%使うのか)を表します。
例えば0.3(30%)の重みを指定すると
xを0.7(70%)、yを0.3(30%)にしたものを足した値を返すという構造になっています。
0.5だと丁度中間の値ということですね。ここで、sを0、1にすると0%と100%なのでx、yどちらかの値が純粋にとれるためIf文の代わりになる、というわけです。
前にも書いた気がしますねこれ。
参考
平方根を使わない
平方根を求める処理も、比較的遅い部類の処理になります。
例えば2つのベクトルの大きさ(length)を比較するとき、平方根を求めるのも手ですが、二乗のまま比較すれば軽くなります。
なるべくVertexShaderで処理する
ピクセルシェーダー(フラグメントシェーダー)は前述のように1px毎に処理が走ります。しかし頂点シェーダーは1頂点毎の処理になるため処理回数的にはまだ少ないです。そのため、頂点シェーダーでできることは先にやってしまって、あらかじめデータを頂点に格納しピクセルシェーダーに渡すのが効率がいいようです。