Welcome to ModernGL’s documentation!

ModernGL

Context

Shaders and Programs

Uniform

Uniform Blocks

Attributes

Varyings

Program Stages

Subroutines
SubroutineUniforms

Buffers

VertexArray

VertexArrayAttributes

Textures

Framebuffers

Renderbuffers

ComputeShaders

InvalidObject

Constants

Enable Flags

Versions

Primitives

Error

Examples

01. Hello World!

01_hello_world

Hello World!

 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
import struct

import GLWindow
import ModernGL

# Window & Context

wnd = GLWindow.create_window()
ctx = ModernGL.create_context()

# Shaders & Program

prog = ctx.program([
	ctx.vertex_shader('''
		#version 330

		in vec2 vert;

		void main() {
			gl_Position = vec4(vert, 0.0, 1.0);
		}
	'''),
	ctx.fragment_shader('''
		#version 330

		out vec4 color;

		void main() {
			color = vec4(0.3, 0.5, 1.0, 1.0);
		}
	'''),
])

# Buffer

vbo = ctx.buffer(struct.pack('6f',
	0.0, 0.8,
	-0.6, -0.8,
	0.6, -0.8,
))

# Put everything together

vao = ctx.simple_vertex_array(prog, vbo, ['vert'])

# Main loop

while wnd.update():
	ctx.viewport = wnd.viewport
	ctx.clear(240, 240, 240)
	vao.render()

02. Uniforms and Attributes

02_uniforms_and_attributes

Uniforms and Attributes

 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
import struct

import GLWindow
import ModernGL

# Window & Context

wnd = GLWindow.create_window()
ctx = ModernGL.create_context()

# Shaders & Program

prog = ctx.program([
	ctx.vertex_shader('''
		#version 330

		in vec2 vert;

		in vec3 vert_color;
		out vec3 frag_color;

		uniform vec2 scale;
		uniform float rotation;

		void main() {
			frag_color = vert_color;
			mat2 rot = mat2(
				cos(rotation), sin(rotation),
				-sin(rotation), cos(rotation)
			);
			gl_Position = vec4((rot * vert) * scale, 0.0, 1.0);
		}
	'''),
	ctx.fragment_shader('''
		#version 330

		in vec3 frag_color;
		out vec4 color;

		void main() {
			color = vec4(frag_color, 1.0);
		}
	'''),
])

# Uniforms

scale = prog.uniforms['scale']
rotation = prog.uniforms['rotation']

width, height = wnd.size
scale.value = (height / width * 0.75, 0.75)

# Buffer

vbo = ctx.buffer(struct.pack('15f',
	1.0, 0.0,
	1.0, 0.0, 0.0,

	-0.5, 0.86,
	0.0, 1.0, 0.0,

	-0.5, -0.86,
	0.0, 0.0, 1.0,
))

# Put everything together

vao = ctx.simple_vertex_array(prog, vbo, ['vert', 'vert_color'])

# Main loop

while wnd.update():
	ctx.viewport = wnd.viewport
	ctx.clear(240, 240, 240)
	rotation.value = wnd.time
	vao.render()

03. Blending

03_blending

Blending

04. Texture

04_texture

Texture

05. Perspective

05_perspective

Perspective projection

Julia Fractal

julia_fractal

Julia Fractal

 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
import struct

import GLWindow
import ModernGL

# Window & Context

wnd = GLWindow.create_window()
ctx = ModernGL.create_context()

vert = ctx.vertex_shader('''
	#version 330

	in vec2 vert;
	out vec2 tex;

	void main() {
		gl_Position = vec4(vert, 0.0, 1.0);
		tex = vert / 2.0 + vec2(0.5, 0.5);
	}
''')

frag = ctx.fragment_shader('''
	#version 330

	in vec2 tex;
	out vec4 color;

	uniform vec2 center;
	uniform int iter;

	void main() {
		vec2 z = vec2(5.0 * (tex.x - 0.5), 3.0 * (tex.y - 0.5));
		vec2 c = center;

		int i;
		for(i = 0; i < iter; i++) {
			vec2 v = vec2(
				(z.x * z.x - z.y * z.y) + c.x,
				(z.y * z.x + z.x * z.y) + c.y
			);
			if (dot(v, v) > 4.0) break;
			z = v;
		}

		float cm = fract((i == iter ? 0.0 : float(i)) * 10 / iter);
		color = vec4(
			fract(cm + 0.0 / 3.0),
			fract(cm + 1.0 / 3.0),
			fract(cm + 2.0 / 3.0),
			1.0
		);
	}
''')

prog = ctx.program([vert, frag])

vbo = ctx.buffer(struct.pack('8f', -1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0))
vao = ctx.simple_vertex_array(prog, vbo, ['vert'])

prog.uniforms['iter'].value = 100

x, y = (0.49, 0.32)

wnd.grab_mouse(True)

while wnd.update():
	ctx.viewport = wnd.viewport
	ctx.clear(240, 240, 240)
	mx, my = wnd.mouse_delta
	x -= mx / 100
	y -= my / 100

	prog.uniforms['center'].value = (y, x)
	vao.render(ModernGL.TRIANGLE_STRIP)

Particle System

particle_system

Particle System

 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
import math
import random
import struct

import GLWindow
import ModernGL

# Window & Context

wnd = GLWindow.create_window()
ctx = ModernGL.create_context()

tvert = ctx.vertex_shader('''
	#version 330

	uniform vec2 acc;

	in vec2 in_pos;
	in vec2 in_prev;

	out vec2 out_pos;
	out vec2 out_prev;

	void main() {
		out_pos = in_pos * 2.0 - in_prev + acc;
		out_prev = in_pos;
	}
''')

vert = ctx.vertex_shader('''
	#version 330

	in vec2 vert;

	void main() {
		gl_Position = vec4(vert, 0.0, 1.0);
	}
''')

frag = ctx.fragment_shader('''
	#version 330

	out vec4 color;

	void main() {
		color = vec4(0.30, 0.50, 1.00, 1.0);
	}
''')

prog = ctx.program([vert, frag])

transform = ctx.program(tvert, ['out_pos', 'out_prev'])

def particle():
	a = random.uniform(0.0, math.pi * 2.0)
	r = random.uniform(0.0, 0.001)

	return struct.pack('2f2f', 0.0, 0.0, math.cos(a) * r - 0.003, math.sin(a) * r - 0.008)

vbo1 = ctx.buffer(b''.join(particle() for i in range(1024)))
vbo2 = ctx.buffer(reserve = vbo1.size)

vao1 = ctx.simple_vertex_array(transform, vbo1, ['in_pos', 'in_prev'])
vao2 = ctx.simple_vertex_array(transform, vbo2, ['in_pos', 'in_prev'])

render_vao = ctx.vertex_array(prog, [
	(vbo1, '2f8x', ['vert']),
])

transform.uniforms['acc'].value = (0, -0.0001)

idx = 0

ctx.point_size = 5.0

while wnd.update():
	ctx.viewport = wnd.viewport
	ctx.clear(240, 240, 240)

	for i in range(8):
		vbo1.write(particle(), offset = idx * struct.calcsize('2f2f'))
		idx = (idx + 1) % 1024

	render_vao.render(ModernGL.POINTS, 1024)
	vao1.transform(vbo2, ModernGL.POINTS, 1024)
	ctx.copy_buffer(vbo1, vbo2)

Contributing

Indices and tables