--shader(GLSL)の小技 13-- ボリュームレンダリング
これは、ボリュームレンダリングです。shadertoyでたまに、見かける方法です。
float sphere(vec3 ro, vec3 rd, float r){ float b = dot( -ro, rd ), inner = b*b - dot(ro,ro) + r*r; return inner < 0. ? -1. : b - sqrt(inner); }
これは、半径rの球にrayが衝突する点とrayの原点との距離を返す関数。
この返り値をd
と置けばro+rd*d
で座標が取れる。
最初に半径が小さい球で座標を取る。そして座標を距離関数に入れて距離をとり、2D描写で、色に加算。
次に半径を少し大きくして、同じ事を繰り返していく。
玉ねぎのような感じですかね。それとも雪だるま式加算とでも言うのでしょうか。
説明が抽象的で、ごめんなさい。上手く説明できません。足りないとこはソースを読んで理解してください。
このくらいが限界です。
sphere関数は、ここから入手しています。
今回のshader (shadertoy rule)
mat2 rotate(float a) { return mat2(cos(a),sin(a),-sin(a),cos(a)); } float sphere(vec3 ro, vec3 rd, float r){ float b = dot( -ro, rd ), inner = b*b - dot(ro,ro) + r*r; return inner < 0. ? -1. : b - sqrt(inner); } // これはraymarchingでも使える普通の距離関数 float deLineBox(vec3 p) { p.xy *= rotate(iTime); p.yz *= rotate(iTime); float de = 1e9; p = abs(p)-0.6; for(int i=0; i<3;i++) { vec3 q =p; q[i]=max(0.0,q[i]); de= min(de,length(q)-0.01); } return de; } float map(vec3 p) { return deLineBox(p); } void mainImage( out vec4 fragColor, in vec2 fragCoord ) { vec2 uv=(fragCoord*2.0-iResolution.xy)/iResolution.y; vec3 ro = vec3(0,0,-3.5); vec3 rd = normalize(vec3(uv,2)); vec3 col=vec3(0); vec3 offset = vec3(0,0,1.6); for (float i=10.; i<60.; i++) { float d = sphere(ro-offset, rd, i*0.05); vec3 p = ro+rd*d; float de = map(p); col += exp(-de*de*1000.0); } fragColor=vec4(col,1.0); }