Quick answer: SubViewportContainer must have stretch = true and mouse_filter = Stop. The SubViewport needs handle_input_locally = true.
An in-game computer terminal renders a 3D scene in a SubViewport shown via SubViewportContainer. Clicks on the terminal don’t reach the 3D scene’s Area3Ds.
Container Settings
SubViewportContainer:
stretch = true # scales viewport to container size + maps input
mouse_filter = MOUSE_FILTER_STOP # container receives the event
stretch enables the input coordinate remapping. Without it, the container shows the viewport but doesn’t translate clicks.
SubViewport Settings
SubViewport:
handle_input_locally = true
Lets the viewport process input independently of the main window.
Coordinate Mapping
With stretch=true, a click at the container’s pixel (x, y) maps to the viewport’s coordinate space scaled by the container/viewport size ratio. Godot handles this automatically once stretch is on.
Picking in the 3D Sub-Scene
Inside the SubViewport, ensure the Camera3D is current and Area3Ds have input_ray_pickable = true (the same rules as any 3D picking).
Verifying
Click the terminal UI. Clicks register on the 3D scene’s interactive objects. Coordinates map correctly even when the container is resized.
“stretch=true is the magic flag. It both scales the render and remaps input coordinates.”
For VR in-world UI panels, the same pattern works — render a 2D/3D sub-scene to a SubViewport, project the controller ray onto its texture for input.