テラByteの時代にキロByte

shader又はdemosceneに関係する事

--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なんてのも、面白いと思う。
今回は過去に作ったモノを見てもらった方が良いと思うので、リンクを書き出します。

neort.io

www.shadertoy.com

www.shadertoy.com

www.shadertoy.com

www.shadertoy.com

今回の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);
}