LYGIA Shader Library

softShadow (lygia/lighting/raymarch/softShadow)

Calculate soft shadows http://iquilezles.org/www/articles/rmshadows/rmshadows.htm

Dependencies:

Use:

<float> raymarchSoftshadow( in <vec3> ro, in <vec3> rd, in <float> tmin, in <float> tmax)

Check it on Github



#ifndef RAYMARCHSOFTSHADOW_ITERATIONS
#define RAYMARCHSOFTSHADOW_ITERATIONS 64
#endif

#ifndef RAYMARCH_SHADOW_MIN_DIST
#define RAYMARCH_SHADOW_MIN_DIST 0.01
#endif

#ifndef RAYMARCH_SHADOW_MAX_DIST
#define RAYMARCH_SHADOW_MAX_DIST 3.0
#endif

#ifndef RAYMARCH_SHADOW_SOLID_ANGLE
#define RAYMARCH_SHADOW_SOLID_ANGLE 0.1
#endif

#ifndef RAYMARCH_MAP_FNC
#define RAYMARCH_MAP_FNC(POS) raymarchMap(POS)
#endif

#ifndef RAYMARCH_MAP_DISTANCE
#define RAYMARCH_MAP_DISTANCE a
#endif

#ifndef FNC_RAYMARCHSOFTSHADOW
#define FNC_RAYMARCHSOFTSHADOW

float raymarchSoftShadow(vec3 ro, vec3 rd, in float mint, in float maxt, float w) {
    float res = 1.0;
    float t = mint;
    for (int i = 0; i < RAYMARCHSOFTSHADOW_ITERATIONS && t < maxt; i++)
    {
        float h = RAYMARCH_MAP_FNC(ro + t * rd).RAYMARCH_MAP_DISTANCE;
        res = min(res, h / (w * t));
        t += clamp(h, 0.005, 0.50);
        if (res < -1.0 || t > maxt)
            break;
    }
    res = max(res, -1.0);
    return 0.25 * (1.0 + res) * (1.0 + res) * (2.0 - res);
}

float raymarchSoftShadow(vec3 ro, vec3 rd, in float tmin, in float tmax) { return raymarchSoftShadow(ro, rd, RAYMARCH_SHADOW_MIN_DIST, RAYMARCH_SHADOW_MAX_DIST, RAYMARCH_SHADOW_SOLID_ANGLE); }
float raymarchSoftShadow(vec3 ro, vec3 rd) { return raymarchSoftShadow(ro, rd, RAYMARCH_SHADOW_MIN_DIST, RAYMARCH_SHADOW_MAX_DIST); }

#endif

Dependencies:

Use:

<float> raymarchSoftshadow( in <float3> ro, in <float3> rd, in <float> tmin, in <float> tmax)

Check it on Github



#ifndef RAYMARCHSOFTSHADOW_ITERATIONS
#define RAYMARCHSOFTSHADOW_ITERATIONS 64
#endif

#ifndef RAYMARCH_SHADOW_MIN_DIST
#define RAYMARCH_SHADOW_MIN_DIST 0.01
#endif

#ifndef RAYMARCH_SHADOW_MAX_DIST
#define RAYMARCH_SHADOW_MAX_DIST 3.0
#endif

#ifndef RAYMARCH_SHADOW_SOLID_ANGLE
#define RAYMARCH_SHADOW_SOLID_ANGLE 0.1
#endif

#ifndef RAYMARCH_MAP_FNC
#define RAYMARCH_MAP_FNC(POS) raymarchMap(POS)
#endif

#ifndef RAYMARCH_MAP_DISTANCE
#define RAYMARCH_MAP_DISTANCE a
#endif

#ifndef FNC_RAYMARCHSOFTSHADOW
#define FNC_RAYMARCHSOFTSHADOW

float raymarchSoftShadow( float3 ro, float3 rd, in float mint, in float maxt, float w ) {
    float res = 1.0;
    float t = mint;
    for (int i = 0; i < RAYMARCHSOFTSHADOW_ITERATIONS && t < maxt; i++)
    {
        float h = RAYMARCH_MAP_FNC(ro + t * rd).RAYMARCH_MAP_DISTANCE;
        res = min(res, h / (w * t));
        t += clamp(h, 0.005, 0.50);
        if (res < -1.0 || t > maxt)
            break;
    }
    res = max(res, -1.0);
    return 0.25 * (1.0 + res) * (1.0 + res) * (2.0 - res);
}

float raymarchSoftShadow( float3 ro, float3 rd, in float tmin, in float tmax) { return raymarchSoftShadow(ro, rd, RAYMARCH_SHADOW_MIN_DIST, RAYMARCH_SHADOW_MAX_DIST, RAYMARCH_SHADOW_SOLID_ANGLE); }
float raymarchSoftShadow( float3 ro, float3 rd) { return raymarchSoftShadow(ro, rd, RAYMARCH_SHADOW_MIN_DIST, RAYMARCH_SHADOW_MAX_DIST); }

#endif

Dependencies:

Use:

<float> raymarchSoftshadow( in <float3> ro, in <float3> rd, in <float> tmin, in <float> tmax)

Check it on Github



#ifndef RAYMARCHSOFTSHADOW_ITERATIONS
#define RAYMARCHSOFTSHADOW_ITERATIONS 16
#endif

#ifndef RAYMARCH_MAP_FNC
#define RAYMARCH_MAP_FNC(POS) raymarchMap(POS)
#endif

#ifndef RAYMARCH_MAP_DISTANCE
#define RAYMARCH_MAP_DISTANCE w
#endif

#ifndef FNC_RAYMARCHSOFTSHADOW
#define FNC_RAYMARCHSOFTSHADOW

inline __host__ __device__ float raymarchSoftShadow(const float3& ro, const float3& rd, float tmin, float tmax, float k ) {
    float res = 1.0f;
    float t = tmin;
    float ph = 1e20;
    for (int i = 0; i < RAYMARCHSOFTSHADOW_ITERATIONS; i++) {
        float h = RAYMARCH_MAP_FNC(ro + rd*t).RAYMARCH_MAP_DISTANCE;

        if (t > tmax)
            break;

        else if (h < 0.001) {
            res = 0.0;
            break;
        }

        float y = h * h / (2.0f * ph);
        float d = sqrt( h * h - y * y);
        res = min( res, k * d / max(0.0f, t - y) );
        ph = h;
        t += h;
    }
    return res;
}

inline __host__ __device__ float raymarchSoftShadow(const float3& ro, const float3& rd, float tmin, float tmax) { return raymarchSoftShadow(ro, rd, tmin, tmax, 12.0f); }
inline __host__ __device__ float raymarchSoftShadow(const float3& ro, const float3& rd) { return raymarchSoftShadow(ro, rd, 0.05f, 5.0f); }

#endif

Examples

LYGIA is dual-licensed under the Prosperity License and the Patron License for sponsors and contributors.

Sponsors and contributors are automatically added to the Patron License and they can ignore the any non-commercial rule of the Prosperity Licensed software (please take a look to the exception).

It's also possible to get a permanent comercial license hook to a single and specific version of LYGIA.

Get the latest news and releases

Sign up for the news letter bellow, joing the LYGIA's channel on Discord or follow the Github repository