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.
Thanks for watching.
#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;
}