Note
Go to the end to download the full example code
Volume and Volume Slice RenderingΒΆ
Render a volume and volume slices. You should see:
On the left: a raycasted volume fit snugly inside a red box.
On the right: three orthogonal slices inside - and through the middle of - a green box.
The volume has its corners darker and its very center is brighter.
import numpy as np
from wgpu.gui.auto import WgpuCanvas, run
import pygfx as gfx
canvas = WgpuCanvas()
renderer = gfx.renderers.WgpuRenderer(canvas)
# Prepare a very small data volume. The data is integer and not uint8,
# so its not interpolated (a wgpu restriction). In this case this is intended.
voldata = np.ones((3, 3, 3), np.int16) * 200
voldata[1:-1, :, :] = 600
voldata[:, 1:-1, :] = 600
voldata[:, :, 1:-1] = 600
voldata[1, 1, 1] = 800
# Create a texture, (wrapped in a geometry) for it
geo = gfx.Geometry(grid=gfx.Texture(voldata, dim=3))
# Prepare two 3x3x3 boxes to indicate the proper position
box1 = gfx.Mesh(
gfx.box_geometry(3.1, 3.1, 3.1),
gfx.MeshBasicMaterial(color=(1, 0, 0, 1), wireframe=True, wireframe_thickness=1),
)
box2 = gfx.Mesh(
gfx.box_geometry(3.1, 3.1, 3.1),
gfx.MeshBasicMaterial(color=(0, 1, 0, 1), wireframe=True, wireframe_thickness=1),
)
# In scene1 we show a raycasted volume
scene1 = gfx.Scene()
vol = gfx.Volume(geo, gfx.VolumeRayMaterial(clim=(0, 2000)))
vol.local.position = (-1, -1, -1)
scene1.add(vol, box1)
# In scene2 we show volume slices
scene2 = gfx.Scene()
slice1 = gfx.Volume(geo, gfx.VolumeSliceMaterial(clim=(0, 1000), plane=(0, 0, 1, 0)))
slice2 = gfx.Volume(geo, gfx.VolumeSliceMaterial(clim=(0, 1000), plane=(0, 1, 0, 0)))
slice3 = gfx.Volume(geo, gfx.VolumeSliceMaterial(clim=(0, 1000), plane=(1, 0, 0, 0)))
for slice in (slice1, slice2, slice3):
slice.local.position = (-1, -1, -1)
scene2.add(slice1, slice2, slice3, box2)
# Prepare a camera so we can see the result in 3D
camera = gfx.PerspectiveCamera(90, 16 / 9, depth_range=(0.1, 2000))
camera.local.position = (3, 3, 1)
camera.look_at((0, 1, 0))
def animate():
w, h = canvas.get_logical_size()
renderer.render(
scene1, camera, rect=(0.0 * w, 0.0 * h, 0.5 * w, 1.0 * h), flush=False
)
renderer.render(
scene2, camera, rect=(0.5 * w, 0.0 * h, 0.5 * w, 1.0 * h), flush=False
)
renderer.flush()
canvas.request_draw(animate)
if __name__ == "__main__":
run()
Total running time of the script: (0 minutes 0.790 seconds)