def test_otho_camera_near_far(): for near, far in [ (0, 100), (0, 10000), (-1200, 1200), (-40, 300), (-400, 0), (-400, -300), (300, 500), ]: camera = gfx.OrthographicCamera(20, 20, near, far) camera.update_projection_matrix() assert camera.near == near assert camera.far == far _run_for_camera(camera, near, far, True)
def __init__(self): super().__init__(None) self.resize(640, 480) # Creat button and hook it up self._button = QtWidgets.QPushButton("Add a line", self) self._button.clicked.connect(self._on_button_click) # Create canvas, renderer and a scene object self._canvas = WgpuCanvas(parent=self) self._renderer = gfx.WgpuRenderer(self._canvas) self._scene = gfx.Scene() self._camera = gfx.OrthographicCamera(110, 110) # Hook up the animate callback self._canvas.request_draw(self.animate) layout = QtWidgets.QHBoxLayout() self.setLayout(layout) layout.addWidget(self._button) layout.addWidget(self._canvas)
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") scene.add(scene.children[0]) canvas.request_draw() elif event["key"] in "0123456789": m = [ None, "opaque", "ordered1", "ordered2", "weighted",
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) # === 1D colormap # # For the 1D texcoords we use the second dimension of the default # texcoords, which runs from the top to the bottom of the cylinder. The # 1D colormap runs from yellow to cyan. texcoords1 = geometry.texcoords.data[:, 1].copy() cmap1 = np.array([(1, 1, 0), (0, 1, 1)], np.float32) tex1 = gfx.Texture(cmap1, dim=1).get_view(filter="linear") create_object(texcoords1, tex1, -6)
# 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() 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,
canvas = WgpuCanvas() renderer = gfx.renderers.WgpuRenderer(canvas) scene = gfx.Scene() voldata = imageio.volread("imageio:stent.npz") nslices = voldata.shape[0] index = nslices // 2 vol = gfx.Volume( gfx.Geometry(grid=voldata), gfx.VolumeSliceMaterial(clim=(0, 2000), plane=(0, 0, -1, index)), ) scene.add(vol) camera = gfx.OrthographicCamera(128, 128) camera.position.set(64, 64, 128) camera.scale.y = -1 # in this case we tweak the camera, not the plane @canvas.add_event_handler("wheel") def handle_wheel_event(event): global index index = index + event["dy"] / 90 index = max(0, min(nslices - 1, index)) vol.material.plane = 0, 0, -1, index canvas.request_draw() @canvas.add_event_handler("pointer_down") def handle_pointer_event(event):
obj1.position.set(-2, 0, 0) obj1.material.side = "FRONT" # Create a green knot for which we show the back material2 = gfx.MeshPhongMaterial(color=(0, 1, 0, 1)) obj2 = gfx.Mesh(geometry, material2) obj2.position.set(+2, 0, 0) obj2.material.side = "BACK" # Rotate all of them and add to scene rot = gfx.linalg.Quaternion().set_from_euler(gfx.linalg.Euler(0.71, 1)) obj1.rotation.multiply(rot) obj2.rotation.multiply(rot) scene.add(obj1, obj2) camera = gfx.OrthographicCamera(6, 4) def animate(): # Render top row camera.scale.z = 1 renderer.render(scene, camera, viewport=(0, 0, 600, 300), flush=False) # Render same scene in bottom row. The camera's z scale is negative. # This means it looks backwards, but more importantly, it means that the # winding is affected. The result should still look correct because we # take this effect into account in the mesh shader. camera.scale.z = -1 renderer.render(scene, camera, viewport=(0, 300, 600, 300)) if __name__ == "__main__":
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: i = int(round(info["vertex_index"])) geometry.positions.data[i, 1] *= -1 geometry.positions.update_range(i) canvas.request_draw() if __name__ == "__main__":
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 colors = np.array(positions.copy()) colors /= colors.max() colors = np.hstack([colors, np.ones((colors.shape[0], 1))]) colors = colors.astype("f4") geometry = gfx.Geometry(positions=positions, colors=colors) material = gfx.LineThinMaterial(thickness=12.0, vertex_colors=True) line = gfx.Line(geometry, material) scene.add(line) camera = gfx.OrthographicCamera(600, 500) camera.position.set(300, 250, 0) if __name__ == "__main__": canvas.request_draw(lambda: renderer.render(scene, camera)) run()
# %% 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) near, far = -400, 700 camera = gfx.OrthographicCamera(512, 512) camera.position.set(256, 256, 0) camera.scale.y = -1 if __name__ == "__main__": canvas.request_draw(lambda: renderer.render(scene, camera)) run()
vol = imageio.volread("imageio:stent.npz") nslices = vol.shape[0] index = nslices // 2 tex_size = tuple(reversed(vol.shape)) tex = gfx.Texture(vol, dim=2, size=tex_size) view = tex.get_view(filter="linear", view_dim="2d", layer_range=range(index, index + 1)) geometry = gfx.plane_geometry(200, 200, 12, 12) material = gfx.MeshBasicMaterial(map=view, clim=(0, 2000)) plane = gfx.Mesh(geometry, material) scene.add(plane) camera = gfx.OrthographicCamera(200, 200) @canvas.add_event_handler("wheel") def handle_event(event): global index index = index + int(event["dy"] / 90) index = max(0, min(nslices - 1, index)) view = tex.get_view(filter="linear", view_dim="2d", layer_range=range(index, index + 1)) material.map = view canvas.request_draw() if __name__ == "__main__":
# Compose another scene scene2 = gfx.Scene() 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) 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.OrthographicCamera(2.2, 2.2) def animate(): rot = gfx.linalg.Quaternion().set_from_euler(gfx.linalg.Euler(0.005, 0.01)) cube1.rotation.multiply(rot) w, h = canvas.get_logical_size() renderer.render(scene1, camera1, flush=False, viewport=(0, 0, w / 2, h / 2)) renderer.render(scene2, camera2, flush=False, viewport=(w / 2, 0, w / 2, h / 2))
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)]) geometry = gfx.Geometry(positions=positions) if use_thin_lines: material = gfx.LineThinMaterial(color=(col / cols, row / rows, 0.5, 1.0)) else: material = gfx.LineMaterial( thickness=0.2 + 2 * row / rows, color=(col / cols, row / rows, 0.5, 1.0) ) line = gfx.Line(geometry, material) line.position.x = col line.position.y = row scene.add(line) camera = gfx.OrthographicCamera(cols, rows) camera.maintain_aspect = False controls = gfx.PanZoomControls(camera.position.clone()) controls.pan(gfx.linalg.Vector3(cols / 2, rows / 2, 0)) controls.add_default_event_handlers(canvas, camera) def animate(): controls.update_camera(camera) t0 = time.perf_counter() # noqa renderer.render(scene, camera) # print(time.perf_counter() - t0) canvas.request_draw() if __name__ == "__main__":
canvas = WgpuCanvas() renderer = gfx.renderers.WgpuRenderer(canvas) scene = gfx.Scene() # %% Select near, far, and camera # With the ortho camera, you can pick any values you like, also negative # near values. With the perspective camera you'll want to pick a small # positive near-value, and a relatively small value for the far-value # as well, otherwise the distant squares become smaller than 1 pixel ;) # Select camera and matchingclipping planes if True: near, far = -40, 300 camera = gfx.OrthographicCamera(2.2, 2.2, near, far) else: near, far = 5, 10 camera = gfx.PerspectiveCamera(50, 1, near, far) # %% Create four planes near the z-clipping planes geometry = gfx.plane_geometry(1, 1) green_material = gfx.MeshBasicMaterial(color=(0, 0.8, 0.2, 1)) greener_material = gfx.MeshBasicMaterial(color=(0, 1, 0, 1)) red_material = gfx.MeshBasicMaterial(color=(1, 0, 0, 1)) plane1 = gfx.Mesh(geometry, green_material) plane2 = gfx.Mesh(geometry, red_material) plane3 = gfx.Mesh(geometry, greener_material) plane4 = gfx.Mesh(geometry, red_material)
""" Display a line depicting a noisy signal consisting of a lot of points. """ import numpy as np from wgpu.gui.auto import WgpuCanvas, run import pygfx as gfx canvas = WgpuCanvas() renderer = gfx.WgpuRenderer(canvas) scene = gfx.Scene() # todo: crank this to 1M when wgpu allows it :D x = np.linspace(0, 100, 10_000, dtype=np.float32) y = np.sin(x) * 30 + np.random.normal(0, 5, len(x)).astype(np.float32) positions = np.column_stack([x, y, np.zeros_like(x)]) line = gfx.Line( gfx.Geometry(positions=positions), gfx.LineMaterial(thickness=2.0, color=(0.0, 0.7, 0.3, 1.0)), ) scene.add(line) camera = gfx.OrthographicCamera(110, 110) camera.position.set(50, 0, 0) if __name__ == "__main__": canvas.request_draw(lambda: renderer.render(scene, camera)) run()