Skip to content

raymarch shadows

BLOKS Shader Bulletin Board

raymarch shadows

By RJ Shelton June 9, 2026

Shader Preview Unavailable

This realtime shader may be too intensive for your current device or browser.

Shader Code
float map(vec3 p)
{
    return length(p) - 1.0;
}

float shadow(vec3 ro, vec3 rd)
{
    float res = 1.0;
    float d = 0.02;

    for(int i = 0; i < 32; i++)
    {
        vec3 p = ro + rd * d;

        float ds = map(p);

        res = min(res, 8.0 * ds / d);

        d += clamp(ds, 0.02, 0.2);
    }

    return clamp(res, 0.0, 1.0);
}

vec3 getNormal(vec3 p)
{
    vec2 e = vec2(0.001, 0.0);

    return normalize(vec3(
        map(p + e.xyy) - map(p - e.xyy),
        map(p + e.yxy) - map(p - e.yxy),
        map(p + e.yyx) - map(p - e.yyx)
    ));
}

void mainImage(out vec4 fragColor, in vec2 fragCoord)
{
    vec2 uv = fragCoord.xy / iResolution.xy;

    vec2 p = uv * 2.0 - 1.0;

    p.x *= iResolution.x / iResolution.y;

    vec3 ro = vec3(0.0, 0.0, -4.0);
    vec3 rd = normalize(vec3(p, 1.5));

    float d = 0.0;

    vec3 color = vec3(0.02, 0.04, 0.08);

    for(int i = 0; i < 64; i++)
    {
        vec3 pos = ro + rd * d;

        float ds = map(pos);

        if(ds < 0.001)
        {
            vec3 normal = getNormal(pos);

            vec3 lightDir =
                normalize(vec3(1.0, 1.0, -1.0));

            float diff =
                max(dot(normal, lightDir), 0.0);

            float sh =
                shadow(pos + normal * 0.01, lightDir);

            color += vec3(1.0, 0.3, 0.8)
                     * diff * sh;

            break;
        }

        d += ds;
    }

    fragColor = vec4(color, 1.0);
}

← Back to Shader Bulletin Board