simvx.graphics.renderer.sub_viewport

SubViewport render-to-texture: offscreen targets for core.SubViewport nodes.

A :class:~simvx.core.SubViewport renders its own subtree (with its own camera) into an offscreen texture that other nodes in the main scene can sample: a “live monitor in the world”, a security-camera feed, a minimap, a render-to-texture portal, etc.

Architecture mirrors :class:~simvx.graphics.renderer.game_viewport.GameViewportRenderer (the proven editor game-preview path): each SubViewport owns a

class:

RenderTarget, registered once as a bindless texture whose slot id stays stable across resizes so consumers that captured subviewport.texture keep working. :class:SubViewportManager keys one renderer per SubViewport by id(node), creates it on first sight, debounce-resizes on size changes, and unregisters on exit-tree / teardown.

Frame ordering: all SubViewports are rendered flat, before the main scene pass, in :meth:SubViewportManager.render_all (driven from the engine pre_render callback). Each target finishes in SHADER_READ_ONLY so the main pass can sample it the same frame. A SubViewport that samples another SubViewport sees last frame’s content (one-frame lag): topological ordering is out of scope for v1.

Module Contents

Classes

SubViewportRenderer

One offscreen render target for a single SubViewport node.

SubViewportManager

Owns one :class:SubViewportRenderer per live SubViewport node.

Data

API

simvx.graphics.renderer.sub_viewport.log

‘getLogger(…)’

simvx.graphics.renderer.sub_viewport.__all__

[‘SubViewportRenderer’, ‘SubViewportManager’]

class simvx.graphics.renderer.sub_viewport.SubViewportRenderer(engine: Any)[source]

One offscreen render target for a single SubViewport node.

Wraps a :class:RenderTarget and exposes the ready / width / height / begin_pass / end_pass / render_draw2d surface that

Meth:

SceneAdapter.render_to_target expects: the same contract

Class:

GameViewportRenderer satisfies.

Initialization

create(width: int, height: int) None[source]

Create the offscreen target and register its colour view as bindless.

resize(width: int, height: int) None[source]

Recreate the target at a new size, preserving the bindless slot.

The slot id handed out as subviewport.texture stays stable; only the backing image view changes, so a Sprite2D / Material that captured the slot keeps sampling the live feed after a resize.

begin_pass(cmd: Any) None[source]

Begin the offscreen colour+depth pass (clear).

end_pass(cmd: Any) None[source]
render_draw2d(cmd: Any, ops: list) None[source]

Overlay pre-extracted Draw2D ops on top of the 3D content (LOAD_OP_LOAD).

property texture_id: int[source]
property width: int[source]
property height: int[source]
property ready: bool[source]
destroy() None[source]

Release the target, Draw2D pass, and the bindless slot.

class simvx.graphics.renderer.sub_viewport.SubViewportManager(engine: Any, adapter: Any)[source]

Owns one :class:SubViewportRenderer per live SubViewport node.

Created once per :class:App run and invoked from the engine pre_render callback via :meth:render_all. Discovers SubViewports each frame by walking the main scene tree, lazily creating a target on first sight, debounce-resizing when SubViewport.size changes, and reaping targets whose nodes have left the tree.

Initialization

render_all(tree: Any) bool[source]

Render every SubViewport in tree into its offscreen target.

Called from the engine pre_render callback, before the main scene pass. Each SubViewport renders its own subtree with its own camera.

Each SubViewport renders on its own dedicated one-time command buffer, submitted and waited on before the next viewport (and before the main frame’s command buffer). This is mandatory: the renderer keeps a single per-frame transform / material SSBO that render_to_target overwrites. If two viewports (or a viewport and the main scene) shared one command buffer (executed together at submit), the last SSBO upload would win and earlier passes would render with the wrong transforms. Fully completing each offscreen pass first leaves its target in SHADER_READ_ONLY and frees the SSBO for the next pass to reuse.

Returns True if at least one SubViewport rendered this frame: the caller must then re-submit the main scene, since render_to_target cleared the renderer’s per-frame submission lists.

A SubViewport that samples another SubViewport sees the previous frame’s content (one-frame lag); v1 does not topologically order them.

destroy() None[source]

Tear down all targets (call on app shutdown).