class Texture#

Returned by Context.texture() and Context.depth_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.


Texture.read(alignment: int = 1) bytes#

Read the pixel data as bytes into system memory.


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

Texture.read_into(buffer: Any, alignment: int = 1, write_offset: int = 0)#

Read the content of the texture into a bytearray or Buffer.

The advantage of reading into a Buffer is that pixel data does not need to travel all the way to system memory:

# Reading pixel data into a bytearray
data = bytearray(8)
texture = ctx.texture3d((2, 2, 2), 1)

# Reading pixel data into a buffer
data = ctx.buffer(reserve=8)
texture = ctx.texture3d((2, 2, 2), 1)
  • buffer (bytearray) – The buffer that will receive the pixels.

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

  • write_offset (int) – The write offset.

Texture.write(data: Any, viewport: tuple, alignment: int = 1)#

Update the content of the texture from byte data or a moderngl Buffer.


# Write data from a moderngl Buffer
data = ctx.buffer(reserve=8)
texture = ctx.texture3d((2, 2, 2), 1)

# Write data from bytes
data = b'\xff\xff\xff\xff\xff\xff\xff\xff'
texture = ctx.texture3d((2, 2), 1)
  • data (bytes) – The pixel data.

  • viewport (tuple) – The viewport.

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

Texture.build_mipmaps(base: int = 0, max_level: int = 1000) None#

Generate mipmaps.

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

  • base (int) – The base level

  • max_level (int) – The maximum levels to generate

Texture.bind_to_image(unit: int, read: bool = True, write: bool = True, level: int = 0, format: int = 0) None#

Bind a texture to an image unit (OpenGL 4.2 required).

This is used to bind textures to image units for shaders. The idea with image load/store is that the user can bind one of the images in a Texture to a number of image binding points (which are separate from texture image units). Shaders can read information from these images and write information to them, in ways that they cannot with textures.

It’s important to specify the right access type for the image. This can be set with the read and write arguments. Allowed combinations are:

  • Read-only: read=True and write=False

  • Write-only: read=False and write=True

  • Read-write: read=True and write=True

format specifies the format that is to be used when performing formatted stores into the image from shaders. format must be compatible with the texture’s internal format. By default the format of the texture is passed in. The format parameter is only needed when overriding this behavior.

Note that we bind the 3D textured layered making the entire texture readable and writable. It is possible to bind a specific 2D section in the future.

More information:

  • unit (int) – Specifies the index of the image unit to which to bind the texture

  • texture (Texture) – The texture to bind

  • read (bool) – Allows the shader to read the image (default: True)

  • write (bool) – Allows the shader to write to the image (default: True)

  • level (int) – Level of the texture to bind (default: 0).

  • format (int) – (optional) The OpenGL enum value representing the format (defaults to the texture’s format)

Texture.use(location: int = 0) None#

Better to use Sampler objects and avoid this call on the Texture object directly.

Bind the texture to a texture unit.


location (int) – The texture location/unit.

The location is the texture unit we want to bind the texture. This should correspond with the value of the sampler2D uniform in the shader because samplers read from the texture unit we assign to them:

# Define what texture unit our two sampler3D uniforms should represent
program['texture_a'] = 0
program['texture_b'] = 1
# Bind textures to the texture units
Texture.get_handle(resident: bool = True) int#

Handle for Bindless Textures.


resident (bool) – Make the texture resident.

Once a handle is created its parameters cannot be changed. Attempting to do so will have no effect. (filter, wrap etc). There is no way to undo this immutability.

Handles cannot be used by shaders until they are resident. This method can be called multiple times to move a texture in and out of residency:

>> texture.get_handle(resident=False)
>> texture.get_handle(resident=True)

Ths same handle is returned if the handle already exists.


Limitations from the OpenGL wiki

The amount of storage available for resident images/textures may be less than the total storage for textures that is available. As such, you should attempt to minimize the time a texture spends being resident. Do not attempt to take steps like making textures resident/unresident every frame or something. But if you are finished using a texture for some time, make it unresident.



Texture.width: int#

The width of the texture.

Texture.height: int#

The height of the texture.

Texture.size: Tuple[int, int]#

The size of the texture.

Texture.components: int#

The number of components of the texture.

Texture.samples: int#

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

Texture.depth: bool#

Determines if the texture contains depth values.

Texture.dtype: str#

Data type.

Texture.swizzle: str#

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:

'1' GL_ONE


# 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'

See Sampler.repeat_x


See Sampler.repeat_y


See Sampler.filter


See Sampler.compare_func


See Sampler.anisotropy

Texture.ctx: Context#

The context this object belongs to

Texture.glo: int#

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

Texture.extra: Any#

User defined data.