dli_arc.fsh 3.24 KB
#version 300 es

#ifdef HIGHP
  precision highp float;
#else
  precision mediump float;
#endif

#define ROUND_STARTCAP   0x1
#define ROUND_ENDCAP     0x2
#define SQUARE_STARTCAP  0x4
#define SQUARE_ENDCAP    0x8
precision mediump float;

in vec2 vUV;

uniform vec4 uColor;
uniform int antiAliasing;
uniform float radius;
uniform vec2 startAngle;
uniform vec2 endAngle;
uniform int arcCaps;

out vec4 FragColor;


void main()
{
////////////////////
//Inputs
  float radius1 = 1.0;
  float uvPixel = length( dFdx( vUV ) ) * 2.0;
  float dx = mix( 0.0001, uvPixel, antiAliasing > 0 );
  float radius2 = mix( 1.0 - radius * uvPixel - dx , -radius , step( 0.0, -radius ) );
////////////////////
  float alpha = 0.0;
  float circle = 0.0;

  vec2 uv = fract(vUV) * 2.0 - 1.0;

  float ang_img = endAngle.y * startAngle.x - endAngle.x * startAngle.y;
  float half1 = uv.x * startAngle.x - uv.y * startAngle.y;
  float half2 = uv.y * endAngle.y - uv.x * endAngle.x;
  float len = length(uv);
  float equalAngles = step(0.99999, dot(endAngle, startAngle));
  float right_side = step(0.0, ang_img);
  vec2 uv_norm = normalize(uv);
  float cap_radius = -0.5 + radius2 / 2.0;
  float square_cap;
  float sq_plane;

    /******************************************
   * Equivalent to:
   * if( len > radius1 || len < radius2 )
   */
  circle = alpha =  smoothstep( len, len + dx, radius1 ) * smoothstep( -len, -len + dx, -radius2 );
  float half1_step = smoothstep( -dx, 0.0, half1 );
  float half2_step = smoothstep( -dx, 0.0, half2 );

  float neg_angimg = max( half1_step, half2_step );
  float pos_angimg = min( half1_step, half2_step );
  /******************************************
   * Equivalent to:
  if(ang_img < 0.0)
  {
    alpha *= max(smoothstep( 0.0, dx, half1 ), smoothstep( 0.0, dx, half2));
  }
  else
  {
    alpha *= min(smoothstep( 0.0, dx, half1 ) , smoothstep( 0.0, dx, half2 ));
  }
  */
  alpha *= mix( neg_angimg, pos_angimg, step(0.0, ang_img) );

  alpha = mix( alpha, mix( circle, 0.0, right_side ), equalAngles );

  if((arcCaps & ROUND_STARTCAP) > 0)
  {
    len = length(uv - normalize( vec2( startAngle.y, startAngle.x )) * (1.0 + cap_radius));
    alpha = max(alpha, smoothstep(cap_radius, cap_radius + dx, -len) );
  }
  if((arcCaps & ROUND_ENDCAP) > 0)
  {
    len = length(uv - normalize( vec2( endAngle.y, endAngle.x )) * (1.0 + cap_radius));
    alpha = max(alpha, smoothstep(cap_radius, cap_radius + dx, -len) );
  }

  if((arcCaps & SQUARE_STARTCAP) > 0)
  {
    sq_plane = -uv.x * startAngle.y - uv.y * startAngle.x;
    square_cap = min(step( 0.0, -half1 ), smoothstep( cap_radius, cap_radius + dx, half1 ));
    square_cap = min(square_cap, smoothstep( radius2, radius2 + dx, -sq_plane ));
    square_cap = min(square_cap, smoothstep( -1.0, -1.0 + dx, sq_plane ));
    alpha = max(square_cap, alpha);
  }

  if((arcCaps & SQUARE_ENDCAP) > 0)
  {
    sq_plane = -uv.x * endAngle.y - uv.y * endAngle.x;
    square_cap = min(step( 0.0, -half2 ), smoothstep( cap_radius, cap_radius + dx, half2 ));
    square_cap = min(square_cap, smoothstep( radius2, radius2 + dx, -sq_plane ));
    square_cap = min(square_cap, smoothstep( -1.0, -1.0 + dx, sq_plane ));
    alpha = max(square_cap, alpha);
  }

  if( alpha == 0.0 )
  {
    discard;
  }

  FragColor = vec4(vec3(uColor), uColor.a * alpha);
}