Skip to content

Picture-in-Picture

App: apps/pip_demo/

Viewport.new(scene) is a first-class composite viewport (Camera v2, CAM-19 / ADR 0062) — a screen region with its own camera — for picture-in-picture / minimap / security-cam, independent of SplitScreen. Here the main view is a normal third-person Cam, and a top-down Viewport composites a minimap into the top-right corner.

import "engine" for Scene, Cam, Viewport
// Main view: the normal third-person camera (the fullscreen base).
var cam = Cam.thirdPerson(scene, player)
// Minimap: a top-down Viewport in the top-right corner, drawn OVER the main view.
var mini = Viewport.new(scene)
mini.rect(0.72, 0.04, 0.24, 0.24) // screen-fraction sub-rect
mini.topDown(player, 34) // straight-down camera 34 units up
mini.border(3) // a frame around it
mini.z(1) // above the main view

draw() is just scene.draw() + the mesh draws — the renderer draws the scene once per viewport.

Terminal window
% ./plume3d pip_demo

The player circles the arena; the main view follows third-person while the minimap shows the top-down map (four corner landmarks + the centered player).

Viewport.new(scene) then fluent setters: rect(x,y,w,h) (screen fractions), z(order) (higher = on top; the main Cam view sits behind), opacity(a), border(width), borderColor(r,g,b), and a camera — follow(target) / topDown(target, height) / orbit(target, radius) / firstPerson(head) / freeFly().

Each Viewport owns its own camera director (independent of the shared per-scene Cam). Each frame WrenVm::tickCameras ticks every Viewport, folds the main Cam view in as a z-behind fullscreen base, and builds the composite viewport list with compositeViewports = true — so each viewport renders to its own offscreen target and composites at its rect/z/opacity/border. This is the same RTT composite path the angled split and the rect-peel use (ADR 0061).