SuiTechLog

Unity,Arduino,RaspberryPiなど、モノづくり系を気ままに書き残すブログ。

シェーダー書きはじめTIPs(おもにUnity)


 最近は誰でもシェーダーが書ける時代になりました。処理を軽くするためのルールがあるようなのでそのいくつかをメモしておきます。(今後も増える予定です。)ピクセルシェーダー(フラグメントシェーダー)は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文の代わりになる、というわけです。

前にも書いた気がしますねこれ。

 

参考

lerp (DirectX HLSL)

 

平方根を使わない

平方根を求める処理も、比較的遅い部類の処理になります。

例えば2つのベクトルの大きさ(length)を比較するとき、平方根を求めるのも手ですが、二乗のまま比較すれば軽くなります。

 

なるべくVertexShaderで処理する

 ピクセルシェーダー(フラグメントシェーダー)は前述のように1px毎に処理が走ります。しかし頂点シェーダーは1頂点毎の処理になるため処理回数的にはまだ少ないです。そのため、頂点シェーダーでできることは先にやってしまって、あらかじめデータを頂点に格納しピクセルシェーダーに渡すのが効率がいいようです。