1import numpy
2
3from OpenGL.GL import *
4from OpenGL.GL.shaders import compileShader, compileProgram
5
6VERTEX_SHADER = """#version 120
7attribute vec4 vertices;
8varying vec2 coords;
9
10void main() {
11    gl_Position = vertices;
12    coords = vertices.xy;
13}
14"""
15
16FRAGMENT_SHADER = """#version 120
17uniform float t;
18varying vec2 coords;
19void main() {
20    float i = 1. - (pow(abs(coords.x), 4.) + pow(abs(coords.y), 4.));
21    i = smoothstep(t - 0.8, t + 0.8, i);
22    i = floor(i * 20.) / 20.;
23    gl_FragColor = vec4(coords * .5 + .5, i, i);
24}
25"""
26
27class Renderer(object):
28
29    def __init__(self):
30        self.t = 0.0
31        self.values = numpy.array([
32            -1.0, -1.0,
33            1.0, -1.0,
34            -1.0, 1.0,
35            1.0, 1.0
36        ], dtype=numpy.float32)
37
38    def set_t(self, t):
39        self.t = t
40
41    def init(self):
42        self.vertexbuffer = glGenBuffers(1)
43        vertex_shader = compileShader(VERTEX_SHADER, GL_VERTEX_SHADER)
44        fragment_shader = compileShader(FRAGMENT_SHADER, GL_FRAGMENT_SHADER)
45        self.program = compileProgram(vertex_shader, fragment_shader)
46        self.vertices_attr = glGetAttribLocation(self.program, b'vertices')
47        self.t_attr = glGetUniformLocation(self.program, b't')
48
49    def reshape(self, x, y, width, height):
50        glViewport(x, y, width, height)
51
52    def render(self):
53        glUseProgram(self.program)
54        try:
55            glDisable(GL_DEPTH_TEST)
56            glClearColor(0, 0, 0, 1)
57            glClear(GL_COLOR_BUFFER_BIT)
58            glEnable(GL_BLEND)
59            glBlendFunc(GL_SRC_ALPHA, GL_ONE)
60
61            glBindBuffer(GL_ARRAY_BUFFER, self.vertexbuffer)
62            glEnableVertexAttribArray(self.vertices_attr)
63            glBufferData(GL_ARRAY_BUFFER, self.values, GL_STATIC_DRAW)
64            glVertexAttribPointer(self.vertices_attr, 2, GL_FLOAT, GL_FALSE, 0, None)
65            glUniform1f(self.t_attr, self.t)
66
67            glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)
68        finally:
69            glDisableVertexAttribArray(0)
70            glBindBuffer(GL_ARRAY_BUFFER, 0)
71            glUseProgram(0)
72
73    def cleanup(self):
74        glDeleteProgram(self.program)
75        glDeleteBuffers(1, [self.vertexbuffer])
76