Core framework and rendering#
The core webgpu framework provides the scene graph, renderer base
classes, and helpers used by most higher-level functionality.
Scenes and renderers#
- class webgpu.scene.Scene(
- render_objects: list[BaseRenderer],
- id: str | None = None,
- canvas: Canvas | None = None,
- camera: Camera | None = None,
- light: Light | None = None,
- use_js_engine: bool | None = None,
- show_gui_controls: bool = True,
Bases:
objectContainer that ties render objects, camera, canvas, and input into a live WebGPU scene.
- cleanup()#
Detach the scene from its canvas, unregister callbacks, and release JS proxies.
- export(path=None)#
Export scene to binary blob for JS engine.
- get_position(x: int, y: int)#
Return the 3D position under canvas pixel (x, y) using the selection buffer.
- property id: str#
- init(canvas)#
Attach the scene to a canvas and initialize GPU resources and event handlers.
- on_click_background(callback)#
- options: RenderOptions#
- reconnect(canvas)#
Re-attach a previously initialized scene to a (new) canvas.
Unlike
init(), this skips the expensive pipeline rebuild for all render objects. Use aftercleanup()when the scene data (buffers, pipelines) is still valid but the canvas changed.
- redraw(blocking=False, fps=10)#
Request a redraw, either blocking immediately or debounced on the event loop.
- render()#
Main render loop: enqueue a frame and optionally keep rendering while objects update.
- render_objects: list[BaseRenderer]#
- save_screenshot(filename: str)#
Save a screenshot of the current rendered frame to filename.
Supports both the live JS engine path and the legacy Python render path. The file format is inferred from the extension (e.g. “.png”).
- select(x: int, y: int)#
Queue an object selection at (x, y).
A single worker processes only the most recent request, so a backlog (e.g. hover moves piled up while Python was busy) collapses to the last position instead of replaying every queued move. Never runs two selects concurrently.
- webgpu.scene.set_default_use_js_engine(value: bool)#
Set the default backend for scenes: True = JS engine, False = legacy Python render/camera. Override per scene via
Scene(use_js_engine=...).
- class webgpu.renderer.BaseRenderer(label=None)#
Bases:
object- property active#
- all_renderer()#
- create_render_pipeline(
- options: RenderOptions,
- get_bindings() list[BaseBinding]#
- get_export_interactions(options, buffer_registry)#
Return Interaction entries this renderer wants to emit.
Override in renderers that need custom JS-side interactions (e.g. time-animation sliders). Default: none.
- get_shader_code() str#
- label: str = ''#
- property needs_update: bool#
- on_select(callback)#
- property on_select_set#
- render(options: RenderOptions) None#
- select(
- options: RenderOptions,
- x: int,
- y: int,
- set_needs_update() None#
- shader_defines: dict[str, str] = None#
- transparent: bool = False#
- update(options: RenderOptions) None#
- class webgpu.renderer.GPUObjects#
Bases:
object
- class webgpu.renderer.MultipleRenderer(render_objects)#
Bases:
BaseRenderer- all_renderer()#
- property needs_update: bool#
- property on_select_set#
- render(options: RenderOptions) None#
- render_opaque(options: RenderOptions) None#
- render_transparent(
- options: RenderOptions,
- select(
- options: RenderOptions,
- x: int,
- y: int,
- set_needs_update() None#
- property transparent#
bool(x) -> bool
Returns True when the argument x is true, False otherwise. The builtins True and False are the only two instances of the class bool. The class bool is a subclass of the class int, and cannot be subclassed.
- update(options: RenderOptions) None#
- class webgpu.renderer.RenderOptions(camera: Camera, light: Light)#
Bases:
object- add_bindings(provider)#
Register an object with a get_bindings() method (e.g. a UniformBase).
- begin_render_pass(**kwargs)#
- begin_select_pass(x, y, **kwargs)#
- command_encoder: CommandEncoder#
- get_bindings()#
- model_view_proj: object#
- render_pass: object = None#
- render_pass_scope()#
Yield the render pass a renderer should record into.
When the Scene has opened a shared frame pass (
self.render_passis set), reuse it and do NOT end it here — the Scene ends it once, after all objects have been recorded, so the MSAA target is resolved a single time per frame. When no shared pass is active (e.g. a renderer rendered in isolation), open and close a private pass for backwards behaviour.
- update_buffers()#
- class webgpu.renderer.Renderer(label=None)#
Bases:
BaseRendererBase class for renderer classes
- create_render_pipeline(options: RenderOptions) None#
- depthBias: int = 0#
- depthBiasSlopeScale: int = 0#
- fragment_entry_point: str = 'fragment_main'#
- get_export_compute_passes(options, buffer_registry)#
Override in renderers that use compute shaders.
- get_export_descriptor(options, buffer_registry)#
Generic export: works for any Renderer subclass after update().
- n_instances: int = 1#
- n_vertices: int = 0#
- render(options: RenderOptions) None#
- render_opaque(options: RenderOptions) None#
- render_transparent(options: RenderOptions) None#
- select(options: RenderOptions, x: int, y: int) None#
- select_entry_point: str = 'fragment_select_default'#
- topology: PrimitiveTopology = 'triangle-list'#
- transparent: bool = False#
- vertex_entry_point: str = 'vertex_main'#
- class webgpu.renderer.SelectEvent(x: int, y: int, data: bytes)#
Bases:
object- calculate_position(options)#
- data: bytes#
- property float32#
- property obj_id#
- property uint32#
- x: int#
- y: int#
- webgpu.renderer.check_timestamp(callback: Callable)#
Decorator to handle updates for render objects. The function is only called if the timestamp has changed.
- webgpu.draw.Draw(
- scene: Scene | BaseRenderer | list[BaseRenderer],
- canvas: Canvas,
Render objects and uniforms#
Simple shapes (cylinder, cone, circle) generation and render objects
- class webgpu.shapes.ShapeComplexUniform(**kwargs)#
Bases:
UniformBase- color_override#
Structure/Union member
- is_complex#
Structure/Union member
- padding#
Structure/Union member
- phase#
Structure/Union member
- class webgpu.shapes.ShapeData(
- vertices: numpy.ndarray,
- normals: numpy.ndarray,
- triangles: numpy.ndarray,
- _buffers: dict = <factory>,
Bases:
object- create_buffers()#
- get_bounding_box()#
- move(v)#
- normalize_z()#
- normals: ndarray#
- triangles: ndarray#
- vertices: ndarray#
- class webgpu.shapes.ShapeRenderer(
- shape_data: ShapeData,
- positions: ndarray | None = None,
- directions: ndarray | None = None,
- values: ndarray | None = None,
- colors: ndarray | None = None,
- label=None,
- colormap=None,
- clipping=None,
Bases:
Renderer- SCALE_UNIFORM = c_uint(0)#
- SCALE_Z = c_uint(1)#
- property colors#
- property directions#
- get_bindings()#
- get_bounding_box()#
- get_shader_code() str#
- property positions#
- render(options: RenderOptions) None#
- property scale#
- property scale_mode#
- select(options: RenderOptions, x, y) None#
- select_entry_point: str = 'shape_fragment_main_select'#
- update(options: RenderOptions)#
- property values#
- vertex_entry_point: str = 'shape_vertex_main'#
- class webgpu.shapes.ShapeUniforms(**kwargs)#
Bases:
UniformBase- padding#
Structure/Union member
- scale#
Structure/Union member
- scale_mode#
Structure/Union member
- webgpu.shapes.generate_cone(n, radius=1.0, height=1.0, bottom_face=False)#
- webgpu.shapes.generate_cylinder(
- n: int,
- radius: float = 1.0,
- height: float = 1.0,
- top_face=False,
- bottom_face=False,
- radius_top=None,
- class webgpu.triangles.TriangulationRenderer(
- points,
- normals=None,
- color=(0.0, 1.0, 0.0, 1.0),
- label='Triangulation',
Bases:
Renderer- get_bindings() list[BufferBinding]#
- get_bounding_box()#
- get_color_shader()#
- get_shader_code() str#
- n_vertices: int = 3#
- update(options: RenderOptions)#
Python equivalents to all uniforms defined in shader code
The UniformBase class are derived from ctypes.Structure to ensure correct memory layout.
CAUTION: - The Binding numbers must match the numbers defined in the shader code. - Uniforms structs must match exactly the memory layout defined in the shader code. - The size of each struct must be a multiple of 16 bytes.
- class webgpu.uniforms.Binding#
Bases:
objectBinding numbers for uniforms in shader code in uniforms.wgsl
- CAMERA = 0#
- CLIPPING = 1#
- COLORBAR = 9#
- COLORMAP = 5#
- COLORMAP_SAMPLER = 7#
- COLORMAP_TEXTURE = 6#
- EDGE = 21#
- FONT = 2#
- FONT_SAMPLER = 4#
- FONT_TEXTURE = 3#
- GBUFFERLAM = 14#
- HEX = 28#
- LIGHT = 8#
- LINE_INTEGRAL_CONVOLUTION = 40#
- LINE_INTEGRAL_CONVOLUTION_INPUT_TEXTURE = 41#
- LINE_INTEGRAL_CONVOLUTION_OUTPUT_TEXTURE = 42#
- MESH = 20#
- PRISM = 27#
- PYRAMID = 26#
- QUAD = 24#
- SEG = 22#
- SEG_FUNCTION_VALUES = 11#
- TET = 25#
- TEXT = 30#
- TRIG = 23#
- TRIGS_INDEX = 13#
- TRIG_FUNCTION_VALUES = 10#
- VERTICES = 12#
- class webgpu.uniforms.LineIntegralConvolutionUniforms(
- kernel_length=25,
- oriented=0,
- thickness=5,
- **kwargs,
Bases:
UniformBase- height#
Structure/Union member
- kernel_length#
Structure/Union member
- oriented#
Structure/Union member
- padding#
Structure/Union member
- thickness#
Structure/Union member
- width#
Structure/Union member
- class webgpu.uniforms.MeshUniforms(subdivision=1, shrink=1.0, **kwargs)#
Bases:
UniformBase- padding#
Structure/Union member
- shrink#
Structure/Union member
- subdivision#
Structure/Union member
- class webgpu.uniforms.UniformBase(**kwargs)#
Bases:
Structure- get_bindings() list[BaseBinding]#
- update_buffer()#
- class webgpu.clipping.Clipping(
- mode=0,
- center=[0.0, 0.0, 0.0],
- normal=[0.0, -1.0, 0.0],
- radius=1.0,
- offset=0.0,
Bases:
BaseRenderer- enable_clipping(value)#
- get_bindings()#
- get_shader_code()#
- render(options: RenderOptions)#
- set_nx_value(value)#
- set_ny_value(value)#
- set_nz_value(value)#
- set_offset(value)#
- set_x_value(value)#
- set_y_value(value)#
- set_z_value(value)#
- update(options: RenderOptions)#
- update_buffer()#
- class webgpu.clipping.ClippingUniforms(mode=0, **kwargs)#
Bases:
UniformBase- mode#
Structure/Union member
- padding#
Structure/Union member
- plane#
Structure/Union member
- sphere#
Structure/Union member
- class webgpu.utils.BaseBinding(nr, visibility=<ShaderStage.ALL: 7>, resource=None, layout=None)#
Bases:
objectBase class for any object that has a binding number (uniform, storage buffer, texture etc.)
- property binding#
- property layout#
- class webgpu.utils.BufferBinding(nr, buffer, read_only=True, visibility=<ShaderStage.ALL: 7>)#
Bases:
BaseBinding
- class webgpu.utils.Lock(do: bool = True)#
Bases:
object
- class webgpu.utils.Pyodide#
Bases:
object
- class webgpu.utils.SamplerBinding(nr, sampler, visibility=<ShaderStage.FRAGMENT: 2>)#
Bases:
BaseBinding
- class webgpu.utils.StorageTextureBinding(
- nr,
- texture,
- visibility=<ShaderStage.COMPUTE: 4>,
- dim=2,
- access='write-only',
Bases:
BaseBinding
- class webgpu.utils.TextureBinding(
- nr,
- texture,
- visibility=<ShaderStage.FRAGMENT: 2>,
- sample_type='float',
- dim=1,
- multisamples=False,
Bases:
BaseBinding
- class webgpu.utils.TimeQuery(device)#
Bases:
object
- class webgpu.utils.UniformBinding(nr, buffer, visibility=<ShaderStage.ALL: 7>)#
Bases:
BaseBinding
- webgpu.utils.buffer_from_array(
- data,
- usage=<BufferUsage.STORAGE: 128>,
- label='from_array',
- reuse: Buffer | None = None,
- use_cache: bool = True,
- webgpu.utils.create_bind_group(device, bindings: list, label='')#
creates bind group layout and bind group from a list of BaseBinding objects
- webgpu.utils.create_buffer(
- size,
- usage=<BufferUsage.COPY_DST|STORAGE: 136>,
- label='buffer',
- reuse: Buffer | None = None,
- webgpu.utils.decode_bytes(data: str) bytes#
- webgpu.utils.encode_bytes(data: bytes) str#
- webgpu.utils.find_shader_file(file_path) Path#
- webgpu.utils.format_number(n, format=None)#
- webgpu.utils.init_device_sync()#
- webgpu.utils.mark_buffer_dirty(buffer)#
Record a host-written GPU buffer so its dependent compute passes re-run.
- webgpu.utils.max_bounding_box(boxes)#
- webgpu.utils.preprocess_shader_code(code: str, defines: dict[str, str] | None = None) str#
- webgpu.utils.read_buffer(buffer, dtype=None, offset=0, size=0)#
Reads a buffer and returns it as a numpy array. If dtype is not specified, return bytes object
- webgpu.utils.read_shader_file(file_name) str#
- webgpu.utils.read_texture(texture, bytes_per_pixel=4, dtype=None)#
- webgpu.utils.register_shader_directory(name, path)#
- webgpu.utils.reload_package(package_name)#
Reload python package and all submodules (searches in modules for references to other submodules)
- webgpu.utils.run_compute_shader(
- code,
- bindings,
- n_workgroups: list | int,
- label='compute',
- entry_point='main',
- encoder=None,
- defines: dict[str, str] | None = None,
- webgpu.utils.take_dirty_buffers()#
Return and clear the buffers host-written since the last call.
- webgpu.utils.texture_from_data(width, height, data, format, label='')#
Create texture from data (bytes or numpy array)