Ejemplo n.º 1
0
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)
Ejemplo n.º 2
0
def create_scene(clipping_planes, clipping_mode):

    maxsize = 221
    scene = gfx.Scene()
    for n in range(20, maxsize, 50):
        material = gfx.MeshPhongMaterial(
            color=(n / maxsize, 1, 0, 1),
            clipping_planes=clipping_planes,
            clipping_mode=clipping_mode,
        )
        geometry = gfx.box_geometry(n, n, n)
        cube = gfx.Mesh(geometry, material)
        scene.add(cube)

    return scene
Ejemplo n.º 3
0
scene = gfx.Scene()

# Create cubemap texture
tex_size = width, height, 6
tex = gfx.Texture(im, dim=2, size=tex_size)
view = tex.get_view(view_dim="cube", layer_range=range(6))

# And the background image with the cube texture
background = gfx.Background(None, gfx.BackgroundImageMaterial(map=view))
scene.add(background)

# Let's add some cubes to make the scene less boring
cubes = []
for pos in (-600, 0, -600), (-600, 0, +600), (+600, 0, -600), (+600, 0, +600):
    clr = (0.5, 0.6, 0.0, 1.0)
    cube = gfx.Mesh(gfx.box_geometry(200, 200, 200),
                    gfx.MeshPhongMaterial(color=clr))
    cube.position.from_array(pos)
    cubes.append(cube)
    scene.add(cube)

camera = gfx.PerspectiveCamera(70)
camera.scale.y = -1
camera.position.z = 0


def animate():
    rot = gfx.linalg.Quaternion().set_from_euler(gfx.linalg.Euler(0.01, 0.02))
    for cube in cubes:
        cube.rotation.multiply(rot)

    rot = gfx.linalg.Quaternion().set_from_euler(gfx.linalg.Euler(0, 0.005))
Ejemplo n.º 4
0
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)
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)))
Ejemplo n.º 5
0
"""

import imageio
from wgpu.gui.auto import WgpuCanvas, run
import pygfx as gfx

canvas = WgpuCanvas()
renderer = gfx.renderers.WgpuRenderer(canvas)
scene = gfx.Scene()

im = imageio.imread("imageio:chelsea.png")
tex = gfx.Texture(im, dim=2).get_view(filter="linear")

material = gfx.MeshBasicMaterial(map=tex)
geometry = gfx.box_geometry(100, 100, 100)
cubes = [gfx.Mesh(geometry, material) for i in range(8)]
for i, cube in enumerate(cubes):
    cube.position.set(350 - i * 100, 0, 0)
    scene.add(cube)

background = gfx.Background(None,
                            gfx.BackgroundMaterial((0, 1, 0, 1), (0, 1, 1, 1)))
scene.add(background)

camera = gfx.PerspectiveCamera(70, 16 / 9)
camera.position.z = 500


def animate():
    for i, cube in enumerate(cubes):
        rot = gfx.linalg.Quaternion().set_from_euler(
Ejemplo n.º 6
0
"""
Example showing subdivided polyhedrons.
"""

import pygfx as gfx


scene = gfx.Scene()

material = gfx.MeshBasicMaterial(wireframe=True, side="FRONT")
geometries = [gfx.tetrahedron_geometry(subdivisions=i) for i in range(4)]

for i, geometry in enumerate(geometries):
    polyhedron = gfx.Mesh(geometry, material)
    polyhedron.position.set(6 - i * 3, 0, 0)
    scene.add(polyhedron)

background = gfx.Background(None, gfx.BackgroundMaterial((0, 1, 0, 1), (0, 1, 1, 1)))
scene.add(background)


if __name__ == "__main__":
    gfx.show(scene, up=gfx.linalg.Vector3(0, 0, 1))
Ejemplo n.º 7
0
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)
scene.add(cube)

camera = gfx.PerspectiveCamera(70, 16 / 9)
camera.position.z = 400

# The post processing scene

renderer2 = gfx.renderers.WgpuRenderer(canvas)
noise_object = Fullquad(texture, NoiseMaterial(0.2))


def animate():
    rot = gfx.linalg.Quaternion().set_from_euler(gfx.linalg.Euler(0.005, 0.01))
    cube.rotation.multiply(rot)
Ejemplo n.º 8
0
"""
Example showing a Klein Bottle.
"""

from wgpu.gui.auto import WgpuCanvas, run
import pygfx as gfx

canvas = WgpuCanvas()
renderer = gfx.renderers.WgpuRenderer(canvas)
scene = gfx.Scene()

geometry = gfx.klein_bottle_geometry(10)
geometry.texcoords = None
material = gfx.MeshPhongMaterial(color=(1, 0.5, 0, 1))
obj = gfx.Mesh(geometry, material)
scene.add(obj)

obj2 = gfx.Mesh(geometry, gfx.MeshNormalLinesMaterial(color=(0, 0, 1, 1)))
obj.add(obj2)

camera = gfx.PerspectiveCamera(70, 1)
camera.position.z = 30


def animate():
    rot = gfx.linalg.Quaternion().set_from_euler(gfx.linalg.Euler(
        0.0071, 0.01))
    obj.rotation.multiply(rot)

    renderer.render(scene, camera)
    canvas.request_draw()
Ejemplo n.º 9
0
    (
        (15, 0, -7.5),
        (1, 0.3, 0.3, 1),
        gfx.sphere_geometry(4, theta_start=np.pi * 0.25, theta_length=np.pi * 0.50),
    ),
    (
        (15, 0, 7.5),
        (0.35, 0, 0, 1),
        gfx.sphere_geometry(5, width_segments=6),
    ),
    ((-15, 0, -7.5), (1, 1, 0.75, 1), gfx.sphere_geometry(7)),
    ((-15, 0, 7.5), (1, 1, 0.75, 1), gfx.sphere_geometry(5, height_segments=8)),
]
for pos, color, geometry in spheres:
    material = gfx.MeshFlatMaterial(color=color)
    wobject = gfx.Mesh(geometry, material)
    wobject.position.set(*pos)
    scene.add(wobject)

camera = gfx.PerspectiveCamera(70, 16 / 9)
camera.position.set(6, 16, -22)
controls = gfx.OrbitControls(camera.position.clone())
controls.add_default_event_handlers(canvas, camera)


def animate():
    controls.update_camera(camera)
    renderer.render(scene, camera)
    canvas.request_draw()

Ejemplo n.º 10
0
"""
Demonstrates show utility
"""

import pygfx as gfx

cube = gfx.Mesh(
    gfx.box_geometry(100, 100, 100),
    gfx.MeshPhongMaterial(),
)

if __name__ == "__main__":
    gfx.show(cube)
Ejemplo n.º 11
0
def create_object(tex, xpos):
    material = gfx.MeshPhongMaterial(map=tex, clim=(-0.05, 1))
    obj = gfx.Mesh(geometry, material)
    obj.position.x = xpos
    scene.add(obj)
Ejemplo n.º 12
0
def test_render_registry_of_wgpu():
    r = gfx.renderers.wgpu.registry

    assert None is r.get_render_function(Object1(Material1()))

    assert r.get_render_function(gfx.Mesh(None, gfx.MeshBasicMaterial()))
Ejemplo n.º 13
0
"""
Example showing transparency using three orthogonal 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()

sphere = gfx.Mesh(gfx.sphere_geometry(10), gfx.MeshPhongMaterial())

geometry = gfx.plane_geometry(50, 50)
plane1 = gfx.Mesh(geometry, gfx.MeshBasicMaterial(color=(1, 0, 0, 0.3)))
plane2 = gfx.Mesh(geometry, gfx.MeshBasicMaterial(color=(0, 1, 0, 0.5)))
plane3 = gfx.Mesh(geometry, gfx.MeshBasicMaterial(color=(0, 0, 1, 0.7)))

plane1.rotation.set_from_axis_angle(gfx.linalg.Vector3(1, 0, 0), 1.571)
plane2.rotation.set_from_axis_angle(gfx.linalg.Vector3(0, 1, 0), 1.571)
plane3.rotation.set_from_axis_angle(gfx.linalg.Vector3(0, 0, 1), 1.571)

scene.add(plane1, plane2, plane3, sphere)

camera = gfx.PerspectiveCamera(70, 16 / 9)
camera.position.z = 70
controls = gfx.OrbitControls(camera.position.clone())

Ejemplo n.º 14
0
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)
    scene.add(plane)

# camera = gfx.PerspectiveCamera(70, 16 / 9)
camera = gfx.OrthographicCamera(200, 200)
Ejemplo n.º 15
0
Archivo: cube.py Proyecto: pygfx/pygfx
"""
Example showing a single geometric cube.
"""

from wgpu.gui.auto import WgpuCanvas, run
import pygfx as gfx

canvas = WgpuCanvas()
renderer = gfx.renderers.WgpuRenderer(canvas)
scene = gfx.Scene()

cube = gfx.Mesh(
    gfx.box_geometry(200, 200, 200),
    gfx.MeshPhongMaterial(color="#336699"),
)
scene.add(cube)

camera = gfx.PerspectiveCamera(70, 16 / 9)
camera.position.z = 400


def animate():
    rot = gfx.linalg.Quaternion().set_from_euler(gfx.linalg.Euler(0.005, 0.01))
    cube.rotation.multiply(rot)

    renderer.render(scene, camera)
    canvas.request_draw()


if __name__ == "__main__":
    canvas.request_draw(animate)
Ejemplo n.º 16
0
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()

positions = np.array(
    [
        [-1, -1, 0.5],
        [-1, +1, 0.5],
        [+1, +1, 0.5],
        [+1, -1, 0.5],
        [-1, -1, 0.5],
Ejemplo n.º 17
0
scene = gfx.Scene()

im = np.array(
    [
        [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__)
Ejemplo n.º 18
0
"""
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")
Ejemplo n.º 19
0
import imageio
from wgpu.gui.auto import WgpuCanvas, run
import pygfx as gfx


canvas = WgpuCanvas()
renderer = gfx.renderers.WgpuRenderer(canvas)
scene = gfx.Scene()

im = imageio.imread("imageio:bricks.jpg")
tex = gfx.Texture(im, dim=2).get_view(filter="linear", address_mode="repeat")

geometry = gfx.torus_knot_geometry(1, 0.3, 128, 32)
geometry.texcoords.data[:, 0] *= 10  # stretch the texture
material = gfx.MeshPhongMaterial(map=tex, clim=(30, 240))
obj = gfx.Mesh(geometry, material)
scene.add(obj)

camera = gfx.PerspectiveCamera(70, 1)
camera.position.z = 4


def animate():
    rot = gfx.linalg.Quaternion().set_from_euler(gfx.linalg.Euler(0.0071, 0.01))
    obj.rotation.multiply(rot)

    renderer.render(scene, camera)
    canvas.request_draw()


if __name__ == "__main__":
Ejemplo n.º 20
0
"""
Demonstrates visualizing object bounding boxes
"""
from pathlib import Path

import trimesh

import pygfx as gfx

teapot = trimesh.load(Path(__file__).parent / "models" / "teapot.stl")

scene = gfx.Scene()

mesh = gfx.Mesh(
    gfx.trimesh_geometry(teapot),
    gfx.MeshPhongMaterial(),
)
mesh.rotation.set_from_euler(gfx.linalg.Euler(0.71, 0.91))
scene.add(mesh)

box_world = gfx.BoxHelper()
box_world.set_transform_by_object(mesh)
scene.add(box_world)

box_local = gfx.BoxHelper()
box_local.set_transform_by_object(mesh, space="local")
mesh.add(box_local)  # note that the parent is `mesh` here, not `scene`

box_local.material.color = (0, 1, 0, 1)

if __name__ == "__main__":
Ejemplo n.º 21
0
renderer = gfx.renderers.WgpuRenderer(canvas)
scene = gfx.Scene()

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()
Ejemplo n.º 22
0
Example showing a single geometric cube.
"""

import pygfx as gfx

from PySide6 import QtWidgets  # Replace PySide6 with PyQt6, PyQt5 or PySide2
from wgpu.gui.qt import WgpuCanvas

app = QtWidgets.QApplication([])

canvas = WgpuCanvas()
renderer = gfx.renderers.WgpuRenderer(canvas)
scene = gfx.Scene()

cube = gfx.Mesh(
    gfx.box_geometry(200, 200, 200),
    gfx.MeshPhongMaterial(color=(0.2, 0.4, 0.6, 1.0)),
)
scene.add(cube)

camera = gfx.PerspectiveCamera(70, 16 / 9)
camera.position.z = 400


def animate():
    rot = gfx.linalg.Quaternion().set_from_euler(gfx.linalg.Euler(0.005, 0.01))
    cube.rotation.multiply(rot)

    renderer.render(scene, camera)
    canvas.request_draw()

Ejemplo n.º 23
0
from wgpu.gui.auto import WgpuCanvas, run
import pygfx as gfx

canvas = WgpuCanvas()
renderer = gfx.renderers.WgpuRenderer(canvas)
scene = gfx.Scene()

material = gfx.MeshPhongMaterial()
geometries = [
    gfx.tetrahedron_geometry(),
    gfx.octahedron_geometry(),
    gfx.icosahedron_geometry(),
    gfx.dodecahedron_geometry(),
]

polyhedrons = [gfx.Mesh(geometries[i], material) for i in range(5)]
for i, polyhedron in enumerate(polyhedrons):
    polyhedron.position.set(6 - i * 3, 0, 0)
    scene.add(polyhedron)

background = gfx.Background(None,
                            gfx.BackgroundMaterial((0, 1, 0, 1), (0, 1, 1, 1)))
scene.add(background)

camera = gfx.PerspectiveCamera(70, 16 / 9)
camera.position.z = 10


def animate():
    for polyhedron in polyhedrons:
        rot = gfx.linalg.Quaternion().set_from_euler(
Ejemplo n.º 24
0
import numpy as np
import imageio
from wgpu.gui.auto import WgpuCanvas, run
import pygfx as gfx

canvas = WgpuCanvas()
renderer = gfx.renderers.WgpuRenderer(canvas)
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)
cube.position.x += 150
scene.add(cube)

torus = gfx.Mesh(gfx.torus_knot_geometry(100, 20, 128, 32),
                 gfx.MeshPhongMaterial())
torus.position.x -= 150
scene.add(torus)

camera = gfx.PerspectiveCamera(70, 16 / 9)
camera.position.z = 400


@canvas.add_event_handler("pointer_down")
def handle_event(event):
    info = renderer.get_pick_info((event["x"], event["y"]))
Ejemplo n.º 25
0
# First create the subscene, that reders into a texture

texture1 = gfx.Texture(dim=2, size=(200, 200, 1), format="rgba8unorm")

renderer1 = gfx.renderers.WgpuRenderer(texture1)
scene1 = gfx.Scene()

background1 = gfx.Background(None, gfx.BackgroundMaterial((0, 0.5, 0, 1)))
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"))
Ejemplo n.º 26
0
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
    material2.plane = 1, 0, 1, dist
Ejemplo n.º 27
0
# 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)

# Note the negation of near and far in the plane's position. This is
# because the camera looks down the z-axis: more negative means moving
# away from the camera, positive values are behind the camera.
plane1.position = gfx.linalg.Vector3(-0.51, -0.51, -(near + 0.01))  # in range
plane2.position = gfx.linalg.Vector3(+0.51, -0.51, -(near - 0.01))  # out range
plane3.position = gfx.linalg.Vector3(-0.51, +0.51, -(far - 0.01))  # in range
plane4.position = gfx.linalg.Vector3(+0.51, +0.51, -(far + 0.01))  # out range

for plane in (plane1, plane2, plane3, plane4):
    scene.add(plane)