Lighting and ShadowsΒΆ

Example adding lights and enabling shadow rendering.

  1import time
  2from pathlib import Path
  3
  4import numpy as np
  5import trimesh
  6
  7import viser
  8import viser.transforms as tf
  9
 10
 11def main() -> None:
 12    # Load mesh.
 13    mesh = trimesh.load_mesh(str(Path(__file__).parent / "assets/dragon.obj"))
 14    assert isinstance(mesh, trimesh.Trimesh)
 15    mesh.apply_scale(0.05)
 16    vertices = mesh.vertices
 17    faces = mesh.faces
 18    print(f"Loaded mesh with {vertices.shape} vertices, {faces.shape} faces")
 19    print(mesh)
 20
 21    # Start Viser server with mesh.
 22    server = viser.ViserServer()
 23
 24    server.scene.add_mesh_simple(
 25        name="/simple",
 26        vertices=vertices,
 27        faces=faces,
 28        wxyz=tf.SO3.from_x_radians(np.pi / 2).wxyz,
 29        position=(0.0, 2.0, 0.0),
 30    )
 31    server.scene.add_mesh_trimesh(
 32        name="/trimesh",
 33        mesh=mesh,
 34        wxyz=tf.SO3.from_x_radians(np.pi / 2).wxyz,
 35        position=(0.0, -2.0, 0.0),
 36    )
 37    server.scene.add_grid(
 38        "grid",
 39        width=20.0,
 40        height=20.0,
 41        position=np.array([0.0, 0.0, -2.0]),
 42    )
 43
 44    # adding controls to custom lights in the scene
 45    server.scene.add_transform_controls(
 46        "/control0", position=(0.0, 10.0, 5.0), scale=2.0
 47    )
 48    server.scene.add_label("/control0/label", "Directional")
 49    server.scene.add_transform_controls(
 50        "/control1", position=(0.0, -5.0, 5.0), scale=2.0
 51    )
 52    server.scene.add_label("/control1/label", "Point")
 53
 54    directional_light = server.scene.add_light_directional(
 55        name="/control0/directional_light",
 56        color=(186, 219, 173),
 57    )
 58    point_light = server.scene.add_light_point(
 59        name="/control1/point_light",
 60        color=(192, 255, 238),
 61        intensity=30.0,
 62    )
 63
 64    # Create default light toggle.
 65    gui_default_lights = server.gui.add_checkbox("Default lights", initial_value=True)
 66    gui_default_shadows = server.gui.add_checkbox(
 67        "Default shadows", initial_value=False
 68    )
 69
 70    gui_default_lights.on_update(
 71        lambda _: server.scene.enable_default_lights(gui_default_lights.value)
 72    )
 73    gui_default_shadows.on_update(
 74        lambda _: server.scene.enable_default_lights(gui_default_lights.value)
 75    )
 76
 77    # Create light control inputs.
 78    with server.gui.add_folder("Directional light"):
 79        gui_directional_color = server.gui.add_rgb(
 80            "Color", initial_value=directional_light.color
 81        )
 82        gui_directional_intensity = server.gui.add_slider(
 83            "Intensity",
 84            min=0.0,
 85            max=20.0,
 86            step=0.01,
 87            initial_value=directional_light.intensity,
 88        )
 89
 90        @gui_directional_color.on_update
 91        def _(_) -> None:
 92            directional_light.color = gui_directional_color.value
 93
 94        @gui_directional_intensity.on_update
 95        def _(_) -> None:
 96            directional_light.intensity = gui_directional_intensity.value
 97
 98    with server.gui.add_folder("Point light"):
 99        gui_point_color = server.gui.add_rgb("Color", initial_value=point_light.color)
100        gui_point_intensity = server.gui.add_slider(
101            "Intensity",
102            min=0.0,
103            max=200.0,
104            step=0.01,
105            initial_value=point_light.intensity,
106        )
107
108        @gui_point_color.on_update
109        def _(_) -> None:
110            point_light.color = gui_point_color.value
111
112        @gui_point_intensity.on_update
113        def _(_) -> None:
114            point_light.intensity = gui_point_intensity.value
115
116    # Create GUI elements for controlling environment map.
117    with server.gui.add_folder("Environment map"):
118        gui_env_preset = server.gui.add_dropdown(
119            "Preset",
120            (
121                "None",
122                "apartment",
123                "city",
124                "dawn",
125                "forest",
126                "lobby",
127                "night",
128                "park",
129                "studio",
130                "sunset",
131                "warehouse",
132            ),
133            initial_value="city",
134        )
135        gui_background = server.gui.add_checkbox("Background", False)
136        gui_bg_blurriness = server.gui.add_slider(
137            "Bg Blurriness",
138            min=0.0,
139            max=1.0,
140            step=0.01,
141            initial_value=0.0,
142        )
143        gui_bg_intensity = server.gui.add_slider(
144            "Bg Intensity",
145            min=0.0,
146            max=1.0,
147            step=0.01,
148            initial_value=1.0,
149        )
150        gui_env_intensity = server.gui.add_slider(
151            "Env Intensity",
152            min=0.0,
153            max=1.0,
154            step=0.01,
155            initial_value=0.3,
156        )
157
158    def update_environment_map(_) -> None:
159        server.scene.set_environment_map(
160            gui_env_preset.value if gui_env_preset.value != "None" else None,
161            background=gui_background.value,
162            background_blurriness=gui_bg_blurriness.value,
163            background_intensity=gui_bg_intensity.value,
164            environment_intensity=gui_env_intensity.value,
165        )
166
167    update_environment_map(None)
168    gui_env_preset.on_update(update_environment_map)
169    gui_background.on_update(update_environment_map)
170    gui_bg_blurriness.on_update(update_environment_map)
171    gui_bg_intensity.on_update(update_environment_map)
172    gui_env_intensity.on_update(update_environment_map)
173
174    while True:
175        time.sleep(10.0)
176
177
178if __name__ == "__main__":
179    main()