テラByteの時代にキロByte

shader又はdemosceneに関係する事

--shader(GLSL)の小技 11-- rayの勢いを抑えて中途半端な距離を利用する

今回の奴は最近みつけたスキルです。 ネーミング的にはゴーストなんて呼ぶのが良いかななんて思ってます。
使用例として

www.shadertoy.com

vec3 col=vec3(0);
    for(i=1.0;i>0.0;i-=1./30.0)
    {
        t+=d=map(p)*(0.2*sin(iTime)+0.6);
        if(d<0.001)
        {
            if(uv.y>0.0) col+=i*i;
            break;
        }
        p+=rd*d;
    }
    if(uv.x>0.0) col += vec3(1,0,0)*exp(-d*d*5.0);

画面の上半分は、rayが衝突した時の描写です。if(uv.y>0.0) col+=i*i;
画面の右半分は、raymarchig loopを抜けたあと距離を使って2D描写のようにしたもの。 if(uv.x>0.0) col += vec3(1,0,0)*exp(-d*d*5.0);
ちょっと実験的に書いてます。
このraymarchig loopは30回と通常より少なく設定して、t+=d=map(p)*(0.2*sin(iTime)+0.6); とmap関数に1以下の定数をかけ、わざとrayを衝突しないようにしています。
ここでの狙いは、衝突してないけど近くにいる距離をつくることで、2D描写のスキルを使ってオーラのような表現をつくることです。
loop回数とか,map関数の距離とかのチューニングで、わりとアナログなノリで絵を出すスキルです。

今回のshader (shadertoy rule)

mat2 rotate(float a)
{
    return mat2(cos(a),sin(a),-sin(a),cos(a));
}

float deLineBox(vec3 p)
{
    p.xy*=rotate(iTime*0.5);
    p.yz*=rotate(iTime*0.5);
    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.02);
    }
    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,-2);
    vec3 rd=normalize(vec3(uv,2));
    vec3 ta=vec3(0);
    vec3 w=normalize(ta-ro);
    vec3 u=normalize(cross(w,vec3(0,1,0)));
    vec3 v=cross(u,w);
    mat3 lookat=mat3(u,v,w);
    rd=lookat*rd;
    float d,i,t=0.0;
    vec3 p=ro;
    vec3 col=vec3(0);
    for(i=1.0;i>0.0;i-=1./30.0)
    {
        t+=d=map(p)*(0.2*sin(iTime)+0.6);
        if(d<0.001)
        {
            if(uv.y>0.0) col+=i*i;
            break;
        }
        p+=rd*d;
    }
    if(uv.x>0.0) col += vec3(1,0,0)*exp(-d*d*5.0);
    fragColor=vec4(col,1.0);
}