LYGIA Shader Library

arrowSDF (lygia/sdf/arrowSDF)

Distance function for an arrow. Returns float. Originally from https://www.shadertoy.com/view/NttcW8

Use:

arrowSDF(<vec3> v, <vec3> start, <vec3> end, <float> baseRadius, <float> tipRadius, <float> tipHeight)

Check it on Github


#ifndef FNC_ARROWSDF
#define FNC_ARROWSDF
float arrowSDF(vec3 v, vec3 start, vec3 end, float baseRadius, float tipRadius, float tipHeight){
    vec3 t = start - end;
    float l = length(t);
    t /= l;
    l = max(l, tipHeight);

    v -= end;
    if(t.y + 1. < .0001) {
        v.y = -v.y;
    } else {
        float k = 1. / (1. + t.y);
        vec3 column1 = vec3( t.z * t.z * k + t.y, t.x, t.z * -t.x * k );
        vec3 column2 = vec3( -t.x , t.y , -t.z );
        vec3 column3 = vec3( -t.x * t.z * k , t.z, t.x * t.x * k + t.y );
        v = mat3( column1 , column2 , column3 ) * v;
    }

    vec2 q = vec2( length(v.xz) , v.y );
    q.x = abs(q.x);

    // tip
    vec2 e = vec2( tipRadius , tipHeight );
    float h = clamp( dot(q,e) / dot(e,e) , 0. , 1. );
    vec2 d1 = q - e * h;
    vec2 d2 = q - vec2( tipRadius , tipHeight );
    d2.x -= clamp( d2.x , baseRadius - tipRadius , 0. );

    // base
    vec2 d3 = q - vec2( baseRadius , tipHeight );
    d3.y -= clamp( d3.y , 0. , l - tipHeight );
    vec2 d4 = vec2( q.y - l , max( q.x - baseRadius , 0. ));

    float s = max( 
                max( 
                    max( d1.x , -d1.y ), 
                    d4.x
                ), 
                min( d2.y , d3.x ) 
            );


    return sqrt(
             min(
                min( 
                    min(dot(d1,d1), dot(d2,d2)), 
                    dot(d3,d3) 
                ),
                dot(d4,d4)
            )
        ) * sign(s);
}
#endif

Use:

arrowSDF(<float3> v, <float3> start, <float3> end, <float> baseRadius, <float> tipRadius, <float> tipHeight)

Check it on Github


#ifndef FNC_ARROWSDF
#define FNC_ARROWSDF
float arrowSDF(float3 v, float3 start, float3 end, float baseRadius, float tipRadius, float tipHeight){
    float3 t = start - end;
    float l = length(t);
    t /= l;
    l = max(l, tipHeight);

    v -= end;
    if(t.y + 1. < .0001) {
        v.y = -v.y;
    } else {
        float k = 1. / (1. + t.y);
        float3 column1 = float3( t.z * t.z * k + t.y, t.x, t.z * -t.x * k );
        float3 column2 = float3( -t.x , t.y , -t.z );
        float3 column3 = float3( -t.x * t.z * k , t.z, t.x * t.x * k + t.y );
        v = mat3( column1 , column2 , column3 ) * v;
    }

    float2 q = float2( length(v.xz) , v.y );
    q.x = abs(q.x);

    // tip
    float2 e = float2( tipRadius , tipHeight );
    float h = clamp( dot(q,e) / dot(e,e) , 0. , 1. );
    float2 d1 = q - e * h;
    float2 d2 = q - float2( tipRadius , tipHeight );
    d2.x -= clamp( d2.x , baseRadius - tipRadius , 0. );

    // base
    float2 d3 = q - float2( baseRadius , tipHeight );
    d3.y -= clamp( d3.y , 0. , l - tipHeight );
    float2 d4 = float2( q.y - l , max( q.x - baseRadius , 0. ));

    float s = max( 
                max( 
                    max( d1.x , -d1.y ), 
                    d4.x
                ), 
                min( d2.y , d3.x ) 
            );


    return sqrt(
             min(
                min( 
                    min(dot(d1,d1), dot(d2,d2)), 
                    dot(d3,d3) 
                ),
                dot(d4,d4)
            )
        ) * sign(s);
}
#endif

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