テラByteの時代にキロByte

shader又はdemosceneに関係する事

--shader(GLSL)の小技 13-- ボリュームレンダリング

これは、ボリュームレンダリングです。shadertoyでたまに、見かける方法です。

float sphere(vec3 ro, vec3 rd, float r){
    float b = dot( -ro, rd ),
    inner = b*b - dot(ro,ro) + r*r;
    return inner < 0. ?  -1. : b - sqrt(inner);
}

これは、半径rの球にrayが衝突する点とrayの原点との距離を返す関数。
この返り値をdと置けばro+rd*dで座標が取れる。 最初に半径が小さい球で座標を取る。そして座標を距離関数に入れて距離をとり、2D描写で、色に加算。 次に半径を少し大きくして、同じ事を繰り返していく。
玉ねぎのような感じですかね。それとも雪だるま式加算とでも言うのでしょうか。
説明が抽象的で、ごめんなさい。上手く説明できません。足りないとこはソースを読んで理解してください。 このくらいが限界です。

www.shadertoy.com

sphere関数は、ここから入手しています。

今回のshader (shadertoy rule)

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

float sphere(vec3 ro, vec3 rd, float r){
    float b = dot( -ro, rd ),
    inner = b*b - dot(ro,ro) + r*r;
    return inner < 0. ?  -1. : b - sqrt(inner);
}

// これはraymarchingでも使える普通の距離関数
float deLineBox(vec3 p)
{
    p.xy *=  rotate(iTime);
    p.yz *=  rotate(iTime);
    
    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.01);
    }
    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,-3.5);
    vec3 rd = normalize(vec3(uv,2));   
 
    vec3 col=vec3(0);
    vec3 offset = vec3(0,0,1.6);
    for (float i=10.; i<60.; i++) {
        float d = sphere(ro-offset, rd, i*0.05);
        vec3 p = ro+rd*d;
        float de = map(p);
        col += exp(-de*de*1000.0);
    }
     
    fragColor=vec4(col,1.0);
}