Contenu connexe
Similaire à シェーダだけで世界を創る!three.jsによるレイマーチング (20)
シェーダだけで世界を創る!three.jsによるレイマーチング
- 63. 法線を求める
63
const float EPS = 0.01;
vec3 getNormal( vec3 p ) {
return normalize(vec3(
sceneDist(p + vec3( EPS, 0.0, 0.0 ) ) - sceneDist(p + vec3( -EPS, 0.0, 0.0 ) ),
sceneDist(p + vec3( 0.0, EPS, 0.0 ) ) - sceneDist(p + vec3( 0.0, -EPS, 0.0 ) ),
sceneDist(p + vec3( 0.0, 0.0, EPS ) ) - sceneDist(p + vec3( 0.0, 0.0, -EPS ) )
));
}
勾配の計算 =
xyzそれぞれ少しずらして、
距離関数の差分を計算
- 64. 法線を求める
数学では、f(x,y,z) = 0 で表せる曲面
の法線ベクトル n は
n = (f x, f y, f z) と fの偏微分(勾配)
となると知られている
距離関数は f(x,y,z) = 0 で表せる曲面に等しい
法線n = 距離関数の勾配 として計算可能
64
- 71. 距離関数の無限の繰り返し
mod 演算 で p をループさせることで、
無限に繰り返し表示できる
71
float distSphere(vec3 p, float r) {
return length(p) - r;
}
vec3 onRep(vec3 p, float interval) {
return mod(p, interval) - interval * 0.5;
}
float distScene(vec3 p) {
return distSphere(onRep(p, 4.0), 1.0);
}
- 76. 距離関数の実践編
無限の繰り返し
76
vec2 onRep(vec2 p, float interval) {
return mod(p, interval) - interval * 0.5;
}
float barDist(vec2 p, float interval, float width) {
return length(
max(abs(onRep(p, interval)) - width, 0.0));
}
p ➡ onRep(p, interval)
- 77. 距離関数の実践編
同様に円柱を無限に繰り返し
77
float tubeDist(vec2 p, float interval, float width) {
return length(onRep(p, interval)) - width;
}
float sceneDist(vec3 p) {
float tube_x = tubeDist(p.yz, 0.5, 0.025);
float tube_y = tubeDist(p.xz, 0.5, 0.025);
float tube_z = tubeDist(p.xy, 0.5, 0.025);
return min(min(tube_x, tube_y),tube_z);
}
- 80. 距離関数の実践編
sceneDist全体
80
float sceneDist(vec3 p) {
float bar_x = barDist(p.yz, 1.0, 0.1);
float bar_y = barDist(p.xz, 1.0, 0.1);
float bar_z = barDist(p.xy, 1.0, 0.1);
float tube_x = tubeDist(p.yz, 0.1, 0.025);
float tube_y = tubeDist(p.xz, 0.1, 0.025);
float tube_z = tubeDist(p.xy, 0.1, 0.025);
return max(max(max(min(min(
bar_x, bar_y),bar_z),
-tube_x), -tube_y), -tube_z);
}
- 89. three.js からシェーダを使う
Material の初期化の時に、シェーダのコードを渡すだけ
89
geometry = new THREE.PlaneBufferGeometry(2.0, 2.0);
material = new THREE.ShaderMaterial({
uniforms: {
resolution: { type: "v2", value: new THREE.Vector2(512.0, 512.0) },
},
vertexShader: "頂点シェーダ",
fragmentShader: "フラグメントシェーダ",
});
mesh = new THREE.Mesh(geometry, material);
- 94. 参考資料
我らが @h_doxas 先生の資料
- https://wgld.org/d/glsl/
メガデモの神 iq(@iquilezles) 氏のページ
- http://iquilezles.org/www/index.htm
のWebフロントエンド本 (私の著書)
- https://techbooster.github.io/c89/#scriptoon2
94