# An efficient way for generating smooth circle

I'm looking for creating smooth circle. OpenGL supports point, line, and triangle. To create other primitives like circle, we utilize the preceding shapes. In my case, I've utilized points as follows:

float radius(0.5f);
meshes.push_back(   new Mesh(vertices, sizeof(vertices)/sizeof(vertices[0]), 'P')   );
}


In rendering loop,

while( Window.isOpen() ){
Window.PollEvents();
Window.clear();
//================( Rendering )=========================

for ( int i(0); i < meshes.size(); ++i )
meshes[i]->draw();

//======================================================
Window.SwapBuffers();
}


The result is

Now to create smooth circle, basically I just increase the number of points. I don't like this approach since I need to create a lot of points for single shape. My question is is there an alternative yet efficient approach for this issue?

• An Efficient Way to Draw Approximate Circles in OpenGL Commented May 18, 2017 at 11:51
• I'm pretty sure no one is going to measurebthe circle you draw them. Also, use the same model for each. Commented May 18, 2017 at 12:03
• @Theraot, they use old OpenGL glBegin(). I'm using shaders. Commented May 18, 2017 at 12:21
• @CroCo I'm aware. Try to see the algorithm beyond the primitives. Edit: glVertex2f would be adding a point to the mesh. C'mon you can do it! Commented May 18, 2017 at 12:23
• Render to a texture and draw that. Commented May 18, 2017 at 12:31

Here's one neat trick you can use to draw nice antialiased curves.

1. Take a mesh (eg. a quad, or to reduce unnecessary overdraw far from the line, you can use an annulus-shaped mesh that approximates the circle more closely.

2. Ensure the mesh's texture coordinates run from -1 at one edge of the circle to +1 at the other edge, to keep our math simple. Ensure there's a little more mesh past the -1...1 range so our circle doesn't run right into the hard polygon edge.

3. Use a fragment shader something a bit like this:

(I'm most familiar with HLSL syntax, so please let me know if I've made any errors translating this to GLSL)

// Compute this fragment's distance from the center of the circle in uv space.

// Convert to a signed distance from the outline we want to draw.
// +ve: outside the disc, -ve: inside the disc.
float signedDistance = radius - 1.0f;

// Use screenspace derivatives to compute how quickly this value changes
// as we move one pixel left or right / up or down:

// Compute (approximately) how far we are from the line in pixel coordinates.

// Combine with our desired line thickness (in pixels) to get an opacity.
float lineWeight = clamp(THICKNESS - rangeFromLine, 0.0f, 1.0f);

return vec4(COLOR.rgb, lineWeight);


While just drawing a dense polygon with straight-line segments as suggested above by Theraot is likely to be more efficient, this shading technique is convenient because it automatically adapts to the scale of the circle / zoom of the camera to show a smooth curve, without needing to add more points as the camera gets closer. It also gives partial opacity along the edge of the line for a smooth antialiased look. It won't look good at extreme glancing angles though, since at the end of the day it's a flat sheet of geometry and has no thickness when viewed edge-on - you'd want to switch to a different shape if viewing the circle this way.

There's always the pure shader rendering thechnique if you really want to make it faster, but it only helps if you draw hundreds of circles, and they overlap.

Basically, you draw a rectangle that covers the whole screen, then you load each circle in the fragment shader including the radiuses. You look through each circle and see if the current fragment position is inside a circle with the formula

(x - centerX)^2 + (y - centerY)^2 < radius^2