def show(object: WorldObject, up=None): """Visualize a given WorldObject in a new window with an interactive camera. Parameters: object (WorldObject): The object to show. up (Vector3): Optional. Configure the up vector for the camera controls. """ from wgpu.gui.auto import WgpuCanvas, run if isinstance(object, Scene): scene = object else: scene = Scene() scene.add(object) background = Background(None, BackgroundMaterial((0, 1, 0, 1), (0, 1, 1, 1))) scene.add(background) camera = PerspectiveCamera(70, 16 / 9) look_at = camera.show_object(object) canvas = WgpuCanvas() renderer = WgpuRenderer(canvas) controls = OrbitControls(camera.position.clone(), look_at, up=up) controls.add_default_event_handlers(canvas, camera) def animate(): controls.update_camera(camera) renderer.render(scene, camera) canvas.request_draw(animate) run()
""" Example showing off the mesh slice material. """ from wgpu.gui.auto import WgpuCanvas, run import pygfx as gfx canvas = WgpuCanvas() renderer = gfx.renderers.WgpuRenderer(canvas) scene = gfx.Scene() geometry = gfx.torus_knot_geometry(1, 0.3, 128, 16) material1 = gfx.MeshPhongMaterial(color=(0.5, 0.5, 0.5, 1.0)) material2 = gfx.MeshSliceMaterial(thickness=8, color=(1, 1, 0, 1), plane=(0, 0, 1, 0)) obj1 = gfx.Mesh(geometry, material1) obj2 = gfx.Mesh(geometry, material2) scene.add(obj1) scene.add(obj2) camera = gfx.PerspectiveCamera(70, 2) camera.position.z = 4 def animate(): dist = material2.plane[3] dist += 0.02 if dist > 1: dist = -1.5
}, "bindings1": { 0: Binding("r_sampler", "sampler/filtering", wobject.texture.get_view()), 1: Binding("r_tex", "texture/auto", wobject.texture.get_view()), }, }, ] # %% The application # The canvas for eventual display canvas = WgpuCanvas(size=(640, 480)) # The texture to render the scene into texture = gfx.Texture(dim=2, size=(640, 480, 1), format="rgba8unorm") # The regular scene renderer1 = gfx.renderers.WgpuRenderer(texture) scene = gfx.Scene() im = imageio.imread("imageio:astronaut.png").astype(np.float32) / 255 tex = gfx.Texture(im, dim=2).get_view(filter="linear", address_mode="repeat") geometry = gfx.box_geometry(200, 200, 200) material = gfx.MeshBasicMaterial(map=tex) cube = gfx.Mesh(geometry, material)
""" Example showing transparency using three overlapping planes. Press space to toggle the order of the planes. Press 1-6 to select the blend mode. """ from wgpu.gui.auto import WgpuCanvas, run import pygfx as gfx canvas = WgpuCanvas() renderer = gfx.renderers.WgpuRenderer(canvas) scene = gfx.Scene() geometry = gfx.plane_geometry(50, 50) plane1 = gfx.Mesh(geometry, gfx.MeshBasicMaterial(color=(1, 0, 0, 0.4))) plane2 = gfx.Mesh(geometry, gfx.MeshBasicMaterial(color=(0, 1, 0, 0.4))) plane3 = gfx.Mesh(geometry, gfx.MeshBasicMaterial(color=(0, 0, 1, 0.4))) plane1.position.set(-10, -10, 1) plane2.position.set(0, 0, 2) plane3.position.set(10, 10, 3) scene.add(plane1, plane2, plane3) camera = gfx.OrthographicCamera(100, 100) @canvas.add_event_handler("key_down") def handle_event(event): if event["key"] == " ": print("Rotating scene element order")
""" Example demonstrating different colormap dimensions on a mesh. """ import numpy as np import imageio from wgpu.gui.auto import WgpuCanvas, run import pygfx as gfx canvas = WgpuCanvas(size=(900, 400)) renderer = gfx.renderers.WgpuRenderer(canvas) scene = gfx.Scene() def get_geometry(): return gfx.cylinder_geometry(height=2, radial_segments=32, open_ended=True) def create_object(texcoords, tex, xpos): geometry = get_geometry() geometry.texcoords = gfx.Buffer(texcoords) material = gfx.MeshPhongMaterial(map=tex, clim=(-0.05, 1)) obj = gfx.Mesh(geometry, material) obj.position.x = xpos scene.add(obj) geometry = get_geometry() camera = gfx.OrthographicCamera(16, 3)
""" Example showing a 3D scene with a 2D overlay. The idea is to render both scenes, but clear the depth before rendering the overlay, so that it's always on top. """ import numpy as np from wgpu.gui.auto import WgpuCanvas, run import pygfx as gfx # Create a canvas and renderer canvas = WgpuCanvas(size=(500, 300)) renderer = gfx.renderers.WgpuRenderer(canvas) # Compose a 3D scene scene1 = gfx.Scene() geometry1 = gfx.box_geometry(200, 200, 200) material1 = gfx.MeshPhongMaterial(color=(1, 1, 0, 1.0)) cube1 = gfx.Mesh(geometry1, material1) scene1.add(cube1) camera1 = gfx.OrthographicCamera(300, 300) # Compose another scene, a 2D overlay scene2 = gfx.Scene()
scene1.add(background1) im = imageio.imread("imageio:bricks.jpg").astype(np.float32) / 255 tex = gfx.Texture(im, dim=2).get_view(filter="linear", address_mode="repeat") geometry1 = gfx.box_geometry(200, 200, 200) material1 = gfx.MeshPhongMaterial(map=tex, color=(1, 1, 0, 1.0)) cube1 = gfx.Mesh(geometry1, material1) scene1.add(cube1) camera1 = gfx.PerspectiveCamera(70, 16 / 9) camera1.position.z = 300 # Then create the actual scene, in the visible canvas canvas2 = WgpuCanvas() renderer2 = gfx.renderers.WgpuRenderer(canvas2) scene2 = gfx.Scene() geometry2 = gfx.box_geometry(200, 200, 200) material2 = gfx.MeshPhongMaterial(map=texture1.get_view(filter="linear")) cube2 = gfx.Mesh(geometry2, material2) scene2.add(cube2) camera2 = gfx.PerspectiveCamera(70, 16 / 9) camera2.position.z = 400 def animate(): rot = gfx.linalg.Quaternion().set_from_euler(gfx.linalg.Euler(0.005, 0.01))
""" Example demonstrating rendering the same scene into two different canvases. """ import numpy as np from wgpu.gui.auto import WgpuCanvas, run import pygfx as gfx # Create two canvases and two renderers canvas_a = WgpuCanvas(size=(500, 300)) canvas_b = WgpuCanvas(size=(300, 500)) renderer_b = gfx.renderers.WgpuRenderer(canvas_b) renderer_a = gfx.renderers.WgpuRenderer(canvas_a) # Compose a 3D scene with 2 objects scene = gfx.Scene() geometry1 = gfx.box_geometry(200, 200, 200) material1 = gfx.MeshPhongMaterial(color=(1, 1, 0, 1.0)) cube = gfx.Mesh(geometry1, material1) scene.add(cube) positions = np.array( [[-1, -1, 0], [-1, +1, 0], [+1, +1, 0], [+1, -1, 0], [-1, -1, 0], [+1, +1, 0]], np.float32, ) geometry2 = gfx.Geometry(positions=positions * 250)
""" Use a plane geometry to show a texture, which is continuously updated to show video. """ import imageio from wgpu.gui.auto import WgpuCanvas, run import pygfx as gfx canvas = WgpuCanvas() renderer = gfx.renderers.WgpuRenderer(canvas) scene = gfx.Scene() reader = imageio.get_reader("imageio:cockatoo.mp4") im = reader.get_next_data()[:, :, 1] tex = gfx.Texture(im, dim=2) geometry = gfx.plane_geometry(200, 200, 12, 12) material = gfx.MeshBasicMaterial(map=tex.get_view(filter="linear")) plane = gfx.Mesh(geometry, material) scene.add(plane) camera = gfx.PerspectiveCamera(70) camera.position.z = 200 def animate(): # Read next frame, rewind if we reach the end try: tex.data[:] = reader.get_next_data()[:, :, 1] except IndexError:
""" Display a lot of line objects. Because of the architecture of wgpu, this is still performant. """ import time # noqa import numpy as np from wgpu.gui.auto import WgpuCanvas, run import pygfx as gfx canvas = WgpuCanvas(max_fps=999) renderer = gfx.WgpuRenderer(canvas, show_fps=True) scene = gfx.Scene() # Define number of vertices cols = 20 rows = 50 nvertices = 30000 use_thin_lines = True print(nvertices * rows * cols, "vertices in total") x = np.linspace(0.05, 0.95, nvertices, dtype=np.float32) for row in range(rows): for col in range(cols): y = np.sin(x * 25) * 0.45 + np.random.normal(0, 0.02, len(x)).astype(np.float32) positions = np.column_stack([x, y, np.zeros_like(x)])