Harold Serrano

View Original

Make a Loading Circle using Shaders

Hey guys,

In this video, I explain how to implement a Loading Circle using Shaders. I use the Metal Shading Language, but the concept here applies to the OpenGL Shading Language as well.

Here is the video and the code for your convenience.

Code Snippet.

#include <metal_stdlib> using namespace metal;

//rotate space by angle float2x2 rotate2d(float _angle){ return float2x2(cos(_angle),-sin(_angle), sin(_angle),cos(_angle)); }

//Sign distance function of circle/ring float sdfCircle(float2 p, float2 c, float r) { return abs(r - length(p - c)); }

//Sign distance function of line float sdfLine( float2 p, float2 a, float2 b) { float2 pa = p - a, ba = b - a; float h = clamp(dot(pa,ba) / dot(ba,ba), 0., 1.);
return length(pa - ba * h); }

//sharpens the object float sharpen(float d, float w, float2 resolution) { float e = 1. / min(resolution.y , resolution.x); return 1. - smoothstep(-e, e, d - w); }

//computes the modulus float mod(float x, float y){ return x-y*floor(x/y); }

#define M_PI 3.1415926535897932384626433832795

fragment float4 fs_main( FS_INPUT In [[stage_in]], constant FS_UNIFORM& uniform [[buffer(16)]], texture2d texture0 [[texture(2)]], sampler texture0Smplr [[sampler(2)]]) { float2 st = -1. + 2. * In.v_texcoord; float3 color=float3(0.0); float m=0.0;

//scale and translate the space    
st*=3.0;
st.y+=2.0;

//Sample the texture
float4 myTexture=texture0.sample(texture0Smplr,In.v_texcoord);

//step 1. create a circle
float c=sdfCircle(st,float2(0.0,0.0),0.5);
c=sharpen(c,0.06,uniform.resolution);


//step 2. create a line and rotate the space
for(int i=0; i<15; i++){

    //make a copy of the space
    float2 st2=st;

    //rotate the space by 24 degrees
    st2=st2*rotate2d((i*24.0)*M_PI/180.0);

    //create line with the current space
    float l=sdfLine(st2,float2(0.0,0.0),float2(0.0,0.6));

    //sharpen the line
    l=sharpen(l,0.06,uniform.resolution);

    m+=min(l,c);

}


float a=-atan2(st.y,st.x);

a=mod(-uniform.time+0.5*(a/M_PI),1.0);

m*=a;

float4 finalColor=max(myTexture,m);

return finalColor;

}

Thanks for watching.