--shader(GLSL)の小技 14-- raycastで面をつくる。
raycastで面をつくる。このやり方は、応用範囲が広いと思ってる。複数の四角を作り、その中で別々のraymarchingも出来たりする。
vec2 rayCastPlane(vec3 ro, vec3 rd, vec3 pos, vec3 nor, vec3 up) { float z = dot(pos-ro,nor)/dot(rd,nor); vec3 p=ro+rd*z, a=p-pos, u=normalize(cross(nor,up)), v=normalize(cross(u,nor)); return vec2(dot(a,u),dot(a,v)); }
中身の説明は、つらいので用法の説明をしておきます。
ro
はrayの原点、rd
はrayの方向、pos
は面の中心点の座標、nor
は面の法線、up
はlookat行列の補助ベクトルと同様のモノ。
返り値uv
は2D描写の時に使う座標と同等と思ってもらえばいいと思う。
これは、raymarchingと同居できる。2.5Dなんてのも、面白いと思う。
今回は過去に作ったモノを見てもらった方が良いと思うので、リンクを書き出します。
今回のshader (shadertoy rule)
// https://www.shadertoy.com/view/4lXyWN vec3 hash(uint i) { uvec3 x = uvec3(123,456,789)*(i+55u); uint k = 1103515245U; x*=k; x = ((x>>2u)^(x.yzx>>1u)^x.zxy)*k; return vec3(x)*(1.0/float(~0U)); } vec2 rayCastPlane(vec3 ro, vec3 rd, vec3 pos, vec3 nor, vec3 up) { float z = dot(pos-ro,nor)/dot(rd,nor); vec3 p=ro+rd*z, a=p-pos, u=normalize(cross(nor,up)), v=normalize(cross(u,nor)); return vec2(dot(a,u),dot(a,v)); } float map(vec2 p) { return abs(length(p)-1.0)-0.1; } void mainImage( out vec4 fragColor, in vec2 fragCoord ) { vec2 uv=(fragCoord*2.0-iResolution.xy)/iResolution.y; vec3 ro=vec3(0,0,-20); vec3 rd=normalize(vec3(uv,2)); vec3 col=vec3(0); for(uint j=1u;j<200u;j++){ // オブジェクトの座標を取得 // 乱数でベクトルを取得し時間を乗算 vec3 q=(hash(j)*2.0-1.0) *(iTime+20.0)*0.2; // この式で-1~1の間を行き来する // イメージで言えば3Dビリヤード q = (abs(fract(q)*2.0-1.0)*2.0-1.0)*15.0; vec2 uv = rayCastPlane(ro,rd,q,normalize(ro-q),vec3(0,1,0)); col = mix(col,vec3(1),smoothstep(0.01,0.0,map(uv))); } fragColor=vec4(col,1.0); }