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: Optional[moderngl.Framebuffer] = None, enable_only: Optional[int] = None, *, textures: Tuple[Tuple[moderngl.Texture, int], ...] = (), uniform_buffers: Tuple[Tuple[moderngl.Buffer, int], ...] = (), storage_buffers: Tuple[Tuple[moderngl.Buffer, int], ...] = (), samplers: Tuple[Tuple[moderngl.Sampler, int], ...] = (), enable: Optional[int] = None) moderngl.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 (tuple) – List of (texture, binding) tuples.

  • uniform_buffers (tuple) – Tuple of (buffer, binding) tuples.

  • storage_buffers (tuple) – Tuple of (buffer, binding) tuples.

  • samplers (tuple) – Tuple of sampler bindings

  • enable (int) – Flags to enable for this vao such as depth testing and blending

Methods#

Scope.__enter__()#
Scope.__exit__(*args: Tuple[Any])#
Scope.release() None#

Destroy the Scope object.

Attributes#

Scope.extra: Any#

Any - Attribute for storing user defined objects

Scope.mglo: Any#

Internal representation for debug purposes only.

Scope.ctx: moderngl.Context#

The context this object belongs to

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.