Render large circular points in modern OpenGL

The “modern” way of drawing points works like this:

  1. Enable program point size mode:

    glEnable(GL_PROGRAM_POINT_SIZE);
    
  2. Render vertices with GL_POINTS primitive mode.

  3. In the vertex shader, set the built-in variable gl_PointSize to the desired size of the individual point:

    gl_Position = ...;
    gl_PointSize = ...;
    

    The value used for this point size could be constant if it’s always the same, a uniform if you want to be able to adjust it between draw calls, or a vertex attribute if the point size is variable per point.

  4. This will generate fragments for a square point of the size specified by the value of gl_PointSize. In the fragment shader, you can use the built-in gl_PointCoord variable, which gives you the relative coordinate of the fragment within the point. It works very similarly to texture coordinates, providing a range of [0, 1] in each direction.

    For example, if you want textured points, which is very useful for particle systems, the fragment shader code could contain:

    outColor = texture(particleTex, gl_PointCoord);
    

    Or if you want round points, you can discard everything outside a circle based on the distance from the center:

    vec2 circCoord = 2.0 * gl_PointCoord - 1.0;
    if (dot(circCoord, circCoord) > 1.0) {
        discard;
    }
    

    Or similarly, you can make the fragments outside the circle transparent, and enable blending, to get round points.

Note that the range of supported point sizes is implementation dependent. You can query the available range with:

GLfloat sizeRange[2] = {0.0f};
glGetFloatv(GL_POINT_SIZE_RANGE, sizeRange);

Leave a Comment