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()