How to draw snowflakes with OpenGL's point sprite?

After watching the Winter Olympics, we know that Altay is not only the "snow capital" of China, but also the "origin of human skiing". Whether this statement is true or not, let alone, Altay's snow is really beautiful. There is a promotional film for the Winter Olympic Games, which tells the story of the Winter Olympic Games from the perspective of an Altay snowflake. It has both historical massiness and artistic romance, with a great sense of visual impact.


So the question comes: how to draw snow flowers with OpenGL? Usually, point sprite technology is used to describe the movement of a large number of particles on the screen. Naturally, it can also be used to draw snowflakes. The point sprite can be understood as a point pasted with a texture image - a 2D texture image can be drawn anywhere on the screen with only one vertex.

Starting and using point sprites in OpenGL is a little complicated. Fortunately, WxGL encapsulates this and is very simple to use. Before giving the demonstration code, paste two texture pictures of snowflakes.

  • snow_1.png

  • snow_2.png

Students familiar with GLSL language can easily understand the shader source code. After the shader source code and texture pictures are loaded into the model, just show it and the snowflakes will be displayed. If you want to achieve the effect of snowflakes, please refer to another blog post Directing a fireworks event with OpenGL to welcome the coming New Year.

import numpy as np
import wxgl
from wxgl import wxplot as plt

vshader_src = """
    #version 330 core
    in vec4 a_Position;
    uniform mat4 u_MVPMatrix;
    void main() { 
        gl_Position = u_MVPMatrix * a_Position; 
        gl_PointSize = (a_Position.z + 1) * 30;
    }
"""

fshader_src = """
    #version 330 core
    uniform sampler2D u_Snow_1;
    in float idx;
    void main() { 
        gl_FragColor = texture2D(u_Snow_1, gl_PointCoord); 
    } 
"""

m = wxgl.Model(wxgl.POINTS, vshader_src, fshader_src, sprite=True) # Open the Point Wizard through sprite = tree
m.set_vertex('a_Position', np.random.random((300, 3))*2-1) # Randomly generate 300 points
m.add_texture('u_Snow_1', 'res/image/snow_1.png', wxgl.TEXTURE_2D) # Add snow texture
m.set_mvp_matrix('u_MVPMatrix') # Set model matrix, viewpoint matrix and projection matrix

plt.model(m)
plt.show()

Here is how to use snow_1.png texture effect.

Here is how to use snow_2.png texture effect.

However, such snowflakes are slightly monotonous. After all, there are no two identical snowflakes in the world. How to make snowflakes look more realistic? The following code attempts to mix the two textures in a slice shader.

import numpy as np
import wxgl
from wxgl import wxplot as plt

vshader_src = """
    #version 330 core
    in vec4 a_Position;
    uniform mat4 u_MVPMatrix;
    void main() { 
        gl_Position = u_MVPMatrix * a_Position; 
        gl_PointSize = (a_Position.z + 1) * 30;
    }
"""

fshader_src = """
    #version 330 core
    uniform sampler2D u_Snow_1;
    uniform sampler2D u_Snow_2;
    in float idx;
    void main() { 
        if (fract(sin(dot(gl_PointCoord ,vec2(12.9898,78.233))) * 43758.5453) < 0.5) {
            gl_FragColor = texture2D(u_Snow_1, gl_PointCoord); 
        } else {
            gl_FragColor = texture2D(u_Snow_2, gl_PointCoord);
        }
    } 
"""

m = wxgl.Model(wxgl.POINTS, vshader_src, fshader_src, sprite=True) # Open the Point Wizard through sprite = tree
m.set_vertex('a_Position', np.random.random((300, 3))*2-1) # Randomly generate 300 points
m.add_texture('u_Snow_1', 'res/image/snow_1.png', wxgl.TEXTURE_2D) # Add snowflake texture 1
m.add_texture('u_Snow_2', 'res/image/snow_2.png', wxgl.TEXTURE_2D) # Add snow texture 2
m.set_mvp_matrix('u_MVPMatrix') # Set model matrix, viewpoint matrix and projection matrix

plt.model(m)
plt.show()

Is this snowflake a little unique?

Keywords: Python OpenGL

Added by RootKit on Sat, 05 Feb 2022 06:53:04 +0200