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,
)#

Bases: object

Container that ties render objects, camera, canvas, and input into a live WebGPU scene.

canvas: Canvas = None#
cleanup()#

Detach the scene from its canvas, unregister callbacks, and release JS proxies.

property device: Device#
get_position(x: int, y: int)#

Return the 3D position under canvas pixel (x, y) using the selection buffer.

gui: object = None#
property id: str#
init(canvas)#

Attach the scene to a canvas and initialize GPU resources and event handlers.

options: RenderOptions#
redraw(blocking=False, fps=10)#

Request a redraw, either blocking immediately or debounced on the event loop.

render(t=0, rerender_if_update_needed=True)#

Main render loop: enqueue a frame and optionally keep rendering while objects update.

render_objects: list[BaseRenderer]#
select(x: int, y: int)#

Perform an object selection at (x, y) and dispatch callbacks on matching renderers.

class webgpu.renderer.BaseRenderer(label=None)#

Bases: object

active: bool = True#
add_options_to_gui(gui)#
all_renderer()#
create_render_pipeline(
options: RenderOptions,
) None#
property device: Device#
get_bindings() list[BaseBinding]#
get_bounding_box() tuple[list[float], list[float]] | 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,
) None#
set_needs_update() None#
shader_defines: dict[str, str] = None#
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#
select(
options: RenderOptions,
x: int,
y: int,
) None#
set_needs_update() None#
update(options: RenderOptions) None#
class webgpu.renderer.RenderOptions(camera: Camera, light: Light)#

Bases: object

begin_render_pass(**kwargs)#
begin_select_pass(x, y, **kwargs)#
canvas: Canvas#
command_encoder: CommandEncoder#
property device: Device#
get_bindings()#
set_canvas(canvas: Canvas)#
timestamp: float#
update_buffers()#
viewport: tuple[int, int, int, int, float, float]#
class webgpu.renderer.Renderer(label=None)#

Bases: BaseRenderer

Base class for renderer classes

create_render_pipeline(options: RenderOptions) None#
depthBias: int = 0#
depthBiasSlopeScale: int = 0#
fragment_entry_point: str = 'fragment_main'#
n_instances: int = 1#
n_vertices: int = 0#
render(options: RenderOptions) None#
select(options: RenderOptions, x: int, y: int) None#
select_entry_point: str = 'fragment_select_default'#
topology: PrimitiveTopology = 'triangle-list'#
vertex_buffer_layouts: list[VertexBufferLayout] = []#
vertex_buffers: list[Buffer] = []#
vertex_entry_point: str = 'vertex_main'#
class webgpu.renderer.SelectEvent(x: int, y: int, data: bytes)#

Bases: object

calculate_position(camera: Camera)#
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,
lilgui=True,
) Scene#

Render objects and uniforms#

Simple shapes (cylinder, cone, circle) generation and render objects

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,
)#

Bases: Renderer

SCALE_UNIFORM = c_uint(0)#
SCALE_Z = c_uint(1)#
add_options_to_gui(gui)#
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_circle(n, radius: float = 1.0) ShapeData#
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.Binding#

Bases: object

INDICES = 92#
NORMALS = 91#
VERTICES = 90#
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: object

Binding 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.Binding#

Bases: object

CLIPPING = 1#
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

class Mode#

Bases: object

DISABLED = 0#
PLANE = 1#
SPHERE = 2#
add_options_to_gui(gui)#
enable_clipping(value)#
get_bindings()#
get_bounding_box() tuple[list[float], list[float]] | None#
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: object

Base 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.ReadBuffer(buffer, encoder)#

Bases: object

get_array(dtype)#
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,
) Buffer#
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,
) Buffer#
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.get_device() Device#
async webgpu.utils.init_device() Device#
webgpu.utils.init_device_sync()#
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.texture_from_data(width, height, data, format, label='')#

Create texture from data (bytes or numpy array)

webgpu.utils.uniform_from_array(
array,
label='',
reuse: Buffer | None = None,
) Buffer#
webgpu.utils.write_array_to_buffer(buffer: Buffer, array)#