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.

Example:

# Accept the current context version
ctx = moderngl.create_context()

# Require at least OpenGL 4.3
ctx = moderngl.create_context(require=430)
Keyword Arguments:
 require (int) – OpenGL version code.
Returns:Context object
moderngl.create_standalone_context(require=None) → Context

Create a standalone ModernGL context.

Example:

# Create a context with highest possible supported version
ctx = moderngl.create_context()

# Require at least OpenGL 4.3
ctx = moderngl.create_context(require=430)
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, index_element_size=4) → 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_element_size (int) – byte size of each index element, 1, 2 or 4.
  • index_buffer (Buffer) – An index buffer.
Returns:

VertexArray object

Context.vertex_array(program, content, index_buffer=None, index_element_size=4, 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:
 
  • index_element_size (int) – byte size of each index element, 1, 2 or 4.
  • 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, layers) of the texture.
  • components (int) – The number of components 1, 2, 3 or 4.
  • data (bytes) – Content of the texture. The size must be (width, height * layers) so each layer is stacked vertically.
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 of the texture. Each side of the cube will have this size.
  • 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
Context.sampler(repeat_x=True, repeat_y=True, repeat_z=True, filter=None, anisotropy=1.0, compare_func='?', border_color=None, min_lod=-1000.0, max_lod=1000.0) → Sampler

Create a Sampler object.

Keyword Arguments:
 
  • repeat_x (bool) – Repeat texture on x
  • repeat_y (bool) – Repeat texture on y
  • repeat_z (bool) – Repeat texture on z
  • filter (tuple) – The min and max filter
  • anisotropy (float) – Number of samples for anisotropic filtering. Any value greater than 1.0 counts as a use of anisotropic filtering
  • compare_func – Compare function for depth textures
  • border_color (tuple) – The (r, g, b, a) color for the texture border. When this value is set the repeat_ values are overriden setting the texture wrap to return the border color when outside [0, 1] range.
  • min_lod (float) – Minimum level-of-detail parameter (Default -1000.0). This floating-point value limits the selection of highest resolution mipmap (lowest mipmap level)
  • max_lod (float) – Minimum level-of-detail parameter (Default 1000.0). This floating-point value limits the selection of the lowest resolution mipmap (highest mipmap level)
Context.clear_samplers(start=0, end=-1)

Unbinds samplers from texture units. Sampler bindings do clear automatically between every frame, but lingering samplers can still be a source of weird bugs during the frame rendering. This methods provides a fairly brute force and efficient way to ensure texture units are clear.

Keyword Arguments:
 
  • start (int) – The texture unit index to start the clearing samplers
  • stop (int) – The texture unit index to stop clearing samplers

Example:

# Clear texture unit 0, 1, 2, 3, 4
ctx.clear_samplers(start=0, end=5)

# Clear texture unit 4, 5, 6, 7
ctx.clear_samplers(start=4, end=8)

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)

Clears all existing flags applying new ones

Available flags:

  • moderngl.NOTHING
  • moderngl.BLEND
  • moderngl.DEPTH_TEST
  • moderngl.CULL_FACE
  • moderngl.RASTERIZER_DISCARD

Examples:

# Disable all flags
ctx.enable_only(moderngl.NOTHING)

# Ensure only depth testing and face culling is enabled
ctx.enable_only(moderngl.DEPTH_TEST | moderngl.CULL_FACE)
Parameters:flags (EnableFlag) – The flags to enable
Context.enable(flags)

Enable flags.

For valid flags, please see enable_only().

Examples:

# Enable a single flag
ctx.enable(moderngl.DEPTH_TEST)

# Enable multiple flags
ctx.enable(moderngl.DEPTH_TEST | moderngl.CULL_FACE | moderngl.BLEND)
Parameters:flag (int) – The flags to enable.
Context.disable(flags)

Disable flags.

For valid flags, please see enable_only().

Examples:

# Only disable depth testing
ctx.disable(moderngl.DEPTH_TEST)

# Disable depth testing and face culling
ctx.disable(moderngl.DEPTH_TEST | moderngl.CULL_FACE)
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

Set the default line width.

Type:float
Context.point_size

Set/get the default point size.

Type:float
Context.depth_func

Set the default depth func. The depth function is set using a string.

Example:

ctx.depth_func = '<='  # GL_LEQUAL
ctx.depth_func = '<'   # GL_LESS
ctx.depth_func = '>='  # GL_GEQUAL
ctx.depth_func = '>'   # GL_GREATER
ctx.depth_func = '=='  # GL_EQUAL
ctx.depth_func = '!='  # GL_NOTEQUAL
ctx.depth_func = '0'   # GL_NEVER
ctx.depth_func = '1'   # GL_ALWAYS
Type:int
Context.blend_func

Set the blend depth func.

Example:

ctx.enable(moderngl.BLEND)
ctx.blend_func = moderngl.SRC_ALPHA, moderngl.ONE_MINUS_SRC_ALPHA
Type:tuple
Context.viewport

The viewport of the active framebuffer. Modifies or gets the viewport.

Example:

>>> ctx.viewport
(0, 0, 1280, 720)
>>> ctx.viewport = (0, 0, 640, 360)
>>> ctx.viewport
(0, 0, 640, 360)

If no framebuffer is bound (0, 0, 0, 0) will be returned.

Type:tuple
Context.version_code

The OpenGL version code. Reports 410 for OpenGL 4.1

Type:int
Context.screen

A Framebuffer instance representing the screen usually set when creating a context with create_context() attaching to an existing context. This is the special system framebuffer represented by framebuffer id=0.

When creating a standalone context this property is not set.

Type:Framebuffer
Context.fbo

The active framebuffer. Set every time Framebuffer.use() is called.

Type:Framebuffer
Context.front_face

The front_face. Acceptable values are 'ccw' (default) or 'cw'.

Face culling must be enabled for this to have any effect: ctx.enable(moderngl.CULL_FACE).

Example:

# Triangles winded counter-clockwise considered front facing
ctx.front_face = 'ccw'
# Triangles winded clockwise considered front facing
ctx.front_face = 'cw'
Type:str
Context.wireframe

Wireframe settings for debugging.

Type:bool
Context.max_samples

The maximum supported number of samples for multisampling

Type:int
Context.max_integer_samples

The max integer samples.

Type:int
Context.max_texture_units

The max texture units.

Type:int
Context.default_texture_unit

The default texture unit.

Type:int
Context.max_anisotropy

The maximum value supported for anisotropic filtering.

Type:float
Context.multisample

Enable/disable multisample mode (GL_MULTISAMPLE). This property is write only.

Example:

# Enable
ctx.multisample = True
# Disable
ctx.multisample = False
Type:bool
Context.patch_vertices

The number of vertices that will be used to make up a single patch primitive.

Type:int
Context.error

The result of glGetError() but human readable. This values is provided for debug purposes only and is likely to reduce performace when used in a draw loop.

Type:str
Context.info

Information about the context

Example:

{
    'GL_VENDOR': 'NVIDIA Corporation',
    'GL_RENDERER': 'NVIDIA GeForce GT 650M OpenGL Engine',
    'GL_VERSION': '4.1 NVIDIA-10.32.0 355.11.10.10.40.102',
    'GL_POINT_SIZE_RANGE': (1.0, 2047.0),
    'GL_SMOOTH_LINE_WIDTH_RANGE': (0.5, 1.0),
    'GL_ALIASED_LINE_WIDTH_RANGE': (1.0, 1.0),
    'GL_POINT_FADE_THRESHOLD_SIZE': 1.0,
    'GL_POINT_SIZE_GRANULARITY': 0.125,
    'GL_SMOOTH_LINE_WIDTH_GRANULARITY': 0.125,
    'GL_MIN_PROGRAM_TEXEL_OFFSET': -8.0,
    'GL_MAX_PROGRAM_TEXEL_OFFSET': 7.0,
    'GL_MINOR_VERSION': 1,
    'GL_MAJOR_VERSION': 4,
    'GL_SAMPLE_BUFFERS': 0,
    'GL_SUBPIXEL_BITS': 8,
    'GL_CONTEXT_PROFILE_MASK': 1,
    'GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT': 256,
    'GL_DOUBLEBUFFER': False,
    'GL_STEREO': False,
    'GL_MAX_VIEWPORT_DIMS': (16384, 16384),
    'GL_MAX_3D_TEXTURE_SIZE': 2048,
    'GL_MAX_ARRAY_TEXTURE_LAYERS': 2048,
    'GL_MAX_CLIP_DISTANCES': 8,
    'GL_MAX_COLOR_ATTACHMENTS': 8,
    'GL_MAX_COLOR_TEXTURE_SAMPLES': 8,
    'GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS': 233472,
    'GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS': 231424,
    'GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS': 80,
    'GL_MAX_COMBINED_UNIFORM_BLOCKS': 70,
    'GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS': 233472,
    'GL_MAX_CUBE_MAP_TEXTURE_SIZE': 16384,
    'GL_MAX_DEPTH_TEXTURE_SAMPLES': 8,
    'GL_MAX_DRAW_BUFFERS': 8,
    'GL_MAX_DUAL_SOURCE_DRAW_BUFFERS': 1,
    'GL_MAX_ELEMENTS_INDICES': 150000,
    'GL_MAX_ELEMENTS_VERTICES': 1048575,
    'GL_MAX_FRAGMENT_INPUT_COMPONENTS': 128,
    'GL_MAX_FRAGMENT_UNIFORM_COMPONENTS': 4096,
    'GL_MAX_FRAGMENT_UNIFORM_VECTORS': 1024,
    'GL_MAX_FRAGMENT_UNIFORM_BLOCKS': 14,
    'GL_MAX_GEOMETRY_INPUT_COMPONENTS': 128,
    'GL_MAX_GEOMETRY_OUTPUT_COMPONENTS': 128,
    'GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS': 16,
    'GL_MAX_GEOMETRY_UNIFORM_BLOCKS': 14,
    'GL_MAX_GEOMETRY_UNIFORM_COMPONENTS': 2048,
    'GL_MAX_INTEGER_SAMPLES': 1,
    'GL_MAX_SAMPLES': 8,
    'GL_MAX_RECTANGLE_TEXTURE_SIZE': 16384,
    'GL_MAX_RENDERBUFFER_SIZE': 16384,
    'GL_MAX_SAMPLE_MASK_WORDS': 1,
    'GL_MAX_SERVER_WAIT_TIMEOUT': -1,
    'GL_MAX_TEXTURE_BUFFER_SIZE': 134217728,
    'GL_MAX_TEXTURE_IMAGE_UNITS': 16,
    'GL_MAX_TEXTURE_LOD_BIAS': 15,
    'GL_MAX_TEXTURE_SIZE': 16384,
    'GL_MAX_UNIFORM_BUFFER_BINDINGS': 70,
    'GL_MAX_UNIFORM_BLOCK_SIZE': 65536,
    'GL_MAX_VARYING_COMPONENTS': 0,
    'GL_MAX_VARYING_VECTORS': 31,
    'GL_MAX_VARYING_FLOATS': 0,
    'GL_MAX_VERTEX_ATTRIBS': 16,
    'GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS': 16,
    'GL_MAX_VERTEX_UNIFORM_COMPONENTS': 4096,
    'GL_MAX_VERTEX_UNIFORM_VECTORS': 1024,
    'GL_MAX_VERTEX_OUTPUT_COMPONENTS': 128,
    'GL_MAX_VERTEX_UNIFORM_BLOCKS': 14,
    'GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET': 0,
    'GL_MAX_VERTEX_ATTRIB_BINDINGS': 0,
    'GL_VIEWPORT_BOUNDS_RANGE': (-32768, 32768),
    'GL_VIEWPORT_SUBPIXEL_BITS': 0,
    'GL_MAX_VIEWPORTS': 16
}
Type:dict
Context.extra

Any - Attribute for storing user defined objects

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, offset=0, size=-1)

Bind the buffer to a uniform block.

Parameters:

binding (int) – The uniform block binding.

Keyword Arguments:
 
  • offset (int) – The offset.
  • size (int) – The size. Value -1 means all.
Buffer.bind_to_storage_buffer(binding=0, offset=0, size=-1)

Bind the buffer to a shader storage buffer.

Parameters:

binding (int) – The shader storage binding.

Keyword Arguments:
 
  • offset (int) – The offset.
  • size (int) – The size. Value -1 means all.
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

The size of the buffer.

Type:int
Buffer.dynamic

Is the buffer created with the dynamic flag?

Type:bool
Buffer.glo

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

Type:int
Buffer.extra

Any - Attribute for storing user defined objects

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, index_element_size=4) → 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_element_size (int) – byte size of each index element, 1, 2 or 4.
  • index_buffer (Buffer) – An index buffer.
Returns:

VertexArray object

Context.vertex_array(program, content, index_buffer=None, index_element_size=4, 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:
 
  • index_element_size (int) – byte size of each index element, 1, 2 or 4.
  • 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

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

Type:Program
VertexArray.index_buffer

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

Type:Buffer
VertexArray.index_element_size

The byte size of each element in the index buffer

Type:int
VertexArray.vertices

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.

Type:int
VertexArray.subroutines

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

Type:tuple
VertexArray.glo

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

Type:int
VertexArray.extra

Any - Attribute for storing user defined objects

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

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

Type:int
Program.geometry_output

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

Type:int
Program.geometry_vertices

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

Type:int
Program.subroutines

The subroutine uniforms.

Type:tuple
Program.glo

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

Type:int
Program.extra

Any - Attribute for storing user defined objects

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

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.

Type:int
Uniform.dimension

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
Type:int
Uniform.array_length

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

Type:int
Uniform.name

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

Type:str
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.

Uniform.extra

Any - Attribute for storing user defined objects

UniformBlock
class moderngl.UniformBlock
UniformBlock.binding

The binding of the uniform block.

Type:int
UniformBlock.name

The name of the uniform block.

Type:str
UniformBlock.index

The index of the uniform block.

Type:int
UniformBlock.size

The size of the uniform block.

Type:int
UniformBlock.extra

Any - Attribute for storing user defined objects

Subroutine
class moderngl.Subroutine

This class represents a program subroutine.

Subroutine.index

The index of the subroutine.

Type:int
Subroutine.name

The name of the subroutine.

Type:str
Subroutine.extra

Any - Attribute for storing user defined objects

Attribute
class moderngl.Attribute

This class represents a program attribute.

Attribute.location

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

Type:int
Attribute.array_length

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

Type:int
Attribute.dimension

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
Type:int
Attribute.shape

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
Type:str
Attribute.name

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

Type:str
Attribute.extra

Any - Attribute for storing user defined objects

Varying
class moderngl.Varying

This class represents a program varying.

Varying.name

The name of the varying.

Type:str
Varying.number

The number of the varying.

Type:int
Varying.extra

Any - Attribute for storing user defined objects

Sampler

class moderngl.Sampler

A Sampler Object is an OpenGL Object that stores the sampling parameters for a Texture access inside of a shader. When a sampler object is bound to a texture image unit, the internal sampling parameters for a texture bound to the same image unit are all ignored. Instead, the sampling parameters are taken from this sampler object.

Unlike textures, a samplers state can also be changed freely be at any time without the sampler object being bound/in use.

Samplers are bound to a texture unit and not a texture itself. Be careful with leaving samplers bound to texture units as it can cause texture incompletness issues (the texture bind is ignored).

Sampler bindings do clear automatically between every frame so a texture unit need at least one bind/use per frame.

Create

Context.sampler(repeat_x=True, repeat_y=True, repeat_z=True, filter=None, anisotropy=1.0, compare_func='?', border_color=None, min_lod=-1000.0, max_lod=1000.0) → Sampler

Create a Sampler object.

Keyword Arguments:
 
  • repeat_x (bool) – Repeat texture on x
  • repeat_y (bool) – Repeat texture on y
  • repeat_z (bool) – Repeat texture on z
  • filter (tuple) – The min and max filter
  • anisotropy (float) – Number of samples for anisotropic filtering. Any value greater than 1.0 counts as a use of anisotropic filtering
  • compare_func – Compare function for depth textures
  • border_color (tuple) – The (r, g, b, a) color for the texture border. When this value is set the repeat_ values are overriden setting the texture wrap to return the border color when outside [0, 1] range.
  • min_lod (float) – Minimum level-of-detail parameter (Default -1000.0). This floating-point value limits the selection of highest resolution mipmap (lowest mipmap level)
  • max_lod (float) – Minimum level-of-detail parameter (Default 1000.0). This floating-point value limits the selection of the lowest resolution mipmap (highest mipmap level)

Methods

Sampler.use(location=0)

Bind the sampler to a texture unit

Parameters:location (int) – The texture unit
Sampler.clear(location=0)

Clear the sampler binding on a texture unit

Parameters:location (int) – The texture unit
Sampler.release()

Release/destroy the ModernGL object.

Attributes

Sampler.repeat_x

The x repeat flag for the sampler (Default True)

Example:

# Enable texture repeat (GL_REPEAT)
sampler.repeat_x = True

# Disable texture repeat (GL_CLAMP_TO_EDGE)
sampler.repeat_x = False
Type:bool
Sampler.repeat_y

The y repeat flag for the sampler (Default True)

Example:

# Enable texture repeat (GL_REPEAT)
sampler.repeat_y = True

# Disable texture repeat (GL_CLAMP_TO_EDGE)
sampler.repeat_y = False
Type:bool
Sampler.repeat_z

The z repeat flag for the sampler (Default True)

Example:

# Enable texture repeat (GL_REPEAT)
sampler.repeat_z = True

# Disable texture repeat (GL_CLAMP_TO_EDGE)
sampler.repeat_z = False
Type:bool
Sampler.filter

The minification and magnification filter for the sampler. (Default (moderngl.LINEAR. moderngl.LINEAR))

Example:

sampler.filter == (monderngl.NEAREST, moderngl.NEAREST)
sampler.filter == (monderngl.LINEAR_MIPMAP_LINEAR, moderngl.LINEAR)
sampler.filter == (monderngl.NEAREST_MIPMAP_LINEAR, moderngl.NEAREST)
sampler.filter == (monderngl.LINEAR_MIPMAP_NEAREST, moderngl.NEAREST)
Type:tuple
Sampler.compare_func

The compare function for a depth textures (Default '?')

By default samplers don’t have depth comparison mode enabled. This means that depth texture values can be read as a sampler2D using texture() in a GLSL shader by default.

When setting this property to a valid compare mode, GL_TEXTURE_COMPARE_MODE is set to GL_COMPARE_REF_TO_TEXTURE so that texture lookup functions in GLSL will return a depth comparison result instead of the actual depth value.

Accepted compare functions:

.compare_func = ''    # Disale depth comparison completely
sampler.compare_func = '<='  # GL_LEQUAL
sampler.compare_func = '<'   # GL_LESS
sampler.compare_func = '>='  # GL_GEQUAL
sampler.compare_func = '>'   # GL_GREATER
sampler.compare_func = '=='  # GL_EQUAL
sampler.compare_func = '!='  # GL_NOTEQUAL
sampler.compare_func = '0'   # GL_NEVER
sampler.compare_func = '1'   # GL_ALWAYS
Type:tuple
Sampler.anisotropy

Number of samples for anisotropic filtering (Default 1.0). The value will be clamped in range 1.0 and ctx.max_anisotropy.

Any value greater than 1.0 counts as a use of anisotropic filtering:

# Disable anisotropic filtering
sampler.anisotropy = 1.0

# Enable anisotropic filtering suggesting 16 samples as a maximum
sampler.anisotropy = 16.0
Type:float
Sampler.border_color

When setting this value the repeat_ values are overriden setting the texture wrap to return the border color when outside [0, 1] range.

Example:

# Red border color
sampler.border_color = (1.0, 0.0, 0.0, 0.0)
Sampler.min_lod

Minimum level-of-detail parameter (Default -1000.0). This floating-point value limits the selection of highest resolution mipmap (lowest mipmap level)

Type:float
Sampler.max_lod

Minimum level-of-detail parameter (Default 1000.0). This floating-point value limits the selection of the lowest resolution mipmap (highest mipmap level)

Type:float
Sampler.extra

Any - Attribute for storing user defined objects

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.

This also changes the texture filter to LINEAR_MIPMAP_LINEAR, LINEAR (Will be removed in 6.x)

Keyword Arguments:
 
  • base (int) – The base level
  • max_level (int) – The maximum levels to generate
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

The x repeat flag for the texture (Default True)

Example:

# Enable texture repeat (GL_REPEAT)
texture.repeat_x = True

# Disable texture repeat (GL_CLAMP_TO_EDGE)
texture.repeat_x = False
Type:bool
Texture.repeat_y

The y repeat flag for the texture (Default True)

Example:

# Enable texture repeat (GL_REPEAT)
texture.repeat_y = True

# Disable texture repeat (GL_CLAMP_TO_EDGE)
texture.repeat_y = False
Type:bool
Texture.filter

The minification and magnification filter for the texture. (Default (moderngl.LINEAR. moderngl.LINEAR))

Example:

texture.filter == (monderngl.NEAREST, moderngl.NEAREST)
texture.filter == (monderngl.LINEAR_MIPMAP_LINEAR, moderngl.LINEAR)
texture.filter == (monderngl.NEAREST_MIPMAP_LINEAR, moderngl.NEAREST)
texture.filter == (monderngl.LINEAR_MIPMAP_NEAREST, moderngl.NEAREST)
Type:tuple
Texture.swizzle

The swizzle mask of the texture (Default 'RGBA').

The swizzle mask change/reorder the vec4 value returned by the texture() function in a GLSL shaders. This is represented by a 4 character string were each character can be:

'R' GL_RED
'G' GL_GREEN
'B' GL_BLUE
'A' GL_ALPHA
'0' GL_ZERO
'1' GL_ONE

Example:

# Alpha channel will always return 1.0
texture.swizzle = 'RGB1'

# Only return the red component. The rest is masked to 0.0
texture.swizzle = 'R000'

# Reverse the components
texture.swizzle = 'ABGR'
Type:str
Texture.compare_func

The compare function of the depth texture (Default '<=')

By default depth textures have GL_TEXTURE_COMPARE_MODE set to GL_COMPARE_REF_TO_TEXTURE, meaning any texture lookup will return a depth comparison value.

If you need to read the actual depth value in shaders, setting compare_func to a blank string will set GL_TEXTURE_COMPARE_MODE to GL_NONE making you able to read the depth texture as a sampler2D:

uniform sampler2D depth;
out vec4 fragColor;
in vec2 uv;

void main() {
    float raw_depth_nonlinear = texture(depth, uv);
    fragColor = vec4(raw_depth_nonlinear);
}

Accepted compare functions:

texture.compare_func = ''    # Disale depth comparison completely
texture.compare_func = '<='  # GL_LEQUAL
texture.compare_func = '<'   # GL_LESS
texture.compare_func = '>='  # GL_GEQUAL
texture.compare_func = '>'   # GL_GREATER
texture.compare_func = '=='  # GL_EQUAL
texture.compare_func = '!='  # GL_NOTEQUAL
texture.compare_func = '0'   # GL_NEVER
texture.compare_func = '1'   # GL_ALWAYS
Type:tuple
Texture.anisotropy

Number of samples for anisotropic filtering (Default 1.0). The value will be clamped in range 1.0 and ctx.max_anisotropy.

Any value greater than 1.0 counts as a use of anisotropic filtering:

# Disable anisotropic filtering
texture.anisotropy = 1.0

# Enable anisotropic filtering suggesting 16 samples as a maximum
texture.anisotropy = 16.0
Type:float
Texture.width

The width of the texture.

Type:int
Texture.height

The height of the texture.

Type:int
Texture.size

The size of the texture.

Type:tuple
Texture.dtype

Data type.

Type:str
Texture.components

The number of components of the texture.

Type:int
Texture.samples

The number of samples set for the texture used in multisampling.

Type:int
Texture.depth

Is the texture a depth texture?

Type:bool
Texture.glo

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

Type:int
Texture.extra

Any - Attribute for storing user defined objects

TextureArray

class moderngl.TextureArray

An Array Texture is a Texture where each mipmap level contains an array of images of the same size. Array textures may have Mipmaps, but each mipmap in the texture has the same number of levels.

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

Create

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

Create a TextureArray object.

Parameters:
  • size (tuple) – The (width, height, layers) of the texture.
  • components (int) – The number of components 1, 2, 3 or 4.
  • data (bytes) – Content of the texture. The size must be (width, height * layers) so each layer is stacked vertically.
Keyword Arguments:
 
  • alignment (int) – The byte alignment 1, 2, 4 or 8.
  • dtype (str) – Data type.
Returns:

Texture3D object

Methods

TextureArray.read(alignment=1) → bytes

Read the content of the texture array into a buffer.

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

Read the content of the texture array 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.
TextureArray.write(data, viewport=None, alignment=1)

Update the content of the texture array.

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

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

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

Generate mipmaps.

This also changes the texture filter to LINEAR_MIPMAP_LINEAR, LINEAR (Will be removed in 6.x)

Keyword Arguments:
 
  • base (int) – The base level
  • max_level (int) – The maximum levels to generate
TextureArray.use(location=0)

Bind the texture array.

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

TextureArray.repeat_x

The x repeat flag for the texture (Default True)

Example:

# Enable texture repeat (GL_REPEAT)
texture.repeat_x = True

# Disable texture repeat (GL_CLAMP_TO_EDGE)
texture.repeat_x = False
Type:bool
TextureArray.repeat_y

The y repeat flag for the texture (Default True)

Example:

# Enable texture repeat (GL_REPEAT)
texture.repeat_y = True

# Disable texture repeat (GL_CLAMP_TO_EDGE)
texture.repeat_y = False
Type:bool
TextureArray.filter

The minification and magnification filter for the texture. (Default (moderngl.LINEAR. moderngl.LINEAR))

Example:

texture.filter == (monderngl.NEAREST, moderngl.NEAREST)
texture.filter == (monderngl.LINEAR_MIPMAP_LINEAR, moderngl.LINEAR)
texture.filter == (monderngl.NEAREST_MIPMAP_LINEAR, moderngl.NEAREST)
texture.filter == (monderngl.LINEAR_MIPMAP_NEAREST, moderngl.NEAREST)
Type:tuple
TextureArray.swizzle

The swizzle mask of the texture (Default 'RGBA').

The swizzle mask change/reorder the vec4 value returned by the texture() function in a GLSL shaders. This is represented by a 4 character string were each character can be:

'R' GL_RED
'G' GL_GREEN
'B' GL_BLUE
'A' GL_ALPHA
'0' GL_ZERO
'1' GL_ONE

Example:

# Alpha channel will always return 1.0
texture.swizzle = 'RGB1'

# Only return the red component. The rest is masked to 0.0
texture.swizzle = 'R000'

# Reverse the components
texture.swizzle = 'ABGR'
Type:str
TextureArray.anisotropy

Number of samples for anisotropic filtering (Default 1.0). The value will be clamped in range 1.0 and ctx.max_anisotropy.

Any value greater than 1.0 counts as a use of anisotropic filtering:

# Disable anisotropic filtering
texture.anisotropy = 1.0

# Enable anisotropic filtering suggesting 16 samples as a maximum
texture.anisotropy = 16.0
Type:float
TextureArray.width

The width of the texture array.

Type:int
TextureArray.height

The height of the texture array.

Type:int
TextureArray.layers

The number of layers of the texture array.

Type:int
TextureArray.size

The size of the texture array.

Type:tuple
TextureArray.dtype

Data type.

Type:str
TextureArray.components

The number of components of the texture array.

Type:int
TextureArray.glo

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

Type:int
TextureArray.extra

Any - Attribute for storing user defined objects

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.

This also changes the texture filter to LINEAR_MIPMAP_LINEAR, LINEAR (Will be removed in 6.x)

Keyword Arguments:
 
  • base (int) – The base level
  • max_level (int) – The maximum levels to generate
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

The x repeat flag for the texture (Default True)

Example:

# Enable texture repeat (GL_REPEAT)
texture.repeat_x = True

# Disable texture repeat (GL_CLAMP_TO_EDGE)
texture.repeat_x = False
Type:bool
Texture3D.repeat_y

The y repeat flag for the texture (Default True)

Example:

# Enable texture repeat (GL_REPEAT)
texture.repeat_y = True

# Disable texture repeat (GL_CLAMP_TO_EDGE)
texture.repeat_y = False
Type:bool
Texture3D.repeat_z

The z repeat flag for the texture (Default True)

Example:

# Enable texture repeat (GL_REPEAT)
texture.repeat_z = True

# Disable texture repeat (GL_CLAMP_TO_EDGE)
texture.repeat_z = False
Type:bool
Texture3D.filter

The filter of the texture.

Type:tuple
Texture3D.swizzle

The swizzle mask of the texture (Default 'RGBA').

The swizzle mask change/reorder the vec4 value returned by the texture() function in a GLSL shaders. This is represented by a 4 character string were each character can be:

'R' GL_RED
'G' GL_GREEN
'B' GL_BLUE
'A' GL_ALPHA
'0' GL_ZERO
'1' GL_ONE

Example:

# Alpha channel will always return 1.0
texture.swizzle = 'RGB1'

# Only return the red component. The rest is masked to 0.0
texture.swizzle = 'R000'

# Reverse the components
texture.swizzle = 'ABGR'
Type:str
Texture3D.width

The width of the texture.

Type:int
Texture3D.height

The height of the texture.

Type:int
Texture3D.depth

The depth of the texture.

Type:int
Texture3D.size

The size of the texture.

Type:tuple
Texture3D.dtype

Data type.

Type:str
Texture3D.components

The number of components of the texture.

Type:int
Texture3D.glo

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

Type:int
Texture3D.extra

Any - Attribute for storing user defined objects

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 of the texture. Each side of the cube will have this size.
  • 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.size

The size of the texture.

Type:tuple
TextureCube.dtype

Data type.

Type:str
TextureCube.components

The number of components of the texture.

Type:int
TextureCube.filter

The minification and magnification filter for the texture. (Default (moderngl.LINEAR. moderngl.LINEAR))

Example:

texture.filter == (monderngl.NEAREST, moderngl.NEAREST)
texture.filter == (monderngl.LINEAR_MIPMAP_LINEAR, moderngl.LINEAR)
texture.filter == (monderngl.NEAREST_MIPMAP_LINEAR, moderngl.NEAREST)
texture.filter == (monderngl.LINEAR_MIPMAP_NEAREST, moderngl.NEAREST)
Type:tuple
TextureCube.swizzle

The swizzle mask of the texture (Default 'RGBA').

The swizzle mask change/reorder the vec4 value returned by the texture() function in a GLSL shaders. This is represented by a 4 character string were each character can be:

'R' GL_RED
'G' GL_GREEN
'B' GL_BLUE
'A' GL_ALPHA
'0' GL_ZERO
'1' GL_ONE

Example:

# Alpha channel will always return 1.0
texture.swizzle = 'RGB1'

# Only return the red component. The rest is masked to 0.0
texture.swizzle = 'R000'

# Reverse the components
texture.swizzle = 'ABGR'
Type:str
TextureCube.anisotropy

Number of samples for anisotropic filtering (Default 1.0). The value will be clamped in range 1.0 and ctx.max_anisotropy.

Any value greater than 1.0 counts as a use of anisotropic filtering:

# Disable anisotropic filtering
texture.anisotropy = 1.0

# Enable anisotropic filtering suggesting 16 samples as a maximum
texture.anisotropy = 16.0
Type:float
TextureCube.glo

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

Type:int
TextureCube.extra

Any - Attribute for storing user defined objects

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

The viewport of the framebuffer.

Type:tuple
Framebuffer.color_mask

The color mask of the framebuffer.

Type:tuple
Framebuffer.depth_mask

The depth mask of the framebuffer.

Type:tuple
Framebuffer.width

The width of the framebuffer.

Type:int
Framebuffer.height

The height of the framebuffer.

Type:int
Framebuffer.size

The size of the framebuffer.

Type:tuple
Framebuffer.samples

The samples of the framebuffer.

Type:int
Framebuffer.bits

The bits of the framebuffer.

Type:dict
Framebuffer.color_attachments

The color attachments of the framebuffer.

Type:tuple
Framebuffer.depth_attachment

The depth attachment of the framebuffer.

Type:Texture or Renderbuffer
Framebuffer.glo

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

Type:int
Framebuffer.extra

Any - Attribute for storing user defined objects

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

The width of the renderbuffer.

Type:int
Renderbuffer.height

The height of the renderbuffer.

Type:int
Renderbuffer.size

The size of the renderbuffer.

Type:tuple
Renderbuffer.samples

The samples of the renderbuffer.

Type:int
Renderbuffer.components

The components of the renderbuffer.

Type:int
Renderbuffer.depth

Is the renderbuffer a depth renderbuffer?

Type:bool
Renderbuffer.dtype

Data type.

Type:str
Renderbuffer.glo

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

Type:int
Renderbuffer.extra

Any - Attribute for storing user defined objects

Scope

class moderngl.Scope

This class represents a Scope object.

Responsibilities on enter:

  • Set the enable flags.
  • Bind the framebuffer.
  • Assigning textures to texture locations.
  • Assigning buffers to uniform buffers.
  • Assigning 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.

Attributes

Scope.extra

Any - Attribute for storing user defined objects

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_only=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 necessary.
# 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

The number of samples passed.

Type:int
Query.primitives

The number of primitives generated.

Type:int
Query.elapsed

The time elapsed in nanoseconds.

Type:int
Query.crender

Can be used in a with statement.

Type:ConditionalRender
Query.extra

Any - Attribute for storing user defined objects

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.
ComputeShader.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

ComputeShader.source

The source code of the compute shader.

Type:str
ComputeShader.glo

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

Type:int
ComputeShader.extra

Any - Attribute for storing user defined objects

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
51
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

Differences 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