Shader : SDFについての備忘録

SDFを”距離場”として捉えてみる。つまり$${f_{sdf}: \R^2 →\R }$$という意味

ここで、このスカラー場$${f_{sdf}: \R^2 →\R }$$の勾配を取ってみたいという願望が湧いてくる。

// .x = f(p)
// .y = ∂f(p)/∂x
// .z = ∂f(p)/∂y
// .yz = ∇f(p) with ‖∇f(p)‖ = 1
vec3 sdgBox( in vec2 p, in vec2 b, float ra )
{
    vec2 w = abs(p)-(b-ra);
    vec2 s = vec2(p.x<0.0?-1:1,p.y<0.0?-1:1);
    
    float g = max(w.x,w.y);
    vec2  q = max(w,0.0);
    float l = length(q);
    
    return vec3(   (g>0.0)?l-ra: g-ra,
                s*((g>0.0)?q/l : ((w.x>w.y)?vec2(1,0):vec2(0,1))));
}

このように勾配を求められる。
以上のように基本的には、勾配は p / f(p) で求まる。
(ref : https://iquilezles.org/articles/distgradfunctions2d/)

  • なぜ分母にfが来ている?→ [0,1]に収める正規化をした結果だから。

一般にsdfは距離場であるのでp/f(p)で正規化ができている。 つまり $${ \left| \frac{p}{length(p)} \right| = \frac{\sqrt{p.x^2 + p.y^2}}{\sqrt{p.x^2 + p.y^2}} = 1}$$
という意味。


今までは二次元の空間で、勾配($${\nabla f}$$)を取っていたが、3次元の空間で勾配を取るとどうなるか。
結論から言うと”法線”になる。

3次元空間でのスカラー場の勾配は”法線”になるし(レイマーチングで`calcNormal()`のように使用されている)、2次元空間でのスカラー場の勾配はそのまま山の等高線のような”勾配”になる。

ちなみにレイマーチングもカメラから徐々にRayを進めて行って、その度RayのPositionの距離場を観測し、それが0に限りなく近づくまでレイマーチするという認識で捉えることもできる。(自分はそのように捉えている。)


「空間に対してスカラー場があるとして、それの勾配を取ったらベクトル場を求められるの、当たり前だけど凄いことだな」と思ったのでこの記事を書いた。

ベクトル場ということは、例えば速度場だったら球が速度が変更されることで、それを用いてObjectが動いて移動していくシミュレーションが出来るということになる。
さらにもっと厳密にシミュレーションしたいとなれば、力場(ベクトル場)を設置して加速度求めればいい話だし。そういうのを「スカラー場を作れば実験できる」という事実に気付いて、面白いなあと。




この記事が気に入ったらサポートをしてみませんか?