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    grid = 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        cast_shadow=True,
 58    )
 59    point_light = server.scene.add_light_point(
 60        name="/control1/point_light",
 61        color=(192, 255, 238),
 62        intensity=30.0,
 63        cast_shadow=True,
 64    )
 65
 66    with server.gui.add_folder("Grid Shadows"):
 67        # Create grid shadows toggle
 68        grid_shadows = server.gui.add_slider(
 69            "Intensity",
 70            min=0.0,
 71            max=1.0,
 72            step=0.01,
 73            initial_value=grid.shadow_opacity,
 74        )
 75
 76        @grid_shadows.on_update
 77        def _(_) -> None:
 78            grid.shadow_opacity = grid_shadows.value
 79
 80    # Create default light toggle.
 81    gui_default_lights = server.gui.add_checkbox("Default lights", initial_value=True)
 82    gui_default_shadows = server.gui.add_checkbox(
 83        "Default shadows", initial_value=False
 84    )
 85
 86    gui_default_lights.on_update(
 87        lambda _: server.scene.enable_default_lights(
 88            gui_default_lights.value, gui_default_shadows.value
 89        )
 90    )
 91    gui_default_shadows.on_update(
 92        lambda _: server.scene.enable_default_lights(
 93            gui_default_lights.value, gui_default_shadows.value
 94        )
 95    )
 96
 97    # Create light control inputs.
 98    with server.gui.add_folder("Directional light"):
 99        gui_directional_color = server.gui.add_rgb(
100            "Color", initial_value=directional_light.color
101        )
102        gui_directional_intensity = server.gui.add_slider(
103            "Intensity",
104            min=0.0,
105            max=20.0,
106            step=0.01,
107            initial_value=directional_light.intensity,
108        )
109        gui_directional_shadows = server.gui.add_checkbox("Shadows", True)
110
111        @gui_directional_color.on_update
112        def _(_) -> None:
113            directional_light.color = gui_directional_color.value
114
115        @gui_directional_intensity.on_update
116        def _(_) -> None:
117            directional_light.intensity = gui_directional_intensity.value
118
119        @gui_directional_shadows.on_update
120        def _(_) -> None:
121            directional_light.cast_shadow = gui_directional_shadows.value
122
123    with server.gui.add_folder("Point light"):
124        gui_point_color = server.gui.add_rgb("Color", initial_value=point_light.color)
125        gui_point_intensity = server.gui.add_slider(
126            "Intensity",
127            min=0.0,
128            max=200.0,
129            step=0.01,
130            initial_value=point_light.intensity,
131        )
132        gui_point_shadows = server.gui.add_checkbox("Shadows", True)
133
134        @gui_point_color.on_update
135        def _(_) -> None:
136            point_light.color = gui_point_color.value
137
138        @gui_point_intensity.on_update
139        def _(_) -> None:
140            point_light.intensity = gui_point_intensity.value
141
142        @gui_point_shadows.on_update
143        def _(_) -> None:
144            point_light.cast_shadow = gui_point_shadows.value
145
146    # Create GUI elements for controlling environment map.
147    with server.gui.add_folder("Environment map"):
148        gui_env_preset = server.gui.add_dropdown(
149            "Preset",
150            (
151                "None",
152                "apartment",
153                "city",
154                "dawn",
155                "forest",
156                "lobby",
157                "night",
158                "park",
159                "studio",
160                "sunset",
161                "warehouse",
162            ),
163            initial_value="city",
164        )
165        gui_background = server.gui.add_checkbox("Background", False)
166        gui_bg_blurriness = server.gui.add_slider(
167            "Bg Blurriness",
168            min=0.0,
169            max=1.0,
170            step=0.01,
171            initial_value=0.0,
172        )
173        gui_bg_intensity = server.gui.add_slider(
174            "Bg Intensity",
175            min=0.0,
176            max=1.0,
177            step=0.01,
178            initial_value=1.0,
179        )
180        gui_env_intensity = server.gui.add_slider(
181            "Env Intensity",
182            min=0.0,
183            max=1.0,
184            step=0.01,
185            initial_value=0.3,
186        )
187
188    def update_environment_map(_) -> None:
189        server.scene.set_environment_map(
190            gui_env_preset.value if gui_env_preset.value != "None" else None,
191            background=gui_background.value,
192            background_blurriness=gui_bg_blurriness.value,
193            background_intensity=gui_bg_intensity.value,
194            environment_intensity=gui_env_intensity.value,
195        )
196
197    update_environment_map(None)
198    gui_env_preset.on_update(update_environment_map)
199    gui_background.on_update(update_environment_map)
200    gui_bg_blurriness.on_update(update_environment_map)
201    gui_bg_intensity.on_update(update_environment_map)
202    gui_env_intensity.on_update(update_environment_map)
203
204    while True:
205        time.sleep(10.0)
206
207
208if __name__ == "__main__":
209    main()