--shader(GLSL)の小技 09-- オブジェクトをある点に向かす
オブジェクトをある点に向かすには、mat3()を使います。lookat行列と同じ作り方をします。
違うのは、かける順番。
本当は逆行列を使うのでしょうけど、GLSLの場合は、かける順番を後にすると逆行列扱いになるようです。
// point at vec3 w=normalize(ta-q); vec3 u=normalize(cross(w,vec3(0,1,0))); mat3 m=mat3(u,cross(u,w),w); q = (p-q)*m;
pointAt行列部分の抜粋。
今回のshader (shadertoy rule)
mat2 rotate(float a) { return mat2(cos(a),sin(a),-sin(a),cos(a)); } float udRoundBox( vec3 p, vec3 b, float r ) { return length(max(abs(p)-b,0.0))-r; } float map(vec3 p) { vec3 ta=vec3(0); ta.y+=sin(iTime)*3.; float de=length(p-ta)-0.5; for(float i=1.0; i>0.0; i-=1.0/8.0) { vec3 q=vec3(rotate(radians(360.0)*i)*vec2(3,0),0).xzy; // point at vec3 w=normalize(ta-q); vec3 u=normalize(cross(w,vec3(0,1,0))); mat3 m=mat3(u,cross(u,w),w); q = (p-q)*m; de = min(de,udRoundBox(q,vec3(0.5),0.1)); q.z-=0.7; de = min(de,length(q)-0.3); } return de; } vec3 doColor(vec3 p) { return vec3(0.3,0.5,0.8); } void mainImage( out vec4 fragColor, in vec2 fragCoord ) { vec2 uv=(fragCoord*2.0-iResolution.xy)/iResolution.y; vec3 ro=vec3(0,3,-7); ro.zx*=rotate(iTime*0.5); vec3 rd=normalize(vec3(uv,2)); vec3 w=normalize(-ro); vec3 u=normalize(cross(w,vec3(0,1,0))); rd=mat3(u,cross(u,w),w)*rd; float d,i,t=0.0; vec3 p=ro; vec3 col=vec3(0); for(i=1.0;i>0.0;i-=1./50.0) { t+=d=map(p); if(d<0.001) { col=doColor(p); col*=i*i; break; } p+=rd*d; } fragColor=vec4(col,1.0); }