RenderView¶
the main scene from a second camera, shown on an in-world monitor.
▶ Run in browserTags: 3d renderview render-to-texture camera
A RenderView renders the main scene through a second Camera3D into an
offscreen texture, every frame. Here that camera is a security camera hung
above the set, and its feed plays on a monitor standing in the same world.
RenderView(camera="SecurityCam", size=(512, 512))names its camera by node path, resolved relative to the view; here the camera is the view’s child.The security camera is built with
visible=False. The scene renders through the first visibleCamera3D, so a hidden camera never takes over the main view, and theRenderViewstill renders through it.Material(albedo_map=view, unlit=True)puts the live feed on a surface. The material follows the view’s texture every frame, so there is nothing to copy or refresh by hand.
A SubViewport renders its own subtree; a RenderView has no subtree of its
own and re-renders the one main world from another viewpoint. The orange cube
spins in both views at once, so the monitor is a live capture, not a snapshot.
Keep the monitor out of the security camera’s view: a camera that sees the surface showing its own feed would sample the texture it is rendering into.
Source¶
1# /// simvx
2# tags = ["3d", "renderview", "render-to-texture", "camera"]
3# screenshot_frame = 30
4# ///
5"""RenderView: the main scene from a second camera, shown on an in-world monitor.
6
7A `RenderView` renders the main scene through a second `Camera3D` into an
8offscreen texture, every frame. Here that camera is a security camera hung
9above the set, and its feed plays on a monitor standing in the same world.
10
11- `RenderView(camera="SecurityCam", size=(512, 512))` names its camera by node
12 path, resolved relative to the view; here the camera is the view's child.
13- The security camera is built with `visible=False`. The scene renders through
14 the first visible `Camera3D`, so a hidden camera never takes over the main
15 view, and the `RenderView` still renders through it.
16- `Material(albedo_map=view, unlit=True)` puts the live feed on a surface. The
17 material follows the view's texture every frame, so there is nothing to
18 copy or refresh by hand.
19
20A `SubViewport` renders its own subtree; a `RenderView` has no subtree of its
21own and re-renders the one main world from another viewpoint. The orange cube
22spins in both views at once, so the monitor is a live capture, not a snapshot.
23
24Keep the monitor out of the security camera's view: a camera that sees the
25surface showing its own feed would sample the texture it is rendering into.
26"""
27
28from simvx.core import (
29 Anchor,
30 Camera3D,
31 CanvasLayer,
32 DirectionalLight3D,
33 Label,
34 Material,
35 Mesh,
36 MeshInstance3D,
37 Node,
38 Quat,
39 RenderView,
40)
41from simvx.graphics import App
42
43
44class RenderViewScene(Node):
45 def on_ready(self):
46 self.add_child(Camera3D(position=(0, 2.2, 7.0), look_at=(0, 0.4, 0)))
47 self.add_child(DirectionalLight3D(intensity=2.5, direction=(-0.4, -1.0, -0.6)))
48
49 # Aimed at the set's centre-right, so the monitor (front-left) stays out of frame.
50 view = self.add_child(RenderView(camera="SecurityCam", size=(512, 512)))
51 view.add_child(
52 Camera3D(name="SecurityCam", visible=False, fov=45.0, position=(4.5, 5.5, 4.5), look_at=(1.2, 0.3, 0.3))
53 )
54
55 self.add_child(
56 MeshInstance3D(
57 mesh=Mesh.box((12.0, 0.5, 12.0)),
58 material=Material(colour=(0.35, 0.38, 0.42, 1.0), roughness=0.9),
59 position=(0, -0.75, 0),
60 )
61 )
62 self.spinner = self.add_child(
63 MeshInstance3D(
64 mesh=Mesh.box(1.2),
65 material=Material(colour=(0.95, 0.55, 0.15, 1.0), roughness=0.4),
66 position=(0, 0.4, 0),
67 )
68 )
69 self.add_child(
70 MeshInstance3D(
71 mesh=Mesh.sphere(0.5),
72 material=Material(colour=(0.3, 0.5, 0.95, 1.0), roughness=0.3),
73 position=(2.2, 0.0, 1.2),
74 )
75 )
76 self.add_child(
77 MeshInstance3D(
78 mesh=Mesh.box((0.6, 1.8, 0.6)),
79 material=Material(colour=(0.3, 0.8, 0.4, 1.0)),
80 position=(-2.2, 0.4, -1.0),
81 )
82 )
83
84 # The monitor, angled toward the main camera.
85 self.add_child(
86 MeshInstance3D(
87 mesh=Mesh.box((2.0, 2.0, 0.08)),
88 material=Material(albedo_map=view, unlit=True),
89 position=(-2.6, 1.5, 3.4),
90 rotation=Quat.from_euler(0.0, 0.5, 0.0),
91 )
92 )
93
94 hud = self.add_child(CanvasLayer())
95 hud.add_child(Label("RenderView: overhead security feed", anchor=Anchor.TOP_LEFT, inset=16, font_size=24))
96
97 def on_update(self, dt):
98 self.spinner.rotate_y(1.4 * dt)
99 self.spinner.rotate_x(0.7 * dt)
100
101
102if __name__ == "__main__":
103 App(width=1280, height=720, title="SimVX - RenderView").run(RenderViewScene())