人生初心者の雑記

すべてにおいてド素人な人がいろんなことを書くよ

シェーダアート_3 物体の複製

wgld.org | GLSL: オブジェクトの複製 repetition |

wgldさんの >フラグメントシェーダのコード を見ていく


物体の複製
43,18~20,14~16 行目

前回からの変更点はここしかなく、これが今回重要なところだ。
物体を複製したい。具体的には下のように
f:id:stalagmite:20150610132143p:plain

球を等間隔に配置しよう。distanceFunc は、(一番近い)物体と光の先端の最短距離を出す。物体が複数ある場合、どの物体との距離が一番近いかを計算しなければならない。

球の配置の仕方を、図のように、「立方体の中心に球」があるとして、その立方体を等間隔に置くようにすると考える。光の先端が、ある立方体の内側にあるとき、光の先端と最も近い球は、その立方体が囲んでいる球だ。これは、立方体と球との位置関係が対照的だから言える。立方体と非対称的な物体(たとえば、三角錐)を考えた場合、もしかしたら光の先端のある立方体の中の物体よりも、隣の立方体の中の物体との距離の方が近いかもしれない。

vec3 trans(vec3 p){
return mod(p, 4.0) - 2.0;
}

float distanceFunc(vec3 p){
return length(trans(p)) - sphereSize;
}

distanceFunc は、最も近い物体との最短距離を返す関数。中で trans が 使われている。 これは何をしている関数だろうか。


まず、球の配置の仕方は、 「{4s-2,4t-2,4u-2} (s,t,u は整数) 」 の位置に、中心がくるようにおいている。
光の先端 p = {x,y,z} が与えられたとき、pが属する立方体の位置は、

s = (x - mod(x,4.0))/4.0 + 1.0
t = (y - mod(y,4,0))/4.0 + 1.0
u = (z - mod(z,4,0))/4.0 + 1.0

であり、最も近い球の中心oは、

{
ox = (x - mod(x,4,0)) + 2.0,
oy = (y - mod(y,4,0)) + 2.0,
oz = (z - mod(z,4,0)) + 2.0
}
すなわち
o = (p - mod(p,4.0)) + 2.0

最短距離は,

length(p-o) - SphereSize
<=> length(mod(p,4.0)-2.0) - SphereSize
<=> length(trans(p)) - sphereSize (ただし vec3 trans(vec3 p){return mod(p, 4.0) - 2.0;})




かくして、複製された物体と光の先端との最短距離を計算することができた。あとはすべて前回と同じだ。