Search code examples
iosopengl-es-2.0vertex-shader

How to draw a star in iOS OpenGL ES 2.0


This question has been asked before but the quite a few years ago in my searches. The answer was always to use texture mapping but what I really want to do is represent the star as a single vertex - you may think I'm copping out with a simplistic method but in fact, a single point source of light actually looks pretty good and realistic. But I want to process that point of light with something like a gaussian blur too give it a little more body when zooming in or for brighter stars. I was going to texture map a gaussian blur image but if I understand things correctly I would then have to draw each star with 4 vertexes. Maybe not so difficult but I don't want to go there if I can just process a single vertex. Would a vertex-shader do this? Can GLKBaseEffects get me there? Any suggestions?

Thanks.


Solution

  • You can use point sprites.

    Draw Calls

    You use a texture containing the image of the star, and use the typical setup to bind a texture, bind it to a sampler uniform in the shader, etc.

    You draw a single vertex for each star, with GL_POINTS as the primitive type passed as the first argument to glDrawArrays()/glDrawElements(). No texture coordinates are needed.

    Vertex Shader

    In the vertex shader, you transform the vertex as you normally would, and also set the built-in gl_PointSize variable:

    uniform float PointSize;
    attribute vec4 Position;
    
    void main() {
        gl_Position = ...;  // Transform Position attribute;
        gl_PointSize = PointSize;
    }
    

    For the example, I used a uniform for the point size, which means that all stars will have the same size. Depending on the desired effect, you could also calculate the size based on the distance, or use an additional vertex attribute to specify a different size for each star.

    Fragment Shader

    In the fragment shader, you can now access the built-in gl_PointCoord variable to get the relative coordinates of the fragment within the point sprite. If your point sprite is a simple texture image, you can use it directly as the texture coordinates.

    uniform sampler2D SpriteTex;
    
    void main() {
        gl_FragColor = texture2D(SpriteTex, gl_PointCoord);
    }
    

    Additional Material

    I answered a somewhat similar question here: Render large circular points in modern OpenGL. Since it was for desktop OpenGL, and not for a textured sprite, this seemed worth a separate answer. But some of the steps are shared, and might be explained in more detail in the other answer.