Drawing Antialiased circle using Shaders

16,612

Here's my current attempt at it. It works, in the sense that it draw a disc with a smooth border. I use a distance field approach ie. I compute the distance from the disc's border

Fragment shader

#version 110

varying vec2 uv;

void
main() {
    float border = 0.01;
    float radius = 0.5;
    vec4 color0 = vec4(0.0, 0.0, 0.0, 1.0);
    vec4 color1 = vec4(1.0, 1.0, 1.0, 1.0);

    vec2 m = uv - vec2(0.5, 0.5);
    float dist = radius - sqrt(m.x * m.x + m.y * m.y);

    float t = 0.0;
    if (dist > border)
      t = 1.0;
    else if (dist > 0.0)
      t = dist / border;

    gl_FragColor = mix(color0, color1, t);
}

Vertex shader

#version 110

varying vec2 uv;

void
main() {
  gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
  uv = vec2(gl_MultiTexCoord0);
}

It's meant to be drawn on quad with texture coordinate (-0.5, -0.5)x(0.5, 0.5)

Share:
16,612

Related videos on Youtube

user1754682
Author by

user1754682

Updated on September 19, 2022

Comments

  • user1754682
    user1754682 over 1 year

    I am new to shader programming. I am trying to draw a circle with glsl. I used a point with a Size and tried to filter out the points outside the radius.(Altering the alpha value). The code is as follows:

    Fragment Shader:

    #version 130
    varying  vec2 textureCoordinate;
    const float circleBorderWidth = 0.08;//for anti aliasing
    void main() {
          float d = smoothstep(circleBorderWidth,0.1, 1.0-length(textureCoordinate));
          gl_FragColor = vec4(0.0, 1.0, 0.0, d);
    }
    

    Vertex Shader:

    #version 130
    attribute vec4 coord3d;
    attribute vec2 varPos;
    varying vec2 textureCoordinate;
    void
    main()
    {
            textureCoordinate = varPos;
            gl_FrontColor = gl_Color;
            gl_Position = vec4(coord3d.xyz,1.);
            gl_PointSize = coord3d.w;
    }
    

    Data:

    float pos[] = {
        -1, -1,
         -1, 1,
         1, 1,
         1, -1,
    };
    
    float vertices[]={0.0,0.0f,0.0f,100.0f};
    

    Draw Method:

    void drawScene() {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        program->makeCurrent();
        glEnable(GL_POINT_SMOOTH);
        glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
        glEnable(GL_BLEND);
        glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    
        if (varPosAttrib>=0) {
            glVertexAttribPointer( varPosAttrib, 2, GL_FLOAT, GL_FALSE,
                                   0, pos ); // -->varPos in Vertex Shader.
            glEnableVertexAttribArray( varPosAttrib );
        }
    
        if (posAttrib>=0) {
            glVertexAttribPointer(posAttrib, 4, GL_FLOAT, GL_FALSE, 0, vertices); // -->coord3d in vertex shader
            glEnableVertexAttribArray(posAttrib);
            glDrawArrays(GL_POINTS, 0, 1);
        }
        glDisable(GL_POINT_SMOOTH);
        glDisable(GL_VERTEX_PROGRAM_POINT_SIZE);
        glDisable(GL_BLEND);
        program->release();
        glutSwapBuffers(); //Send the 3D scene to the screen
    }
    

    This results in drawing a square if I replace d with 1.0 in the following line (in the fragment shader):

    gl_FragColor = vec4(0.0, 1.0, 0.0, d); // -> if d is replaced by 1.0
    

    I tried to replace the x and y values in gl_FragColor with textureCoordinate.x and textureCoordinate.y. Result was black (so I assume the values are 0.0). The thing which I don't understand is that if I take the length of textureCoordinate than it is always 1.0.(experimented by replacing the value in gl_fragcolor). I am unable to figure out as to what I am doing wrong here. I was expecting the textureCoordinate value to interpolate with respect to the passed in data (varPos).

  • Sébastien Pierre
    Sébastien Pierre over 5 years
    You'd probably want to square your radius instead, which can be done statically, so you'll avoid the expensive sqrt in dist.
  • Zach Saucier
    Zach Saucier over 2 years
    I believe you can also drop the if/else by using some operators: gist.github.com/ZachSaucier/f924f49fe8e8d8c9e5a1ae305ff6716a