ModernGL

ModernGL is a high performance rendering module for Python.

Installation

Install ModernGL with pip:

$ pip install ModernGL

Version check:

$ python -m moderngl --version  # 5.0.0 and above
$ python -m ModernGL --version  # before 5.0.0

Note

  • The package name is “ModernGL” for ModernGL<5.0.0
  • The package name is “moderngl” for ModernGL>=5.0.0

Reference

Context

class moderngl.Context

Class exposing OpenGL features. ModernGL objects can be created from this class.

Create

moderngl.create_context(require=None) → Context

Create a ModernGL context by loading OpenGL functions from an existing OpenGL context. An OpenGL context must exists. If rendering is done without a window please use the create_standalone_context() instead.

Keyword Arguments:
 require (int) – OpenGL version code.
Returns:Context object
moderngl.create_standalone_context(require=None) → Context

Create a standalone ModernGL context.

Keyword Arguments:
 require (int) – OpenGL version code.
Returns:Context object

ModernGL Objects

Context.program(vertex_shader, fragment_shader=None, geometry_shader=None, tess_control_shader=None, tess_evaluation_shader=None, varyings=()) → Program

Create a Program object.

Only linked programs will be returned.

A single shader in the shaders parameter is also accepted. The varyings are only used when a transform program is created.

Parameters:
  • shaders (list) – A list of Shader objects.
  • varyings (list) – A list of varying names.
Returns:

Program object

Context.simple_vertex_array(program, buffer, *attributes, index_buffer=None) → VertexArray

Create a VertexArray object.

Parameters:
  • program (Program) – The program used when rendering.
  • buffer (Buffer) – The buffer.
  • attributes (list) – A list of attribute names.
Keyword Arguments:
 

index_buffer (Buffer) – An index buffer.

Returns:

VertexArray object

Context.vertex_array(program, content, index_buffer=None, skip_errors=False) → VertexArray

Create a VertexArray object.

Parameters:
  • program (Program) – The program used when rendering.
  • content (list) – A list of (buffer, format, attributes).
  • index_buffer (Buffer) – An index buffer.
Keyword Arguments:
 

skip_errors (bool) – Ignore skip_errors varyings.

Returns:

VertexArray object

Context.buffer(data=None, reserve=0, dynamic=False) → Buffer

Create a Buffer object.

Parameters:

data (bytes) – Content of the new buffer.

Keyword Arguments:
 
  • reserve (int) – The number of bytes to reserve.
  • dynamic (bool) – Treat buffer as dynamic.
Returns:

Buffer object

Context.texture(size, components, data=None, samples=0, alignment=1, dtype='f1') → Texture

Create a Texture object.

Parameters:
  • size (tuple) – The width and height of the texture.
  • components (int) – The number of components 1, 2, 3 or 4.
  • data (bytes) – Content of the texture.
Keyword Arguments:
 
  • samples (int) – The number of samples. Value 0 means no multisample format.
  • alignment (int) – The byte alignment 1, 2, 4 or 8.
  • dtype (str) – Data type.
Returns:

Texture object

Context.depth_texture(size, data=None, samples=0, alignment=4) → Texture

Create a Texture object.

Parameters:
  • size (tuple) – The width and height of the texture.
  • data (bytes) – Content of the texture.
Keyword Arguments:
 
  • samples (int) – The number of samples. Value 0 means no multisample format.
  • alignment (int) – The byte alignment 1, 2, 4 or 8.
Returns:

Texture object

Context.texture3d(size, components, data=None, alignment=1, dtype='f1') → Texture3D

Create a Texture3D object.

Parameters:
  • size (tuple) – The width, height and depth of the texture.
  • components (int) – The number of components 1, 2, 3 or 4.
  • data (bytes) – Content of the texture.
Keyword Arguments:
 
  • alignment (int) – The byte alignment 1, 2, 4 or 8.
  • dtype (str) – Data type.
Returns:

Texture3D object

Context.texture_array(size, components, data=None, alignment=1, dtype='f1') → TextureArray

Create a TextureArray object.

Parameters:
  • size (tuple) – The width, height and layers of the texture.
  • components (int) – The number of components 1, 2, 3 or 4.
  • data (bytes) – Content of the texture.
Keyword Arguments:
 
  • alignment (int) – The byte alignment 1, 2, 4 or 8.
  • dtype (str) – Data type.
Returns:

Texture3D object

Context.texture_cube(size, components, data=None, alignment=1, dtype='f1') → TextureCube

Create a TextureCube object.

Parameters:
  • size (tuple) – The width, height and depth of the texture.
  • components (int) – The number of components 1, 2, 3 or 4.
  • data (bytes) – Content of the texture.
Keyword Arguments:
 
  • alignment (int) – The byte alignment 1, 2, 4 or 8.
  • dtype (str) – Data type.
Returns:

TextureCube object

Context.simple_framebuffer(size, components=4, samples=0, dtype='f1') → Framebuffer

A Framebuffer is a collection of buffers that can be used as the destination for rendering. The buffers for Framebuffer objects reference images from either Textures or Renderbuffers.

Parameters:
  • size (tuple) – The width and height of the renderbuffer.
  • components (int) – The number of components 1, 2, 3 or 4.
Keyword Arguments:
 
  • samples (int) – The number of samples. Value 0 means no multisample format.
  • dtype (str) – Data type.
Returns:

Framebuffer object

Context.framebuffer(color_attachments=(), depth_attachment=None) → Framebuffer

A Framebuffer is a collection of buffers that can be used as the destination for rendering. The buffers for Framebuffer objects reference images from either Textures or Renderbuffers.

Parameters:
Returns:

Framebuffer object

Context.renderbuffer(size, components=4, samples=0, dtype='f1') → Renderbuffer

Renderbuffer objects are OpenGL objects that contain images. They are created and used specifically with Framebuffer objects.

Parameters:
  • size (tuple) – The width and height of the renderbuffer.
  • components (int) – The number of components 1, 2, 3 or 4.
Keyword Arguments:
 
  • samples (int) – The number of samples. Value 0 means no multisample format.
  • dtype (str) – Data type.
Returns:

Renderbuffer object

Context.depth_renderbuffer(size, samples=0) → Renderbuffer

Renderbuffer objects are OpenGL objects that contain images. They are created and used specifically with Framebuffer objects.

Parameters:size (tuple) – The width and height of the renderbuffer.
Keyword Arguments:
 samples (int) – The number of samples. Value 0 means no multisample format.
Returns:Renderbuffer object
Context.scope(framebuffer, enable_only=None, textures=(), uniform_buffers=(), storage_buffers=()) → Scope

Create a Scope object.

Parameters:
  • framebuffer (Framebuffer) – The framebuffer to use when entering.
  • enable_only (int) – The enable_only flags to set when entering.
Keyword Arguments:
 
  • textures (list) – List of (texture, binding) tuples.
  • uniform_buffers (list) – List of (buffer, binding) tuples.
  • storage_buffers (list) – List of (buffer, binding) tuples.
Context.query(samples=False, any_samples=False, time=False, primitives=False) → Query

Create a Query object.

Keyword Arguments:
 
  • samples (bool) – Query GL_SAMPLES_PASSED or not.
  • any_samples (bool) – Query GL_ANY_SAMPLES_PASSED or not.
  • time (bool) – Query GL_TIME_ELAPSED or not.
  • primitives (bool) – Query GL_PRIMITIVES_GENERATED or not.
Context.compute_shader(source) → ComputeShader

A ComputeShader is a Shader Stage that is used entirely for computing arbitrary information. While it can do rendering, it is generally used for tasks not directly related to drawing.

Parameters:source (str) – The source of the compute shader.
Returns:ComputeShader object

Methods

Context.clear(red=0.0, green=0.0, blue=0.0, alpha=0.0, depth=1.0, viewport=None)

Clear the bound framebuffer. By default clears the screen.

If the viewport is not None then scrissor test will be used to clear the given viewport.

If the viewport is a 2-tuple it will clear the (0, 0, width, height) where (width, height) is the 2-tuple.

If the viewport is a 4-tuple it will clear the given viewport.

Parameters:
  • red (float) – color component.
  • green (float) – color component.
  • blue (float) – color component.
  • alpha (float) – alpha component.
  • depth (float) – depth value.
Keyword Arguments:
 

viewport (tuple) – The viewport.

Context.enable_only(flags)

Enable flags.

  • moderngl.NOTHING
  • moderngl.BLEND
  • moderngl.DEPTH_TEST
  • moderngl.CULL_FACE
  • moderngl.RASTERIZER_DISCARD
Parameters:flags (EnableFlag) – The flags to enable. Unset flags will be disabled.
Context.enable(flags)

Enable flags.

For valid flags, please see enable_only().

Parameters:flag (int) – The flags to enable.
Context.disable(flags)

Disable flags.

For valid flags, please see enable_only().

Parameters:flag (int) – The flags to disable.
Context.finish()

Wait for all drawing commands to finish.

Context.copy_buffer(dst, src, size=-1, read_offset=0, write_offset=0)

Copy buffer content.

Parameters:
  • dst (Buffer) – The destination buffer.
  • src (Buffer) – The source buffer.
  • size (int) – The number of bytes to copy.
Keyword Arguments:
 
  • read_offset (int) – The read offset.
  • write_offset (int) – The write offset.
Context.copy_framebuffer(dst, src)

Copy framebuffer content.

Use this method to:

  • blit framebuffers.
  • copy framebuffer content into a texture.
  • downsample framebuffers. (it will allow to read the framebuffer’s content)
  • downsample a framebuffer directly to a texture.
Parameters:
Context.detect_framebuffer(glo=None) → Framebuffer

Detect framebuffer.

Parameters:glo (int) – Framebuffer object.
Returns:Framebuffer object

Attributes

Context.line_width

float – Set the default line width.

Context.point_size

float – Set the default point size.

Context.depth_func

int – Set the default depth func.

Context.blend_func

tuple – Set the blend depth func.

Context.viewport

tuple – The viewport.

Context.version_code

int – The OpenGL version code.

Context.screen

Framebuffer – The default framebuffer.

Context.fbo

Framebuffer – The active framebuffer.

Context.front_face

str – The front_face.

Context.wireframe

bool – Wireframe settings for debugging.

Context.max_samples

int – The max samples.

Context.max_integer_samples

int – The max integer samples.

Context.max_texture_units

int – The max texture units.

Context.default_texture_unit

int – The default texture unit.

Context.multisample

bool – Multisample.

Context.error

str – The result of glGetError() but human readable. This values is provided for debug purposes only.

Context.info

dict – The result of multiple glGet.

Examples

ModernGL Context
import moderngl
# create a window
ctx = moderngl.create_context()
print(ctx.version_code)
Standalone ModernGL Context
import moderngl
ctx = moderngl.create_standalone_context()
print(ctx.version_code)
ContextManager

context_manager.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
import moderngl


class ContextManager:
    ctx = None

    @staticmethod
    def get_default_context(allow_fallback_standalone_context=True) -> moderngl.Context:
        '''
            Default context
        '''

        if ContextManager.ctx is None:
            try:
                ContextManager.ctx = moderngl.create_context()
            except moderngl.Error:
                if allow_fallback_standalone_context:
                    ContextManager.ctx = moderngl.create_standalone_context()
                else:
                    raise

        return ContextManager.ctx

example.py

1
2
3
4
from context_manager import ContextManager

ctx = ContextManager.get_default_context()
print(ctx.version_code)

Buffer

class moderngl.Buffer

Buffer objects are OpenGL objects that store an array of unformatted memory allocated by the OpenGL context, (data allocated on the GPU). These can be used to store vertex data, pixel data retrieved from images or the framebuffer, and a variety of other things.

A Buffer object cannot be instantiated directly, it requires a context. Use Context.buffer() to create one.

Copy buffer content using Context.copy_buffer().

Create

Context.buffer(data=None, reserve=0, dynamic=False) → Buffer

Create a Buffer object.

Parameters:

data (bytes) – Content of the new buffer.

Keyword Arguments:
 
  • reserve (int) – The number of bytes to reserve.
  • dynamic (bool) – Treat buffer as dynamic.
Returns:

Buffer object

Methods

Buffer.write(data, offset=0)

Write the content.

Parameters:data (bytes) – The data.
Keyword Arguments:
 offset (int) – The offset.
Buffer.write_chunks(data, start, step, count)

Split data to count equal parts.

Write the chunks using offsets calculated from start, step and stop.

Parameters:
  • data (bytes) – The data.
  • start (int) – First offset.
  • step (int) – Offset increment.
  • count (int) – The number of offsets.
Buffer.read(size=-1, offset=0) → bytes

Read the content.

Parameters:size (int) – The size. Value -1 means all.
Keyword Arguments:
 offset (int) – The offset.
Returns:bytes
Buffer.read_into(buffer, size=-1, offset=0, write_offset=0)

Read the content into a buffer.

Parameters:
  • buffer (bytarray) – The buffer that will receive the content.
  • size (int) – The size. Value -1 means all.
Keyword Arguments:
 
  • offset (int) – The read offset.
  • write_offset (int) – The write offset.
Buffer.read_chunks(chunk_size, start, step, count) → bytes

Read the content.

Read and concatenate the chunks of size chunk_size using offsets calculated from start, step and stop.

Parameters:
  • chunk_size (int) – The chunk size.
  • start (int) – First offset.
  • step (int) – Offset increment.
  • count (int) – The number of offsets.
Returns:

bytes

Buffer.read_chunks_into(buffer, chunk_size, start, step, count, write_offset=0)

Read the content.

Read and concatenate the chunks of size chunk_size using offsets calculated from start, step and stop.

Parameters:
  • buffer (bytarray) – The buffer that will receive the content.
  • chunk_size (int) – The chunk size.
  • start (int) – First offset.
  • step (int) – Offset increment.
  • count (int) – The number of offsets.
Keyword Arguments:
 

write_offset (int) – The write offset.

Buffer.clear(size=-1, offset=0, chunk=None)

Clear the content.

Parameters:

size (int) – The size. Value -1 means all.

Keyword Arguments:
 
  • offset (int) – The offset.
  • chunk (bytes) – The chunk to use repeatedly.
Buffer.bind_to_uniform_block(binding=0)

Bind the buffer to a uniform block.

Parameters:binding (int) – The uniform block binding.
Buffer.bind_to_storage_buffer(binding=0)

Bind the buffer to a shader storage buffer.

Parameters:binding (int) – The shader storage binding.
Buffer.orphan()

Orphan the buffer.

It is also called buffer re-specification.

Reallocate the buffer object before you start modifying it.

Since allocating storage is likely faster than the implicit synchronization, you gain significant performance advantages over synchronization.

The old storage will still be used by the OpenGL commands that have been sent previously. It is likely that the GL driver will not be doing any allocation at all, but will just be pulling an old free block off the unused buffer queue and use it, so it is likely to be very efficient.

Example

# For simplicity the VertexArray creation is omitted

>>> vbo = ctx.buffer(reserve=1024)

# Fill the buffer

>>> vbo.write(some_temorary_data)

# Issue a render call that uses the vbo

>>> vao.render(...)

# Orphan the buffer

>>> vbo.orphan()

# Issue another render call without waiting for the previous one

>>> vbo.write(some_temorary_data)
>>> vao.render(...)

Attributes

Buffer.size

int – The size of the buffer.

Buffer.dynamic

bool – Is the buffer created with the dynamic flag?

Buffer.glo

int – The internal OpenGL object. This values is provided for debug purposes only.

VertexArray

class moderngl.VertexArray

A VertexArray object is an OpenGL object that stores all of the state needed to supply vertex data. It stores the format of the vertex data as well as the Buffer objects providing the vertex data arrays.

In ModernGL, the VertexArray object also stores a reference for a Program object, and some Subroutine information.

A VertexArray object cannot be instantiated directly, it requires a context. Use Context.vertex_array() or Context.simple_vertex_array() to create one.

Note

Compared to OpenGL, VertexArray objects have some additional responsibilities:

Create

Context.simple_vertex_array(program, buffer, *attributes, index_buffer=None) → VertexArray

Create a VertexArray object.

Parameters:
  • program (Program) – The program used when rendering.
  • buffer (Buffer) – The buffer.
  • attributes (list) – A list of attribute names.
Keyword Arguments:
 

index_buffer (Buffer) – An index buffer.

Returns:

VertexArray object

Context.vertex_array(program, content, index_buffer=None, skip_errors=False) → VertexArray

Create a VertexArray object.

Parameters:
  • program (Program) – The program used when rendering.
  • content (list) – A list of (buffer, format, attributes).
  • index_buffer (Buffer) – An index buffer.
Keyword Arguments:
 

skip_errors (bool) – Ignore skip_errors varyings.

Returns:

VertexArray object

Methods

VertexArray.render(mode=None, vertices=-1, first=0, instances=1)

The render primitive (mode) must be the same as the input primitive of the GeometryShader.

Parameters:
  • mode (int) – By default TRIANGLES will be used.
  • vertices (int) – The number of vertices to transform.
Keyword Arguments:
 
  • first (int) – The index of the first vertex to start with.
  • instances (int) – The number of instances.
VertexArray.render_indirect(buffer, mode=None, count=-1, first=0)

The render primitive (mode) must be the same as the input primitive of the GeometryShader.

The draw commands are 5 integers: (count, instanceCount, firstIndex, baseVertex, baseInstance).

Parameters:
  • buffer (Buffer) – Indirect drawing commands.
  • mode (int) – By default TRIANGLES will be used.
  • count (int) – The number of draws.
Keyword Arguments:
 

first (int) – The index of the first indirect draw command.

VertexArray.transform(buffer, mode=None, vertices=-1, first=0, instances=1)

Transform vertices. Stores the output in a single buffer. The transform primitive (mode) must be the same as the input primitive of the GeometryShader.

Parameters:
  • buffer (Buffer) – The buffer to store the output.
  • mode (int) – By default POINTS will be used.
  • vertices (int) – The number of vertices to transform.
Keyword Arguments:
 
  • first (int) – The index of the first vertex to start with.
  • instances (int) – The number of instances.
VertexArray.bind(attribute, cls, buffer, fmt, offset=0, stride=0, divisor=0, normalize=False)

Bind individual attributes to buffers.

Parameters:
  • location (int) – The attribute location.
  • cls (str) – The attribute class. Valid values are f, i or d.
  • buffer (Buffer) – The buffer.
  • format (str) – The buffer format.
Keyword Arguments:
 
  • offset (int) – The offset.
  • stride (int) – The stride.
  • divisor (int) – The divisor.
  • normalize (bool) – The normalize parameter, if applicable.

Attributes

VertexArray.program

Program – The program assinged to the VertexArray. The program used when rendering or transforming primitives.

VertexArray.index_buffer

Buffer – The index buffer if the index_buffer is set, otherwise None.

VertexArray.vertices

int – The number of vertices detected. This is the minimum of the number of vertices possible per Buffer. The size of the index_buffer determines the number of vertices. Per instance vertex attributes does not affect this number.

VertexArray.subroutines

tuple – The subroutines assinged to the VertexArray. The subroutines used when rendering or transforming primitives.

VertexArray.glo

int – The internal OpenGL object. This values is provided for debug purposes only.

Program

class moderngl.Program

A Program object represents fully processed executable code in the OpenGL Shading Language, for one or more Shader stages.

In ModernGL, a Program object can be assigned to VertexArray objects. The VertexArray object is capable of binding the Program object once the VertexArray.render() or VertexArray.transform() is called.

Program objects has no method called use(), VertexArrays encapsulate this mechanism.

A Program object cannot be instantiated directly, it requires a context. Use Context.program() to create one.

Create

Context.program(vertex_shader, fragment_shader=None, geometry_shader=None, tess_control_shader=None, tess_evaluation_shader=None, varyings=()) → Program

Create a Program object.

Only linked programs will be returned.

A single shader in the shaders parameter is also accepted. The varyings are only used when a transform program is created.

Parameters:
  • shaders (list) – A list of Shader objects.
  • varyings (list) – A list of varying names.
Returns:

Program object

Methods

Program.get(key, default) → Union[Uniform, UniformBlock, Subroutine, Attribute, Varying]

Returns a Uniform, UniformBlock, Subroutine, Attribute or Varying.

Parameters:default – This is the value to be returned in case key does not exist.
Returns:Uniform, UniformBlock, Subroutine, Attribute or Varying

Attributes

Program.geometry_input

int – The geometry input primitive. The GeometryShader’s input primitive if the GeometryShader exists. The geometry input primitive will be used for validation.

Program.geometry_output

int – The geometry output primitive. The GeometryShader’s output primitive if the GeometryShader exists.

Program.geometry_vertices

int – The maximum number of vertices that the geometry shader will output.

Program.subroutines

tuple – The subroutine uniforms.

Program.glo

int – The internal OpenGL object. This values is provided for debug purposes only.

Examples

A simple program designed for rendering

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
my_render_program = ctx.program(
    vertex_shader='''
        #version 330

        in vec2 vert;

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

        out vec4 color;

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

A simple program designed for transforming

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
my_transform_program = ctx.program(
    vertex_shader='''
        #version 330

        in vec4 vert;
        out float vert_length;

        void main() {
            vert_length = length(vert);
        }
    ''',
    varyings=['vert_length']
)

Program Members

Uniform
class moderngl.Uniform

A uniform is a global GLSL variable declared with the “uniform” storage qualifier. These act as parameters that the user of a shader program can pass to that program.

In ModernGL, Uniforms can be accessed using Program.uniforms

Methods
Uniform.read() → bytes

Read the value of the uniform.

Uniform.write(data)

Write the value of the uniform.

Attributes
Uniform.location

int – The location of the uniform. The location holds the value returned by the glGetUniformLocation. To set the value of the uniform use the value instead.

Uniform.dimension

int – The dimension of the uniform.

GLSL type dimension
sampler2D 1
sampler2DCube 1
sampler2DShadow 1
bool 1
bvec2 2
bvec3 3
bvec4 4
int 1
ivec2 2
ivec3 3
ivec4 4
uint 1
uvec2 2
uvec3 3
uvec4 4
float 1
vec2 2
vec3 3
vec4 4
double 1
dvec2 2
dvec3 3
dvec4 4
mat2 4
mat2x3 6
mat2x4 8
mat3x2 6
mat3 9
mat3x4 12
mat4x2 8
mat4x3 12
mat4 16
dmat2 4
dmat2x3 6
dmat2x4 8
dmat3x2 6
dmat3 9
dmat3x4 12
dmat4x2 8
dmat4x3 12
dmat4 16
Uniform.array_length

int – The length of the array of the uniform. The array_length is 1 for non array uniforms.

Uniform.name

str – The name of the uniform. The name does not contain leading [0]. The name may contain [ ] when the uniform is part of a struct.

Uniform.value

The value of the uniform. Reading the value of the uniform may force the GPU to sync.

The value must be a tuple for non array uniforms. The value must be a list of tuples for array uniforms.

UniformBlock
class moderngl.UniformBlock
UniformBlock.binding

int – The binding of the uniform block.

UniformBlock.name

str – The name of the uniform block.

UniformBlock.index

int – The index of the uniform block.

UniformBlock.size

int – The size of the uniform block.

Subroutine
class moderngl.Subroutine

This class represents a program subroutine.

Subroutine.index

int – The index of the subroutine.

Subroutine.name

str – The name of the subroutine.

Attribute
class moderngl.Attribute

This class represents a program attribute.

Attribute.location

int – The location of the attribute. The result of the glGetAttribLocation.

Attribute.array_length

int – If the attribute is an array the array_length is the length of the array otherwise 1.

Attribute.dimension

int – The attribute dimension.

GLSL type dimension
int 1
ivec2 2
ivec3 3
ivec4 4
uint 1
uvec2 2
uvec3 3
uvec4 4
float 1
vec2 2
vec3 3
vec4 4
double 1
dvec2 2
dvec3 3
dvec4 4
mat2 4
mat2x3 6
mat2x4 8
mat3x2 6
mat3 9
mat3x4 12
mat4x2 8
mat4x3 12
mat4 16
dmat2 4
dmat2x3 6
dmat2x4 8
dmat3x2 6
dmat3 9
dmat3x4 12
dmat4x2 8
dmat4x3 12
dmat4 16
Attribute.shape

str – The shape is a single character, representing the scalar type of the attriute.

shape GLSL types
'i' int
ivec2 ivec3 ivec4
'I' uint
uvec2 uvec3 uvec4
'f' float
vec2 vec3 vec4
mat2 mat3 mat4
mat2x3 mat2x4 mat3x4 mat4x2 mat4x2 mat4x3
'd' double
dvec2 dvec3 dvec4
dmat2 dmat3 dmat4
dmat2x3 dmat2x4 dmat3x4 dmat4x2 dmat4x2 dmat4x3
Attribute.name

str – The attribute name. The name will be filtered to have no array syntax on it’s end. Attribute name without '[0]' ending if any.

Varying
class moderngl.Varying

This class represents a program varying.

Varying.name

str – The name of the varying.

Varying.number

int – The number of the varying.

Texture

class moderngl.Texture

A Texture is an OpenGL object that contains one or more images that all have the same image format. A texture can be used in two ways. It can be the source of a texture access from a Shader, or it can be used as a render target.

A Texture object cannot be instantiated directly, it requires a context. Use Context.texture() or Context.depth_texture() to create one.

Create

Context.texture(size, components, data=None, samples=0, alignment=1, dtype='f1') → Texture

Create a Texture object.

Parameters:
  • size (tuple) – The width and height of the texture.
  • components (int) – The number of components 1, 2, 3 or 4.
  • data (bytes) – Content of the texture.
Keyword Arguments:
 
  • samples (int) – The number of samples. Value 0 means no multisample format.
  • alignment (int) – The byte alignment 1, 2, 4 or 8.
  • dtype (str) – Data type.
Returns:

Texture object

Context.depth_texture(size, data=None, samples=0, alignment=4) → Texture

Create a Texture object.

Parameters:
  • size (tuple) – The width and height of the texture.
  • data (bytes) – Content of the texture.
Keyword Arguments:
 
  • samples (int) – The number of samples. Value 0 means no multisample format.
  • alignment (int) – The byte alignment 1, 2, 4 or 8.
Returns:

Texture object

Methods

Texture.read(level=0, alignment=1) → bytes

Read the content of the texture into a buffer.

Keyword Arguments:
 
  • level (int) – The mipmap level.
  • alignment (int) – The byte alignment of the pixels.
Returns:

bytes

Texture.read_into(buffer, level=0, alignment=1, write_offset=0)

Read the content of the texture into a buffer.

Parameters:

buffer (bytearray) – The buffer that will receive the pixels.

Keyword Arguments:
 
  • level (int) – The mipmap level.
  • alignment (int) – The byte alignment of the pixels.
  • write_offset (int) – The write offset.
Texture.write(data, viewport=None, level=0, alignment=1)

Update the content of the texture.

Parameters:
  • data (bytes) – The pixel data.
  • viewport (tuple) – The viewport.
Keyword Arguments:
 
  • level (int) – The mipmap level.
  • alignment (int) – The byte alignment of the pixels.
Texture.build_mipmaps(base=0, max_level=1000)

Generate mipmaps.

Texture.use(location=0)

Bind the texture.

Parameters:location (int) – The texture location. Same as the integer value that is used for sampler2D uniforms in the shaders. The value 0 will bind the texture to the GL_TEXTURE0 binding point.

Attributes

Texture.repeat_x

bool – The repeat_x of the texture.

Texture.repeat_y

bool – The repeat_y of the texture.

Texture.filter

tuple – The filter of the texture.

Texture.swizzle

str – The swizzle of the texture.

Texture.compare_func

tuple – The compare function of the depth texture.

Texture.width

int – The width of the texture.

Texture.height

int – The height of the texture.

Texture.size

tuple – The size of the texture.

Texture.dtype

str – Data type.

Texture.components

int – The number of components of the texture.

Texture.samples

int – The number of samples of the texture.

Texture.depth

bool – Is the texture a depth texture?

Texture.glo

int – The internal OpenGL object. This values is provided for debug purposes only.

Texture3D

class moderngl.Texture3D

A Texture is an OpenGL object that contains one or more images that all have the same image format. A texture can be used in two ways. It can be the source of a texture access from a Shader, or it can be used as a render target.

A Texture3D object cannot be instantiated directly, it requires a context. Use Context.texture3d() to create one.

Create

Context.texture3d(size, components, data=None, alignment=1, dtype='f1') → Texture3D

Create a Texture3D object.

Parameters:
  • size (tuple) – The width, height and depth of the texture.
  • components (int) – The number of components 1, 2, 3 or 4.
  • data (bytes) – Content of the texture.
Keyword Arguments:
 
  • alignment (int) – The byte alignment 1, 2, 4 or 8.
  • dtype (str) – Data type.
Returns:

Texture3D object

Methods

Texture3D.read(alignment=1) → bytes

Read the content of the texture into a buffer.

Keyword Arguments:
 alignment (int) – The byte alignment of the pixels.
Returns:bytes
Texture3D.read_into(buffer, alignment=1, write_offset=0)

Read the content of the texture into a buffer.

Parameters:

buffer (bytearray) – The buffer that will receive the pixels.

Keyword Arguments:
 
  • alignment (int) – The byte alignment of the pixels.
  • write_offset (int) – The write offset.
Texture3D.write(data, viewport=None, alignment=1)

Update the content of the texture.

Parameters:
  • data (bytes) – The pixel data.
  • viewport (tuple) – The viewport.
Keyword Arguments:
 

alignment (int) – The byte alignment of the pixels.

Texture3D.build_mipmaps(base=0, max_level=1000)

Generate mipmaps.

Texture3D.use(location=0)

Bind the texture.

Parameters:location (int) – The texture location. Same as the integer value that is used for sampler3D uniforms in the shaders. The value 0 will bind the texture to the GL_TEXTURE0 binding point.

Attributes

Texture3D.repeat_x

bool – The repeat_x of the texture.

Texture3D.repeat_y

bool – The repeat_y of the texture.

Texture3D.repeat_z

bool – The repeat_z of the texture.

Texture3D.filter

tuple – The filter of the texture.

Texture3D.swizzle

str – The swizzle of the texture.

Texture3D.width

int – The width of the texture.

Texture3D.height

int – The height of the texture.

Texture3D.depth

int – The depth of the texture.

Texture3D.size

tuple – The size of the texture.

Texture3D.dtype

str – Data type.

Texture3D.components

int – The number of components of the texture.

Texture3D.glo

int – The internal OpenGL object. This values is provided for debug purposes only.

TextureCube

class moderngl.TextureCube

A Texture is an OpenGL object that contains one or more images that all have the same image format. A texture can be used in two ways. It can be the source of a texture access from a Shader, or it can be used as a render target.

A Texture3D object cannot be instantiated directly, it requires a context. Use Context.texture_cube() to create one.

Create

Context.texture_cube(size, components, data=None, alignment=1, dtype='f1') → TextureCube

Create a TextureCube object.

Parameters:
  • size (tuple) – The width, height and depth of the texture.
  • components (int) – The number of components 1, 2, 3 or 4.
  • data (bytes) – Content of the texture.
Keyword Arguments:
 
  • alignment (int) – The byte alignment 1, 2, 4 or 8.
  • dtype (str) – Data type.
Returns:

TextureCube object

Methods

TextureCube.read(face, alignment=1) → bytes

Read a face from the cubemap texture.

Parameters:face (int) – The face to read.
Keyword Arguments:
 alignment (int) – The byte alignment of the pixels.
TextureCube.read_into(buffer, face, alignment=1, write_offset=0)

Read a face from the cubemap texture.

Parameters:
  • buffer (bytearray) – The buffer that will receive the pixels.
  • face (int) – The face to read.
Keyword Arguments:
 
  • alignment (int) – The byte alignment of the pixels.
  • write_offset (int) – The write offset.
TextureCube.write(face, data, viewport=None, alignment=1)

Update the content of the texture.

Parameters:
  • face (int) – The face to update.
  • data (bytes) – The pixel data.
  • viewport (tuple) – The viewport.
Keyword Arguments:
 

alignment (int) – The byte alignment of the pixels.

TextureCube.use(location=0)

Bind the cubemap texture.

Parameters:location (int) – The texture location. Same as the integer value that is used for sampler3D uniforms in the shaders. The value 0 will bind the texture to the GL_TEXTURE0 binding point.

Attributes

TextureCube.glo

int – The internal OpenGL object. This values is provided for debug purposes only.

Framebuffer

class moderngl.Framebuffer

A Framebuffer is a collection of buffers that can be used as the destination for rendering. The buffers for Framebuffer objects reference images from either Textures or Renderbuffers.

Create a Framebuffer using Context.framebuffer().

Create

Context.simple_framebuffer(size, components=4, samples=0, dtype='f1') → Framebuffer

A Framebuffer is a collection of buffers that can be used as the destination for rendering. The buffers for Framebuffer objects reference images from either Textures or Renderbuffers.

Parameters:
  • size (tuple) – The width and height of the renderbuffer.
  • components (int) – The number of components 1, 2, 3 or 4.
Keyword Arguments:
 
  • samples (int) – The number of samples. Value 0 means no multisample format.
  • dtype (str) – Data type.
Returns:

Framebuffer object

Context.framebuffer(color_attachments=(), depth_attachment=None) → Framebuffer

A Framebuffer is a collection of buffers that can be used as the destination for rendering. The buffers for Framebuffer objects reference images from either Textures or Renderbuffers.

Parameters:
Returns:

Framebuffer object

Methods

Framebuffer.clear(red=0.0, green=0.0, blue=0.0, alpha=0.0, depth=1.0, viewport=None)

Clear the framebuffer.

If the viewport is not None then scrissor test will be used to clear the given viewport.

If the viewport is a 2-tuple it will clear the (0, 0, width, height) where (width, height) is the 2-tuple.

If the viewport is a 4-tuple it will clear the given viewport.

Parameters:
  • red (float) – color component.
  • green (float) – color component.
  • blue (float) – color component.
  • alpha (float) – alpha component.
  • depth (float) – depth value.
Keyword Arguments:
 

viewport (tuple) – The viewport.

Framebuffer.read(viewport=None, components=3, attachment=0, alignment=1, dtype='f1') → bytes

Read the content of the framebuffer.

Parameters:
  • viewport (tuple) – The viewport.
  • components (int) – The number of components to read.
Keyword Arguments:
 
  • attachment (int) – The color attachment.
  • alignment (int) – The byte alignment of the pixels.
  • dtype (str) – Data type.
Returns:

bytes

Framebuffer.read_into(buffer, viewport=None, components=3, attachment=0, alignment=1, dtype='f1', write_offset=0)

Read the content of the framebuffer into a buffer.

Parameters:
  • buffer (bytearray) – The buffer that will receive the pixels.
  • viewport (tuple) – The viewport.
  • components (int) – The number of components to read.
Keyword Arguments:
 
  • attachment (int) – The color attachment.
  • alignment (int) – The byte alignment of the pixels.
  • dtype (str) – Data type.
  • write_offset (int) – The write offset.
Framebuffer.use()

Bind the framebuffer. Set the target for the VertexArray.render().

Attributes

Framebuffer.viewport

tuple – The viewport of the framebuffer.

Framebuffer.color_mask

tuple – The color mask of the framebuffer.

Framebuffer.depth_mask

tuple – The depth mask of the framebuffer.

Framebuffer.width

int – The width of the framebuffer.

Framebuffer.height

int – The height of the framebuffer.

Framebuffer.size

tuple – The size of the framebuffer.

Framebuffer.samples

int – The samples of the framebuffer.

Framebuffer.bits

dict – The bits of the framebuffer.

Framebuffer.color_attachments

tuple – The color attachments of the framebuffer.

Framebuffer.depth_attachment

Texture or Renderbuffer – The depth attachment of the framebuffer.

Framebuffer.glo

int – The internal OpenGL object. This values is provided for debug purposes only.

Renderbuffer

class moderngl.Renderbuffer

Renderbuffer objects are OpenGL objects that contain images. They are created and used specifically with Framebuffer objects. They are optimized for use as render targets, while Texture objects may not be, and are the logical choice when you do not need to sample from the produced image. If you need to resample, use Textures instead. Renderbuffer objects also natively accommodate multisampling.

A Renderbuffer object cannot be instantiated directly, it requires a context. Use Context.renderbuffer() or Context.depth_renderbuffer() to create one.

Create

Context.renderbuffer(size, components=4, samples=0, dtype='f1') → Renderbuffer

Renderbuffer objects are OpenGL objects that contain images. They are created and used specifically with Framebuffer objects.

Parameters:
  • size (tuple) – The width and height of the renderbuffer.
  • components (int) – The number of components 1, 2, 3 or 4.
Keyword Arguments:
 
  • samples (int) – The number of samples. Value 0 means no multisample format.
  • dtype (str) – Data type.
Returns:

Renderbuffer object

Context.depth_renderbuffer(size, samples=0) → Renderbuffer

Renderbuffer objects are OpenGL objects that contain images. They are created and used specifically with Framebuffer objects.

Parameters:size (tuple) – The width and height of the renderbuffer.
Keyword Arguments:
 samples (int) – The number of samples. Value 0 means no multisample format.
Returns:Renderbuffer object

Attributes

Renderbuffer.width

int – The width of the renderbuffer.

Renderbuffer.height

int – The height of the renderbuffer.

Renderbuffer.size

tuple – The size of the renderbuffer.

Renderbuffer.samples

int – The samples of the renderbuffer.

Renderbuffer.components

int – The components of the renderbuffer.

Renderbuffer.depth

bool – Is the renderbuffer a depth renderbuffer?

Renderbuffer.dtype

str – Data type.

Renderbuffer.glo

int – The internal OpenGL object. This values is provided for debug purposes only.

Scope

class moderngl.Scope

This class represents a Scope object.

Responsibilities on enter:

  • Set the enable flags.
  • Bind the framebuffer.
  • Assing textures to texture locations.
  • Assing buffers to uniform buffers.
  • Assing buffers to shader storage buffers.

Responsibilities on exit:

  • Restore the enable flags.
  • Restore the framebuffer.

Create

Context.scope(framebuffer, enable_only=None, textures=(), uniform_buffers=(), storage_buffers=()) → Scope

Create a Scope object.

Parameters:
  • framebuffer (Framebuffer) – The framebuffer to use when entering.
  • enable_only (int) – The enable_only flags to set when entering.
Keyword Arguments:
 
  • textures (list) – List of (texture, binding) tuples.
  • uniform_buffers (list) – List of (buffer, binding) tuples.
  • storage_buffers (list) – List of (buffer, binding) tuples.

Examples

Simple scope example

scope1 = ctx.scope(fbo1, moderngl.BLEND)
scope2 = ctx.scope(fbo2, moderngl.DEPTH_TEST | moderngl.CULL_FACE)

with scope1:
    # do some rendering

with scope2:
    # do some rendering

Scope for querying

query = ctx.query(samples=True)
scope = ctx.scope(ctx.screen, moderngl.DEPTH_TEST | moderngl.RASTERIZER_DISCARD)

with scope, query:
    # do some rendering

print(query.samples)

Understanding what scope objects do

scope = ctx.scope(
    framebuffer=framebuffer1,
    enable_flags=moderngl.BLEND,
    textures=[
        (texture1, 4),
        (texture2, 3),
    ],
    uniform_buffers=[
        (buffer1, 6),
        (buffer2, 5),
    ],
    storage_buffers=[
        (buffer3, 8),
    ],
)

# Let's assume we have some state before entering the scope
some_random_framebuffer.use()
some_random_texture.use(3)
some_random_buffer.bind_to_uniform_block(5)
some_random_buffer.bind_to_storage_buffer(8)
ctx.enable_only(moderngl.DEPTH_TEST)

with scope:
    # on __enter__
    #     framebuffer1.use()
    #     ctx.enable_only(moderngl.BLEND)
    #     texture1.use(4)
    #     texture2.use(3)
    #     buffer1.bind_to_uniform_block(6)
    #     buffer2.bind_to_uniform_block(5)
    #     buffer3.bind_to_storage_buffer(8)

    # do some rendering

    # on __exit__
    #     some_random_framebuffer.use()
    #     ctx.enable_only(moderngl.DEPTH_TEST)

# Originally we had the following, let's see what was changed
some_random_framebuffer.use()                 # This was restored hurray!
some_random_texture.use(3)                    # Have to restore it manually.
some_random_buffer.bind_to_uniform_block(5)   # Have to restore it manually.
some_random_buffer.bind_to_storage_buffer(8)  # Have to restore it manually.
ctx.enable_only(moderngl.DEPTH_TEST)          # This was restored too.

# Scope objects only do as much as neccessary.
# Restoring the framebuffer and enable flags are lowcost operations and
# without them you could get a hard time debugging the application.

Query

class moderngl.Query

This class represents a Query object.

Create

Context.query(samples=False, any_samples=False, time=False, primitives=False) → Query

Create a Query object.

Keyword Arguments:
 
  • samples (bool) – Query GL_SAMPLES_PASSED or not.
  • any_samples (bool) – Query GL_ANY_SAMPLES_PASSED or not.
  • time (bool) – Query GL_TIME_ELAPSED or not.
  • primitives (bool) – Query GL_PRIMITIVES_GENERATED or not.

Attributes

Query.samples

int – The number of samples passed.

Query.primitives

int – The number of primitives generated.

Query.elapsed

int – The time elapsed in nanoseconds.

Query.crender

ConditionalRender – Can be used in a with statement.

Examples

Simple query example

 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
import moderngl
import numpy as np

ctx = moderngl.create_standalone_context()
prog = ctx.program(
    vertex_shader='''
        #version 330

        in vec2 in_vert;

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

        out vec4 color;

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

vertices = np.array([
    0.0, 0.0,
    1.0, 0.0,
    0.0, 1.0,
], dtype='f4')

vbo = ctx.buffer(vertices.tobytes())
vao = ctx.simple_vertex_array(prog, vbo, 'in_vert')

fbo = ctx.simple_framebuffer((64, 64))
fbo.use()

query = ctx.query(samples=True, time=True)

with query:
    vao.render()

print('It took %d nanoseconds' % query.elapsed)
print('to render %d samples' % query.samples)

Output

It took 13529 nanoseconds
to render 496 samples

ConditionalRender

class moderngl.ConditionalRender

This class represents a ConditionalRender object.

ConditionalRender objects can only be accessed from Query objects.

Examples

Simple conditional rendering example

query = ctx.query(any_samples=True)

with query:
    vao1.render()

with query.crender:
    print('This will always get printed')
    vao2.render()  # But this will be rendered only if vao1 has passing samples.

ComputeShader

class moderngl.ComputeShader

A Compute Shader is a Shader Stage that is used entirely for computing arbitrary information. While it can do rendering, it is generally used for tasks not directly related to drawing.

Create

Context.compute_shader(source) → ComputeShader

A ComputeShader is a Shader Stage that is used entirely for computing arbitrary information. While it can do rendering, it is generally used for tasks not directly related to drawing.

Parameters:source (str) – The source of the compute shader.
Returns:ComputeShader object

Methods

ComputeShader.run(group_x=1, group_y=1, group_z=1)

Run the compute shader.

Parameters:
  • group_x (int) – The number of work groups to be launched in the X dimension.
  • group_y (int) – The number of work groups to be launched in the Y dimension.
  • group_z (int) – The number of work groups to be launched in the Z dimension.

Attributes

ComputeShader.source

str – The source code of the compute shader.

ComputeShader.glo

int – The internal OpenGL object. This values is provided for debug purposes only.

The Guide

A short introduction

What you will need?

To get something rendered, you will need a VertexArray.

VertexArrays can be created from a Program object and several Buffer objects.

To create a Program object, you will need some Shader objects.

Once you have your Program object, you can fill a Buffer with your data, then pass them to VertexArray, then call VertexArray.render().

All of the objects above can only be created from a Context object.

Here is our checklist:

  1. Install ModernGL.
  2. Create a Context.
  3. Create a Program object.
  4. Create a VertexArray object.

Proceede to the next step.

Install ModernGL

$ pip install --upgrade ModernGL

This tutorial will also use numpy to generate data and Pillow to save the final image.

$ pip install --upgrade numpy Pillow

Proceed to the next step.

Context

Let’s create a Standalone Context for now. It will help us write less code. Later you can reuse this code to render directly to a window.

1
2
3
import moderngl

ctx = moderngl.create_standalone_context()

Proceed to the next step.

Program

ModernGL is different from standard plotting libraries. You can define your own shader program to render stuff. This could complicate things, but also provides freedom on how you render your data.

Here is a sample program that passes the input vertex coordinates as is to screen coordinates.

Screen coordinates are in the [-1, 1], [-1, 1] range for x and y axes. The (-1, 1) point is the lower left corner of the screen.

Screen Coordinates

The screen coordinates

The program will also process a color information.

Entire source

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

ctx = moderngl.create_standalone_context()

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

        in vec2 in_vert;
        in vec3 in_color;

        out vec3 v_color;

        void main() {
            v_color = in_color;
            gl_Position = vec4(in_vert, 0.0, 1.0);
        }
    ''',
    fragment_shader='''
        #version 330

        in vec3 v_color;

        out vec3 f_color;

        void main() {
            f_color = v_color;
        }
    ''',
)

Vertex Shader

in vec2 in_vert;
in vec3 in_color;

out vec3 v_color;

void main() {
    v_color = in_color;
    gl_Position = vec4(in_vert, 0.0, 1.0);
}

Fragment Shader

in vec3 v_color;

out vec3 f_color;

void main() {
    f_color = v_color;
}

Proceed to the next step.

VertexArray

 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
import moderngl
import numpy as np

ctx = moderngl.create_standalone_context()

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

        in vec2 in_vert;
        in vec3 in_color;

        out vec3 v_color;

        void main() {
            v_color = in_color;
            gl_Position = vec4(in_vert, 0.0, 1.0);
        }
    ''',
    fragment_shader='''
        #version 330

        in vec3 v_color;

        out vec3 f_color;

        void main() {
            f_color = v_color;
        }
    ''',
)

x = np.linspace(-1.0, 1.0, 50)
y = np.random.rand(50) - 0.5
r = np.ones(50)
g = np.zeros(50)
b = np.zeros(50)

vertices = np.dstack([x, y, r, g, b])

vbo = ctx.buffer(vertices.astype('f4').tobytes())
vao = ctx.simple_vertex_array(prog, vbo, 'in_vert', 'in_color')

Proceed to the next step.

Rendering

 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
import moderngl
import numpy as np
from PIL import Image

ctx = moderngl.create_standalone_context()

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

        in vec2 in_vert;
        in vec3 in_color;

        out vec3 v_color;

        void main() {
            v_color = in_color;
            gl_Position = vec4(in_vert, 0.0, 1.0);
        }
    ''',
    fragment_shader='''
        #version 330

        in vec3 v_color;

        out vec3 f_color;

        void main() {
            f_color = v_color;
        }
    ''',
)

x = np.linspace(-1.0, 1.0, 50)
y = np.random.rand(50) - 0.5
r = np.ones(50)
g = np.zeros(50)
b = np.zeros(50)

vertices = np.dstack([x, y, r, g, b])

vbo = ctx.buffer(vertices.astype('f4').tobytes())
vao = ctx.simple_vertex_array(prog, vbo, 'in_vert', 'in_color')

fbo = ctx.simple_framebuffer((512, 512))
fbo.use()
fbo.clear(0.0, 0.0, 0.0, 1.0)
vao.render(moderngl.LINE_STRIP)

Image.frombytes('RGB', fbo.size, fbo.read(), 'raw', 'RGB', 0, -1).show()

Miscellaneous

Differneces between ModernGL5 and ModernGL4

Package Name

ModernGL4

import ModernGL  # mixed case

ModernGL5

import moderngl  # this is pep8 style



Program Creation

ModernGL4

my_program = ctx.program([  # extra list
    # vertex_shader returned a Shader object
    ctx.vertex_shader('''
        ...
    '''),
    # fragment_shader returned a Shader object
    ctx.fragment_shader('''
        ...
    '''),
])

ModernGL5

my_program = ctx.program(  # no list needed
    # vertex_shader is a keyword argument
    vertex_shader='''
        ...
    ''',
    # fragment_shader is a keyword argument
    fragment_shader='''
        ...
    ''',
)



Program Varyings

ModernGL4

my_program = ctx.program(
    ctx.vertex_shader('''
        ...
    '''),
    ['out_vert', 'out_norm']  # no keyword argument needed
])

ModernGL5

my_program = ctx.program(
    vertex_shader='''
        ...
    ''',
    varyings=['out_vert', 'out_norm'],  # varyings are explicitly given
)



Program Members

ModernGL4

my_program.uniforms['ModelViewMatrix'].value = ...
my_program.uniform_buffers['UniformBuffer'].binding = ...

ModernGL5

my_program['ModelViewMatrix'].value = ...
my_program['UniformBuffer'].binding = ...



Texture Pixel Types

ModernGL4

my_texture = ctx.texture(size, 4, floats=True)  # floats or not floats

ModernGL5

my_texture = ctx.texture(size, 4, dtype='f4')  # floats=True
my_texture = ctx.texture(size, 4, dtype='f2')  # half-floats
my_texture = ctx.texture(size, 4, dtype='f1')  # floats=False
my_texture = ctx.texture(size, 4, dtype='i4')  # integers

This also apply for Texture3D, TextureCube and Renderbuffer.




Buffer Format

ModernGL4

my_vertex_array = ctx.vertex_array(prog, [
    (vbo1, '3f3f', ['in_vert', 'in_norm']),  # extra list object
    #        ^ no space between the attributes
    ...
])

ModernGL5

my_vertex_array = ctx.vertex_array(prog, [
    (vbo1, '3f 3f', 'in_vert', 'in_norm'),  # no list needed
    #         ^ space is obligatory
    ...
])



Buffer Format Half-Floats

ModernGL4

Not available in ModernGL4

ModernGL5

my_vertex_array = ctx.vertex_array(prog, [
    (vbo1, '3f2 3f2', 'in_vert', 'in_norm'),  # '3f2' means '3' of 'f2', where 'f2' is a half-float
    ...
])



Buffer Format Padding

ModernGL4

my_vertex_array = ctx.vertex_array(prog, [
    (vbo1, '3f12x', ['in_vert']),  # same as above, in_norm was replaced with padding
    ...
])

ModernGL5

my_vertex_array = ctx.vertex_array(prog, [
    (vbo1, '3f 3x4', ['in_vert']),  # '3x4' means '3' of 'x4', where 'x4' means 4 bytes of padding
    ...
])



Buffer Format Errors

Let’s assume in_vert was declared as: in vec4 in_vert

ModernGL4

my_vertex_array = ctx.vertex_array(prog, [
    (vbo1, '3f', ['in_vert']),  # throws an error (3 != 4)
    ...
])

my_vertex_array = ctx.vertex_array(prog, [
    (vbo1, '4i', ['in_vert']),  # throws an error (float != int)
    ...
])

ModernGL5

my_vertex_array = ctx.vertex_array(prog, [
    (vbo1, '3f', 'in_vert'),  # totally fine
    ...
])

my_vertex_array = ctx.vertex_array(prog, [
    (vbo1, '4i', 'in_vert'),  # totally fine
    ...
])



Found something not covered here? Please file an issue.

Indices and tables