Welcome to an explorative journey through the realm of Godot 4, where today’s stop is the innovative SubViewport feature. This tutorial promises to guide you through the intricacies of the SubViewport class, a uniquely streamlined method of managing game worlds which adds depth and versatility to your development arsenal without the need for creating new windows or directly drawing to the screen. Whether you’re just starting or are well-versed in the Godot engine, ready your creative muscles to harness the power of isolated scene rendering for both aesthetic appeal and functional design in your games.
Table of contents
What Is SubViewport?
A SubViewport in Godot 4 is akin to a specialized camera in your game’s world that captures a particular scene or element without the need to draw directly onto the main screen. Think of it like having a mini-stage within your larger play, where you can orchestrate separate performances simultaneously. SubViewports are crucial for rendering different parts of your game, such as UI elements in 3D space or creating picture-in-picture effects, independent from the main viewport.
What Is It For?
SubViewports serve various purposes, greatly enhancing a developer’s toolset for creating immersive experiences. With the ability to isolate parts of a scene, they can be used for:
– Displaying multiple camera angles.
– Rendering 3D models within a 2D interface.
– Creating dynamic split-screen games.
– As a render target for post-processing effects.
Why Should I Learn It?
Understanding SubViewports opens up a new dimension of visual and interactive possibilities:
– Increased Flexibility: SubViewports enable a modular approach to scene management, providing the flexibility to control how and when parts of a scene are rendered.
– Performance Optimization: They can optimize performance by limiting rendering to only the visible or necessary parts of a game scene.
– Creative Freedom: With SubViewports, your creative vision is not confined to the main game screen, which means you can craft intricate gameplay mechanics and visuals that stand out.
With this fundamental knowledge, you’re well on your way to transforming your game development skills and expanding your creative horizons. Let’s embark on this coding adventure and make your game worlds come alive with SubViewports.
Developer API
For the latest version please visit the official documentation.
Example Project
You can download the project files here.
In this example, we will be looking at how we can use the SubViewport node to render a 3D scene inside of a 2D scene. For the purpose of this example, we will be starting with a Control node as the main node, but you can use a Node2D scene just the same. Note that the concept discussed in this example can also be applied to render the output of a 2D scene in a 3D scene.
To begin with, lets create a new scene called “main” of type Control. Let’s add a ColorRect node to the scene and set it’s Anchor Preset to ‘Full Rect’ and give it a color we like.
Setting up the 3D scene
To set up the SubViewport to render a 3D scene onto our 2D scene, lets create a SubViewport node in the same scene and add a Node3D child to it. As children of the Node3D, we will add a MeshInstance3D node and set it’s mesh property to a new BoxMesh. When we switch to the 3D view, we should see a box in our scene. After scaling down and duplicating the the cube, we end up with something like this.
Click on the ‘toggle preview sunlight’ and ‘toggle preview environment’ buttons located at the menu bar right above the 3D viewport to get a more accurate representation of what our 3D scene looks like.

Create a Camera3D node and position it to get a good view of our objects. Let’s also create an OmniLight3D node and position it appropriately to light our 3D model. You can give the light a color if you’d like. Let’s add some movement into the scene! We can do this pretty easily by having our camera rotate around our objects. Create a new Node3D, rename it to “Pivot” and position it at the center of the objects in the scene. This node will act as the pivot of our rotation.
Child the Camera3D and the OmniLight3D to the newly created Pivot node. Now, when we rotate the Pivot node, the camera and light should rotate along with the Pivot. Lets create a script on the Pivot node called pivot.gd, and have it rotate on the y axis every frame.
extends Node3D var rotation_amount = 1 func _process(delta: float) -> void: rotation.y += rotation_amount * delta
We have now finished setting up our 3D scene! At the end of this, you should have something that resembles this:

Setting up the SubViewport
We can set the size of the subviewport by setting it’s size property. In this example, we will be leaving it at it’s default size of (512, 512).
A SubViewport node does not render anything to the screen by itself. We can render it’s content in two ways:
- Childing the SubViewport node to a SubViewportContainer parent.
- Rendering the texture to a node that is able to render a
ViewportTexture(Eg: Sprite2D, TextureRect)
In this example, we will be using the second method, lets create a TextureRect node as a child of our previously created ColorRect node and position it appropriately. In the texture property of the TextureRect, lets create a new ViewportTexture, by right clicking on the slot in the texture property.

We should now be prompted to select a SubViewport node, lets select the one we have in the scene.
We should now see our Camera3D’s view being projected onto the TextureRect with the help of the subviewport! When we play our scene, we should also see it being rotated and update to the movement properly!
Capturing a snapshot using the SubViewport
Lets create another TextureRect node as a child of the ColorRect and call it “SnapshotTextureRect” and position it appropriately, in this example, we will be placing it to the right of the previously created TextureRect. In ProjectSettings → Input Map, lets create a new input action called “space” and assign it the space key as an action.
We can easily capture a snapshot of what’s being rendered to the SubViewport by
- Accessing the SubViewport’s texture using
Viewport.get_texture() - Accessing the texture’s image using
Texture2D.get_image() - Using the retrieved image to create a new
ImageTexture- We do this by calling the static method
ImageTexture.create_from_image()
- We do this by calling the static method
- Setting the SnapshotTextureRect’s
textureproperty to the ImageTexture we just created.
Lets create a new script on the SnapshotTextureRect node and follow the steps outlined above.
extends TextureRect
@onready var sub_viewport: SubViewport = $"../../SubViewport"
func _process(delta: float) -> void:
if Input.is_action_just_pressed("space"):
print("Taking snapshot")
var snapshot = sub_viewport.get_texture().get_image()
var snapshot_image_texture = ImageTexture.create_from_image(snapshot)
texture = snapshot_image_textureNow when we play the game, we should see a snapshot of the viewport when the space key is pressed on our SnapshotTextureRect!

There we have it! That should get you started on working with the Subviewport node to render additional viewports onto the main viewport!
Full script code
You can download the Godot project here. The project was developed and tested in version 4.2.
pivot.gd
extends Node3D var rotation_amount = 1 func _process(delta: float) -> void: rotation.y += rotation_amount * delta
snapshot_texture_rect.gd
extends TextureRect
@onready var sub_viewport: SubViewport = $"../../SubViewport"
func _process(delta: float) -> void:
if Input.is_action_just_pressed("space"):
print("Taking snapshot")
var snapshot = sub_viewport.get_texture().get_image()
var snapshot_image_texture = ImageTexture.create_from_image(snapshot)
texture = snapshot_image_textureConclusion
As we reach the end of our adventure with SubViewports in Godot 4, we hope your mind brims with the possibilities that this powerful feature unlocks for your projects. Remember, what we’ve covered today is just the tip of the iceberg in the boundless sea of game development with Godot. Embrace these tools, experiment with them, and craft immersive experiences that leave players in awe.
Continue with us on your journey to mastery by diving into our Godot Game Development Mini-Degree. Let each course be a stepping stone towards realizing your dream games. With dedication and the right resources at your fingertips, there’s no limit to what you can create. Let your creativity soar, and transform your virtual worlds into reality with Zenva—your gateway to becoming a champion of game development.
Did you come across any errors in this tutorial? Please let us know by completing this form and we’ll look into it!

FINAL DAYS: Unlock coding courses in Unity, Godot, Unreal, Python and more.







