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()
|