def _on_button_click(self): positions = [[random.uniform(-50, 50), random.uniform(-50, 50), 0] for i in range(8)] line = gfx.Line(gfx.Geometry(positions=positions), gfx.LineMaterial(thickness=3)) self._scene.add(line) self._canvas.update()
import imageio import numpy as np from wgpu.gui.auto import WgpuCanvas, run import pygfx as gfx canvas = WgpuCanvas() renderer = gfx.renderers.WgpuRenderer(canvas) scene = gfx.Scene() voldata = imageio.volread("imageio:stent.npz").astype(np.float32) tex = gfx.Texture(voldata, dim=3) vol = gfx.Volume(gfx.Geometry(grid=tex), gfx.VolumeRayMaterial(clim=(0, 2000))) slice = gfx.Volume( gfx.Geometry(grid=tex), gfx.VolumeSliceMaterial(clim=(0, 2000), plane=(0, 0, 1, 0)) ) scene.add(vol, slice) for ob in (slice, vol): ob.position.set(*(-0.5 * i for i in voldata.shape[::-1])) camera = gfx.PerspectiveCamera(70, 16 / 9) camera.position.z = 500 controls = gfx.OrbitControls(camera.position.clone(), up=gfx.linalg.Vector3(0, 0, 1)) controls.rotate(-0.5, -0.5) @canvas.add_event_handler("pointer_down", "pointer_up", "pointer_move", "wheel")
# Compose another scene, a 2D overlay scene2 = gfx.Scene() positions = np.array( [ [-1, -1, 0.5], [-1, +1, 0.5], [+1, +1, 0.5], [+1, -1, 0.5], [-1, -1, 0.5], [+1, +1, 0.5], ], np.float32, ) geometry2 = gfx.Geometry(positions=positions * 0.9) material2 = gfx.LineMaterial(thickness=5.0, color=(0.8, 0.0, 0.2, 1.0)) line2 = gfx.Line(geometry2, material2) scene2.add(line2) camera2 = gfx.NDCCamera() def animate(): rot = gfx.linalg.Quaternion().set_from_euler(gfx.linalg.Euler(0.005, 0.01)) cube1.rotation.multiply(rot) renderer.render(scene1, camera1, flush=False) renderer.render(scene2, camera2) canvas.request_draw()
""" Render three volumes using different world transforms. """ import imageio import numpy as np from wgpu.gui.auto import WgpuCanvas, run import pygfx as gfx canvas = WgpuCanvas() renderer = gfx.renderers.WgpuRenderer(canvas) scene = gfx.Scene() voldata = imageio.volread("imageio:stent.npz").astype(np.float32) geometry = gfx.Geometry(grid=voldata) material = gfx.VolumeRayMaterial(clim=(0, 2000)) vol1 = gfx.Volume(geometry, material) vol2 = gfx.Volume(geometry, material) vol3 = gfx.Volume(geometry, material) scene.add(vol1, vol2, vol3) vol2.position.x = -150 vol2.scale.z = 0.5 vol3.position.x = 150 camera = gfx.PerspectiveCamera(70, 16 / 9) camera.position.y = 500 controls = gfx.OrbitControls(camera.position.clone(),
# 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) material2 = gfx.LineMaterial(thickness=5.0, color=(0.8, 0.0, 0.2, 1.0)) line = gfx.Line(geometry2, material2) scene.add(line) camera = gfx.PerspectiveCamera(70, 16 / 9) camera.position.z = 400 # Define animation functions. Each renders the scene into its own canvas. def animate_a(): rot = gfx.linalg.Quaternion().set_from_euler(gfx.linalg.Euler(0.005, 0.01)) cube.rotation.multiply(rot) renderer_a.render(scene, camera) canvas_a.request_draw()
Example showing picking points. When clicking on a point, it's location is changed. With a small change, a line is shown instead. """ import numpy as np from wgpu.gui.auto import WgpuCanvas, run import pygfx as gfx canvas = WgpuCanvas() renderer = gfx.renderers.WgpuRenderer(canvas) scene = gfx.Scene() xx = np.linspace(-50, 50, 10) yy = np.random.uniform(20, 50, 10) geometry = gfx.Geometry(positions=[(x, y, 0) for x, y in zip(xx, yy)]) if True: # Set to False to try this for a line ob = gfx.Points(geometry, gfx.PointsMaterial(color=(0, 1, 1, 1), size=20)) else: ob = gfx.Line(geometry, gfx.LineMaterial(color=(0, 1, 1, 1), thickness=12)) scene.add(ob) camera = gfx.OrthographicCamera(120, 120) @canvas.add_event_handler("pointer_down") def handle_event(event): info = renderer.get_pick_info((event["x"], event["y"])) wobject = info["world_object"] # If a point was clicked .. if wobject and "vertex_index" in info:
renderer = gfx.WgpuRenderer(canvas) # A straight line line1 = [[100, 100], [100, 200], [100, 200], [100, 400]] # A line with a 180 degree turn (a bit of a special case for the implementation) line2 = [[200, 100], [200, 400], [200, 100]] # A swiggly line line3 = [[300 + random.randint(-10, 10), 100 + i * 3] for i in range(100)] # A line with other turns line4 = [[400, 100], [500, 200], [400, 300], [450, 400]] scene = gfx.Scene() material = gfx.LineMaterial(thickness=80.0, color=(0.8, 0.7, 0.0, 1.0)) for line in [line1, line2, line3, line4]: line = [pos + [0] for pos in line] # Make the positions vec3 geometry = gfx.Geometry(positions=line) line = gfx.Line(geometry, material) scene.add(line) camera = gfx.ScreenCoordsCamera() if __name__ == "__main__": canvas.request_draw(lambda: renderer.render(scene, camera)) run()
import numpy as np from wgpu.gui.auto import WgpuCanvas, run import pygfx as gfx canvas = WgpuCanvas() renderer = gfx.WgpuRenderer(canvas) scene = gfx.Scene() positions = np.random.normal(0, 0.5, (100, 3)).astype(np.float32) sizes = np.random.rand(100).astype(np.float32) * 50 colors = np.random.rand(100, 4).astype(np.float32) geometry = gfx.Geometry(positions=positions, sizes=sizes, colors=colors) material = gfx.PointsMaterial(vertex_colors=True, vertex_sizes=True) points = gfx.Points(geometry, material) scene.add(points) scene.add( gfx.Background(None, gfx.BackgroundMaterial((0.2, 0.0, 0, 1), (0, 0.0, 0.2, 1))) ) camera = gfx.NDCCamera() if __name__ == "__main__": canvas.request_draw(lambda: renderer.render(scene, camera)) run()
canvas = WgpuCanvas() renderer = gfx.renderers.WgpuRenderer(canvas) scene = gfx.Scene() im = np.array( [ [0, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 2], ], np.float32, ) image = gfx.Image( gfx.Geometry(grid=gfx.Texture(im, dim=2).get_view(filter="nearest")), gfx.ImageBasicMaterial(clim=(0, 2)), ) scene.add(image) points = gfx.Points( gfx.Geometry(positions=[[0, 0, 1], [3, 3, 1]]), gfx.PointsMaterial(color=(0, 1, 0, 1), size=20), ) scene.add(points) camera = gfx.OrthographicCamera(10, 10) if __name__ == "__main__": print(__doc__) canvas.request_draw(lambda: renderer.render(scene, camera))
""" import imageio from wgpu.gui.auto import WgpuCanvas, run import pygfx as gfx canvas = WgpuCanvas() renderer = gfx.renderers.WgpuRenderer(canvas) scene = gfx.Scene() # %% add image im = imageio.imread("imageio:astronaut.png") image = gfx.Image( gfx.Geometry(grid=gfx.Texture(im, dim=2)), gfx.ImageBasicMaterial(clim=(0, 255)), ) scene.add(image) # %% add points xx = [182, 180, 161, 153, 191, 237, 293, 300, 272, 267, 254] yy = [145, 131, 112, 59, 29, 14, 48, 91, 136, 137, 172] points = gfx.Points( gfx.Geometry(positions=[(x, y, 0) for x, y in zip(xx, yy)]), gfx.PointsMaterial(color=(0, 1, 1, 1), size=10), ) points.position.z = 1 # move points in front of the image scene.add(points)
scene = gfx.Scene() positions = [[200 + np.sin(i) * i * 6, 200 + np.cos(i) * i * 6, 0] for i in range(20)] positions += [[400 - np.sin(i) * i * 6, 200 + np.cos(i) * i * 6, 0] for i in range(20)] positions += [ [450, 400, 0], [375, 400, 0], [300, 400, 0], [400, 370, 0], [300, 340, 0], ] # Spiral away in z (to make the depth buffer less boring) for i in range(len(positions)): positions[i][2] = i line = gfx.Line( gfx.Geometry(positions=positions), gfx.LineMaterial(thickness=12.0, color=(0.8, 0.7, 0.0)), ) scene.add(line) camera = gfx.OrthographicCamera(600, 500) camera.position.set(300, 250, 0) if __name__ == "__main__": renderer_svg.render(scene, camera) canvas.request_draw(lambda: renderer.render(scene, camera)) run()
[0, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 2], ], np.float32, ) tex = gfx.Texture(im, dim=2) plane = gfx.Mesh( gfx.plane_geometry(4, 4), gfx.MeshBasicMaterial(map=tex.get_view(filter="nearest"), clim=(0, 2)), ) plane.position = gfx.linalg.Vector3(2, 2) # put corner at 0, 0 scene.add(plane) points = gfx.Points( gfx.Geometry(positions=[[0, 0, 1], [4, 4, 1]]), gfx.PointsMaterial(color=(0, 1, 0, 1), size=20), ) scene.add(points) camera = gfx.OrthographicCamera(10, 10) if __name__ == "__main__": print(__doc__) canvas.request_draw(lambda: renderer.render(scene, camera)) run()
canvas = WgpuCanvas() renderer = gfx.renderers.WgpuRenderer(canvas) scene = gfx.Scene() background = gfx.Background(None, gfx.BackgroundMaterial((0, 1, 0, 1), (0, 1, 1, 1))) scene.add(background) scene.add(gfx.AxesHelper(length=50)) vol = imageio.volread("imageio:stent.npz") tex = gfx.Texture(vol, dim=3) surface = marching_cubes(vol[0:], 200) geo = gfx.Geometry(positions=np.fliplr(surface[0]), indices=surface[1], normals=surface[2]) mesh = gfx.Mesh( geo, gfx.MeshSliceMaterial(plane=(0, 0, -1, vol.shape[0] / 2), color=(1, 1, 0, 1))) scene.add(mesh) planes = [] for dim in [0, 1, 2]: # xyz abcd = [0, 0, 0, 0] abcd[dim] = -1 abcd[-1] = vol.shape[2 - dim] / 2 material = gfx.VolumeSliceMaterial(clim=(0, 2000), plane=abcd) plane = gfx.Volume(gfx.Geometry(grid=tex), material) planes.append(plane)
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=2), ) box2 = gfx.Mesh( gfx.box_geometry(3.1, 3.1, 3.1), gfx.MeshBasicMaterial(color=(0, 1, 0, 1), wireframe=True, wireframe_thickness=2), ) # In scene1 we show a raycasted volume scene1 = gfx.Scene() vol = gfx.Volume(geo, gfx.VolumeRayMaterial(clim=(0, 2000))) vol.position.set(-1, -1, -1)