1
+ import pygame
2
+ import moderngl
3
+ import ctypes
4
+ import sys
5
+
6
+ vertex_shader_sprite = """
7
+ #version 330
8
+ in vec2 in_position;
9
+ in vec2 in_uv;
10
+ out vec2 v_uv;
11
+ void main()
12
+ {
13
+ v_uv = in_uv;
14
+ gl_Position = vec4(in_position, 0.0, 1.0);
15
+ }
16
+ """
17
+
18
+ fragment_shader_sprite = """
19
+ #version 330
20
+ out vec4 fragColor;
21
+ uniform sampler2D u_texture;
22
+ uniform float y;
23
+ in vec2 v_uv;
24
+
25
+ #define PI 3.1415926535897932384626433832795;
26
+
27
+ float rand(vec2 c){
28
+ return fract(sin(dot(c.xy ,vec2(12.9898,78.233))) * 43758.5453);
29
+ }
30
+
31
+ float noise(vec2 p, float freq ){
32
+ float unit = 1/freq;
33
+ vec2 ij = floor(p/unit);
34
+ vec2 xy = mod(p,unit)/unit;
35
+ xy = 3.*xy*xy-2.*xy*xy*xy;
36
+ //xy = 0.5*(1.-cos(PI*xy));
37
+ float a = rand((ij+vec2(0.,0.)));
38
+ float b = rand((ij+vec2(1.,0.)));
39
+ float c = rand((ij+vec2(0.,1.)));
40
+ float d = rand((ij+vec2(1.,1.)));
41
+ float x1 = mix(a, b, xy.x);
42
+ float x2 = mix(c, d, xy.x);
43
+ return mix(x1, x2, xy.y);
44
+ }
45
+
46
+ float pNoise(vec2 p, int res){
47
+ float persistance = .5;
48
+ float n = 0.;
49
+ float normK = 0.;
50
+ float f = 4.;
51
+ float amp = 1.;
52
+ int iCount = 0;
53
+ for (int i = 0; i<50; i++){
54
+ n+=amp*noise(p, f);
55
+ f*=2.;
56
+ normK+=amp;
57
+ amp*=persistance;
58
+ if (iCount == res) break;
59
+ iCount++;
60
+ }
61
+ float nf = n/normK;
62
+ return nf*nf*nf*nf;
63
+ }
64
+
65
+ void main()
66
+ {
67
+ //fragColor = texture(u_texture, v_uv)*pNoise(vec2(v_uv.x, y+v_uv.y), 1);
68
+ vec2 new_v_uv = v_uv*2;
69
+ float transparency = pNoise(vec2(new_v_uv.x, new_v_uv.y+y), 1);
70
+ if (transparency < 0.075) {
71
+ discard;
72
+ } else {
73
+ float y = y/3;
74
+ fragColor = vec4(0.05+pNoise(vec2(y-50, -y+50), 1), 0.05+pNoise(vec2(-y, y), 1), 0.05+pNoise(vec2(y+600, y-750), 1), 1)*(0.9+transparency);
75
+ }
76
+ }
77
+ """
78
+
79
+ class ModernGLGroup (pygame .sprite .Group ):
80
+
81
+ gl_context = None
82
+ gl_program = None
83
+ gl_buffer = None
84
+ gl_vao = None
85
+ gl_textures = {}
86
+ y = 0
87
+
88
+ def __init__ (self , sprites = None ):
89
+ if sprites == None :
90
+ super ().__init__ ()
91
+ else :
92
+ super ().__init__ (sprites )
93
+
94
+ def get_program ():
95
+ if ModernGLGroup .gl_program == None :
96
+ ModernGLGroup .gl_program = ModernGLGroup .gl_context .program (
97
+ vertex_shader = vertex_shader_sprite ,
98
+ fragment_shader = fragment_shader_sprite )
99
+ return ModernGLGroup .gl_program
100
+
101
+ def get_buffer ():
102
+ if ModernGLGroup .gl_buffer == None :
103
+ ModernGLGroup .gl_buffer = ModernGLGroup .gl_context .buffer (None , reserve = 6 * 4 * 4 )
104
+ return ModernGLGroup .gl_buffer
105
+
106
+ def get_vao ():
107
+ if ModernGLGroup .gl_vao == None :
108
+ ModernGLGroup .gl_vao = ModernGLGroup .gl_context .vertex_array (
109
+ ModernGLGroup .get_program (), [(ModernGLGroup .get_buffer (), "2f4 2f4" , "in_position" , "in_uv" )])
110
+ return ModernGLGroup .gl_vao
111
+
112
+ def get_texture (image ):
113
+ if not image in ModernGLGroup .gl_textures :
114
+ rgba_image = image .convert_alpha ()
115
+ texture = ModernGLGroup .gl_context .texture (rgba_image .get_size (), 4 , rgba_image .get_buffer ())
116
+ texture .swizzle = 'BGRA'
117
+ ModernGLGroup .gl_textures [image ] = texture
118
+ return ModernGLGroup .gl_textures [image ]
119
+
120
+ def convert_vertex (pt , surface ):
121
+ return pt [0 ] / surface .get_width () * 2 - 1 , 1 - pt [1 ] / surface .get_height () * 2
122
+
123
+ def render (sprite , surface ):
124
+ corners = [
125
+ ModernGLGroup .convert_vertex (sprite .rect .bottomleft , surface ),
126
+ ModernGLGroup .convert_vertex (sprite .rect .bottomright , surface ),
127
+ ModernGLGroup .convert_vertex (sprite .rect .topright , surface ),
128
+ ModernGLGroup .convert_vertex (sprite .rect .topleft , surface )]
129
+
130
+ vertices_quad_2d = (ctypes .c_float * (6 * 4 ))(
131
+ * corners [0 ], 0.0 , 1.0 ,
132
+ * corners [1 ], 1.0 , 1.0 ,
133
+ * corners [2 ], 1.0 , 0.0 ,
134
+ * corners [0 ], 0.0 , 1.0 ,
135
+ * corners [2 ], 1.0 , 0.0 ,
136
+ * corners [3 ], 0.0 , 0.0 )
137
+
138
+ ModernGLGroup .get_buffer ().write (vertices_quad_2d )
139
+ ModernGLGroup .get_program ()["y" ] = ModernGLGroup .y
140
+ ModernGLGroup .get_texture (sprite .image ).use (0 )
141
+ ModernGLGroup .get_vao ().render ()
142
+ ModernGLGroup .y += 0.001
143
+
144
+ def draw (self , surface ):
145
+ for sprite in self :
146
+ ModernGLGroup .render (sprite , surface )
147
+
148
+ class SpriteObject (pygame .sprite .Sprite ):
149
+ def __init__ (self , size ):
150
+ super ().__init__ ()
151
+ self .image = pygame .Surface (size , pygame .SRCALPHA )
152
+ self .rect = self .image .get_rect (center = (size [0 ]// 2 , size [1 ]// 2 ))
153
+
154
+ pygame .init ()
155
+
156
+ window = pygame .display .set_mode (
157
+ (1280 , 720 ),
158
+ pygame .DOUBLEBUF | pygame .OPENGL | pygame .HWACCEL ,
159
+ vsync = True )
160
+ pygame .display .set_caption ("Colorful Stacked Patterns - 2" )
161
+
162
+ clock = pygame .time .Clock ()
163
+
164
+ gl_context = moderngl .create_context ()
165
+ gl_context .enable (moderngl .BLEND )
166
+ ModernGLGroup .gl_context = gl_context
167
+
168
+ sprite_object = SpriteObject (window .get_size ())
169
+ group = ModernGLGroup (sprite_object )
170
+
171
+ run = True
172
+ fullscreen = False
173
+ while 1 :
174
+ event_list = pygame .event .get ()
175
+ for event in event_list :
176
+ if event .type == pygame .QUIT :
177
+ pygame .quit ()
178
+ sys .exit ()
179
+
180
+ elif event .type == pygame .KEYDOWN :
181
+ if event .key == pygame .K_ESCAPE :
182
+ pygame .quit ()
183
+ sys .exit ()
184
+ elif event .key == pygame .K_F11 :
185
+ fullscreen = not fullscreen
186
+ if fullscreen :
187
+ window = pygame .display .set_mode (
188
+ (0 , 0 ),
189
+ pygame .DOUBLEBUF | pygame .OPENGL | pygame .FULLSCREEN | pygame .HWACCEL ,
190
+ vsync = True )
191
+ else :
192
+ window = pygame .display .set_mode (
193
+ (1280 , 720 ),
194
+ pygame .DOUBLEBUF | pygame .OPENGL | pygame .HWACCEL ,
195
+ vsync = True )
196
+
197
+ ModernGLGroup .gl_context .viewport = (
198
+ 0 ,
199
+ 0 ,
200
+ * pygame .display .get_window_size ())
201
+
202
+ sprite_object = SpriteObject (window .get_size ())
203
+ group = ModernGLGroup (sprite_object )
204
+ gl_context .clear (0 , 0 , 0 )
205
+
206
+ group .draw (window )
207
+ pygame .display .flip ()
208
+ clock .tick (200 )
209
+
210
+ pygame .quit ()
211
+ exit ()
0 commit comments