シェーダー関数(Unityで使うCg/HLSL)
ものすごくやさしく解説したCg/HLSL言語の関数説明。
Reference
See Also
Draw Graph
https://gyazo.com/6c4e53bb3465d9ddf45ab1bf696385f2.png
step
ある値よりも大きいか?小さいか?によって1か0を返すよ。bool(if文)とか二項演算子のかわりにも使えるよ。
smoothstep
徐々にstepするよ。ある値からある値までの間で、0から1までの間の値をなめらかなかんじで返すよ。stepだとギザギザしちゃう場合に使うよ。
frac
小数部を返すよ。2.34を与えると、0.34が返ってくる。Timeを与えて、周期的な動きを作ったりできて、0から1までに値が変わっていった後、また0に戻って1に進む。
distance
ベクトルを2つ渡すと距離を返してくれるよ。ピタゴラスの定理だね。
シェーダーやフォントの世界では、ディスタンスフィールドっていうかっこいい名前の技があるよ。
レイマーチングだとこれではなくlengthが多用されるよ。ふたつの座標で引き算をすれば、distanceとlengthを書き換えることができる。こんなかんじにすればいい。
code:distance.hlsl
distance(p, q);
length(p - q);
sin
cos
三角関数はとにかくすごく重要なんだ。あらゆるすべての基本になるし、周期的を数字を作ったりできる。
abs
絶対値を返してくれる。シェーダーでは0から1までの数字を作るということを思い出してみよう。たとえば三角関数で0から-1までのあいだの数字を、0から1までに置き換えることができる。
pow
階乗を計算するよ。
sqrt
ルートを計算するよ。
lerp
線形補完ってやつをしてくれる。ある座標と別の座標を知っていて、その間の座標を求めたい時に使えるんだ。
dot
内積を取って0から1までのあいだの値を返せるよ。これを使えばキャラの顔にリムライトの影を描けるよ。
saturate
与えられた値を、0から1のあいだにおさめて結果を返してくれる。マイナスは0にしてくれるし、1を超えていたら1にしてくれるよ。
clamp
ある値を与えて、それを特定の範囲の中におさまるように変換してくれる。0から1までの数字を作るって用途ですごく便利だし、もっと別の範囲を選んでもいいよ。
ShaderGraphではremapというノードだよ。
atan2
これはグラフで見た方がいい。xとyの値がわかっているなら、atan2でその原点からの角度を出してくれるよ。つまり、y=axの直線上にある点なら、同じ結果が戻ってくるよ。
arc tangentはすごく重要だよ。シューティングゲームだと、自機に向かって飛んでくる敵弾の計算で使うよ。
noise
ランダムな数字を使うことができる。自然っぽく見えるパーリンノイズっていうやつらしいよ。
ノイズ関数については、伝統的なやり方で以下のような計算式が使われてきたりしたよ。
code:Shader
fract(sin(dot(co.xy,vec2(12.9898,78.233))) * 43758.5453);
※UnityのシェーダーではCg言語が主に使われます。(Unityからシェーダーを作成したときに、内容にCGPROGRAMと書かれているのは、Cg言語を使うということを指しています)
Cg言語はHLSL言語と大部分が似ていますが、noise関数はありません。GitHubでkeijiro神のnoiseやsnoise関数を探してコピペして使いましょう。
max
min
2つの値を比べて、大きい方または小さい方を返すよ。
レイマーチングだとこの関数は重要で、「2つのオブジェクトを同時に表示するのにminを使う」「1つのオブジェクトからもうひとつのオブジェクトの形を引き算で削り取るのにmaxを使う」というやり方があるよ。
smooth min
まろやかなmin関数。エクスポネンシャルを使ったりしますが、それ以外の実装もあります。
code:Shader
// smooth min
// exponential smooth, k=32
float sminEx(float a, float b, float k)
{
float res = exp2(-k * a) + exp2(-k * b);
return -log2(res) / k;
}
// polynomial smooth, k=0.1
float sminPoly(float a, float b, float k)
{
float h = clamp(0.5 + 0.5 * (b - a) / k, 0.0, 1.0);
return lerp(b, a, h) - k * h * (1.0 - h);
}
// power smooth, k=8
float sminPow(float a, float b, float k)
{
a = pow(a, k);
b = pow(b, k);
return pow((a * b) / (a + b), 1.0 / k);
}
floor
ceil
切り上げ、切り捨てをして、与えられた数字の整数部を返すよ。天井とか床って表現をするところがまたいい。
cross
外積。2つのベクトルを与えて、その両方に直交するベクトルを返してくれます。
transpose
転置行列を返します。