File: points_variable_size.py

package info (click to toggle)
python-moderngl 5.12.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 4,700 kB
  • sloc: python: 15,758; cpp: 14,665; makefile: 14
file content (92 lines) | stat: -rw-r--r-- 2,954 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
"""
Example showing the use of PROGRAM_POINT_SIZE
were we modify point sizes int the vertex shader
making us able to specify a unique size per point.

Without PROGRAM_POINT_SIZE enabled the point size
will be static and obtained from ctx.point_size.

We also show the use of gl_PointCoord making us able
to fill the point with any data we want just like a quad.
"""
import numpy as np
from pyrr import Matrix44

import moderngl
from _example import Example


class Particles(Example):
    title = "Particle System"
    gl_version = (3, 3)
    aspect_ratio = None

    def __init__(self, **kwargs):
        super().__init__(**kwargs)

        self.prog = self.ctx.program(
            vertex_shader="""
            #version 330

            in vec3 in_position;

            uniform mat4 projection;
            uniform mat4 modelview;
            uniform float time;

            out vec3 color;

            void main() {
                gl_Position = projection * modelview * vec4(in_position, 1.0);

                // Set the point size
                gl_PointSize = 25 - gl_Position.z + sin((time + gl_VertexID) * 7.0) * 10.0;

                // Calculate a random color based on the vertex index
                color = vec3(mod(gl_VertexID * 432.43, 1.0), mod(gl_VertexID * 6654.32, 1.0), mod(gl_VertexID  * 6544.11, 1.0));
            }
            """,
            fragment_shader="""
            #version 330

            in vec3 color;
            out vec4 outColor;

            void main() {
                // Calculate the distance from the center of the point
                // gl_PointCoord is available when redering points. It's basically an uv coordinate.
                float dist = step(length(gl_PointCoord.xy - vec2(0.5)), 0.5);

                // .. an use to render a circle!
                outColor = vec4(dist * color, dist);
            }
            """,
        )

        positions = np.random.random_sample((1000,)) * 10 - 5
        self.pos_buffer = self.ctx.buffer(positions.astype('f4'))
        self.vao = self.ctx.vertex_array(
            self.prog,
            [(self.pos_buffer, '3f', 'in_position')],
        )
        self.resize(*self.wnd.buffer_size)

    def render(self, time, frame_time):
        self.ctx.enable_only(moderngl.PROGRAM_POINT_SIZE | moderngl.BLEND)
        self.ctx.blend_func = moderngl.ADDITIVE_BLENDING

        rotation = Matrix44.from_eulers((time, time / 2 , time / 3), dtype='f4')
        translation = Matrix44.from_translation((0, 0, -10), dtype='f4')
        modelview = translation * rotation

        self.prog['modelview'].write(modelview)
        self.prog['time'].value = time
        self.vao.render(mode=moderngl.POINTS)

    def resize(self, width, height):
        self.projection = Matrix44.perspective_projection(60, self.wnd.aspect_ratio, 1, 100, dtype='f4')
        self.prog['projection'].write(self.projection)


if __name__ == '__main__':
    Particles.run()