Drawing Antialiased circle using Shaders
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)
Related videos on Youtube
user1754682
Updated on September 19, 2022Comments
-
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
withtextureCoordinate.x
andtextureCoordinate.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 oftextureCoordinate
than it is always 1.0.(experimented by replacing the value ingl_fragcolor
). I am unable to figure out as to what I am doing wrong here. I was expecting thetextureCoordinate
value to interpolate with respect to the passed in data (varPos
). -
Sébastien Pierre over 5 yearsYou'd probably want to square your radius instead, which can be done statically, so you'll avoid the expensive
sqrt
indist
. -
Zach Saucier over 2 yearsI believe you can also drop the if/else by using some operators: gist.github.com/ZachSaucier/f924f49fe8e8d8c9e5a1ae305ff6716a