Question

I'm trying to draw a circle with OpenGL using glDrawArrays and GL_POINTS. My circle is drawn correct, but each point has got a white border (see screenshot).

Screenshot

Here is the code:

glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_POINT_SMOOTH);
glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);

Color* color = (Color*)colors;

glEnableClientState(GL_VERTEX_ARRAY);
pointSize *= this->GetScale();

glPointSize(pointSize);
glColor4f(color->r/255.0f, color->g/255.0f, color->b/255.0f, 1.0f);

glVertexPointer(2, GL_FLOAT, 0, verts);
glDrawArrays(GL_POINTS, 0, count);
glDisableClientState(GL_VERTEX_ARRAY);

I think, something's wrong with blending mode, but I can't find the right one. Any suggestions?

Was it helpful?

Solution

I believe GL_POINT_SMOOTH is intended to be used with saturation blending glBlendFunc(GL_SRC_ALPHA_SATURATE, GL_ONE) as the alpha is calculated as a portion of the pixel that the sprite overlaps. The depth buffer may interfere with the rendering too.

For a more accurate circle I'd suggest using a triangle strip, or even a single textured or (if using shaders, implicitly coloured in the fragment shader) quad.

OTHER TIPS

Funny, I actually explained this yesterday (though using GL_POLYGON_SMOOTH instead). The problem is the same, however.

GL_LINE_SMOOTH, GL_POLYGON_SMOOTH and GL_POINT_SMOOTH all suffer from one major problem that creates these blending artifacts. When you draw using these anti-aliasing techniques, aliased edges are blended together with the existing pixel in the frame buffer. This creates an order-dependent situation that can only be resolved by sorting your primitives back-to-front and taking a potentially serious performance hit due to overdraw.

When you see these white pixels, what is really happening is that the aliased edge is being blended with the only thing in your color buffer up until that time (the clear color).

If you really insist upon using point smoothing in this situation, you should draw all of your points twice. For best results, you might want to reverse the order you draw them in on the first pass and disable depth writes using glDepthMask (GL_FALSE), then on the second pass re-enable depth writes. Obviously this is going to suck from a performance perspective, but these non-fullscene anti-aliasing techniques are far from ideal to begin with.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top