テラByteの時代にキロByte

shader又はdemosceneに関係する事

--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);
}