Search code examples
javascriptshaderwebglfragment-shaderantialiasing

Why am I getting these artifacts in the middle of my circle rendered with WebGL?


I have the following fragment shader:

float curve(float theta) {
  float waveDepth = 0.70;
  float waveCount = 5.0;

  return waveDepth * (sin(theta * waveCount) + 1.0) * 0.5;
}

void main() { 
  vec2 cxy = 2.0 * v_pos - 1.0;
  float r = cxy.x * cxy.x + cxy.y * cxy.y;

  float theta = atan(cxy.y, cxy.x);
  r += curve(theta);

  float delta = fwidth(r);
  float alpha = 1.0 - smoothstep(1.0 - delta, 1.0 + delta, r);

  outputColor = vec4(1, 1, 0.5, 1) * alpha;
}

Which draws something that looks like this:

enter image description here

It's a wavy circle that looks like a star. I would like to get rid of the grey pixely artifacts in the center of the circle.

I notice that if I set delta equal to 0 (and avoid using fwidth), then I do not get these artifacts, but that also removes antialiasing from the outside.

Is there any way to keep the antialiasing but also remove these artifacts present in the center of the wavy circle?


Solution

  • A workaround is to ensure that alpha` is 1.0 when the fragment is near the center of the circle:

    void main() { 
        
        vec2 cxy = 2.0 * v_pos - 1.0;
        float r0 = cxy.x * cxy.x + cxy.y * cxy.y;
        
        float theta = atan(cxy.y, cxy.x);
        float r = r0 + curve(theta);
      
        float delta = fwidth(r);
        float alpha = 1.0 - step(0.1, r0) * smoothstep(1.0 - delta, 1.0 + delta, r);
      
        outputColor = vec4(1.0, 0.0, 0.0, 1) * alpha;
    }