Standalone rendering#

Standalone (offline) rendering allows you to render without using a window, and is included in ModernGL by default.

Rendering occurs when VertexArray.render() is called. By default, the mode parameter is moderngl.TRIANGLES, but since we need to draw a line, we change the mode value to moderngl.LINES:

vao.render(moderngl.LINES)  # "mode" is the first optional argument

To display the rendering result, we use the Pillow (PIL) library that comes with Python. Let’s return the texture from the GPU memory to RAM and call the PIL.Image.show() method to show it.

Entire source

 1import moderngl
 2import numpy as np
 3
 4from PIL import Image
 5
 6ctx = moderngl.create_context(standalone=True)
 7
 8prog = ctx.program(
 9    vertex_shader="""
10        #version 330
11
12        in vec2 in_vert;
13        in vec3 in_color;
14
15        out vec3 v_color;
16
17        void main() {
18            v_color = in_color;
19            gl_Position = vec4(in_vert, 0.0, 1.0);
20        }
21    """,
22    fragment_shader="""
23        #version 330
24
25        in vec3 v_color;
26
27        out vec3 f_color;
28
29        void main() {
30            f_color = v_color;
31        }
32    """,
33)
34
35x = np.linspace(-1.0, 1.0, 50)
36y = np.random.rand(50) - 0.5
37r = np.zeros(50)
38g = np.ones(50)
39b = np.zeros(50)
40
41vertices = np.dstack([x, y, r, g, b])
42
43vbo = ctx.buffer(vertices.astype("f4").tobytes())
44vao = ctx.vertex_array(prog, vbo, "in_vert", "in_color")
45
46fbo = ctx.framebuffer(
47    color_attachments=[ctx.texture((512, 512), 3)]
48)
49fbo.use()
50fbo.clear(0.0, 0.0, 0.0, 1.0)
51vao.render(moderngl.LINE_STRIP)
52
53Image.frombytes(
54    "RGB", fbo.size, fbo.color_attachments[0].read(),
55    "raw", "RGB", 0, -1
56).show()

The result will be something like this:

Rendering result

Rendering result#