Skip to content

Commit

Permalink
Update viewport scaling demo to 4.0.
Browse files Browse the repository at this point in the history
Fixes #856.

The 3d_scaling demo was updated to use the built-in 3D scaling mechanisms
in the Forward+ renderer.

A new 3d_scaling_compat demo was added to demonstrate the legacy
SubViewport-based scaling method for the Compatibility renderer.
  • Loading branch information
rcorre committed Mar 19, 2023
1 parent 956875c commit 37aab55
Show file tree
Hide file tree
Showing 21 changed files with 278 additions and 62 deletions.
15 changes: 6 additions & 9 deletions viewport/3d_scaling/README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
# 3D Viewport Scaling
# 3D Resolution Scaling

This demo shows how to scale the 3D viewport rendering without affecting 2D
elements such as the HUD. It also demonstrates how to toggle filtering on a
viewport. This technique can be useful in 2D games as well. For instance, it can
be used to have a "pixel art" viewport for the main game area and a
non-pixel-art viewport for HUD elements.
This demo shows how to downscale the 3D resolution without affecting 2D
elements, to improve performance without making the UI blurry.
This uses built-in resolution scaling supported by the `Forward+` renderer.
If you're using the `Compatibility` renderer, see ../3d_scaling_compat instead.

Language: GDScript

Renderer: GLES 2

Check out this demo on the asset library: https://godotengine.org/asset-library/asset/586
Renderer: Forward+

## Screenshots

Expand Down
43 changes: 13 additions & 30 deletions viewport/3d_scaling/hud.gd
Original file line number Diff line number Diff line change
@@ -1,42 +1,25 @@
extends Control

# The 3D viewport's scale factor. For instance, 1.0 is full resolution,
# 0.5 is half resolution and 2.0 is double resolution. Higher values look
# sharper but are slower to render. Values above 1 can be used for supersampling
# (SSAA), but filtering must be enabled for supersampling to work.
var scale_factor = 1.0
# The 3D viewport's shrink factor. For instance, 1 is full resolution,
# 2 is half resolution and 4 is quarter resolution. Lower values look
# sharper but are slower to render.
var scale_factor = 1
var filter_mode = Viewport.SCALING_3D_MODE_BILINEAR

@onready var viewport_container = $SubViewportContainer
@onready var viewport = $SubViewportContainer/SubViewport
@onready var viewport = get_tree().root
@onready var scale_label = $VBoxContainer/Scale
@onready var filter_label = $VBoxContainer/Filter

func _ready():
viewport_container.texture_filter = CanvasItem.TEXTURE_FILTER_LINEAR

# Required to change the 3D viewport's size when the window is resized.
viewport.size_changed.connect(self._root_viewport_size_changed)

viewport.scaling_3d_mode = Viewport.SCALING_3D_MODE_BILINEAR

func _unhandled_input(event):
if event.is_action_pressed("cycle_viewport_resolution"):
scale_factor = wrapf(scale_factor + 0.25, 0.25, 2.25)
viewport.size = get_viewport().size * scale_factor
scale_label.text = "Scale: %s%%" % str(scale_factor * 100)
scale_factor = wrapi(scale_factor + 1, 1, 5)
viewport.scaling_3d_scale = 1.0 / scale_factor
scale_label.text = "Scale: %3.0f%%" % (100.0 / scale_factor)

if event.is_action_pressed("toggle_filtering"):
# Toggle the Filter flag on the ViewportTexture.
if viewport_container.texture_filter == CanvasItem.TEXTURE_FILTER_LINEAR:
viewport_container.texture_filter = CanvasItem.TEXTURE_FILTER_NEAREST
filter_label.text = "Filter: Disabled"
else:
viewport_container.texture_filter = CanvasItem.TEXTURE_FILTER_LINEAR
filter_label.text = "Filter: Enabled"


# Called when the root's viewport size changes (i.e. when the window is resized).
# This is done to handle multiple resolutions without losing quality.
func _root_viewport_size_changed():
# The viewport is resized depending on the window height.
# To compensate for the larger resolution, the viewport sprite is scaled down.
viewport.size = get_viewport().size * scale_factor
filter_mode = wrapi(filter_mode + 1, Viewport.SCALING_3D_MODE_BILINEAR, Viewport.SCALING_3D_MODE_MAX) as Viewport.Scaling3DMode
viewport.scaling_3d_mode = filter_mode
filter_label.text = ClassDB.class_get_enum_constants("Viewport", "Scaling3DMode")[filter_mode].capitalize()
28 changes: 8 additions & 20 deletions viewport/3d_scaling/hud.tscn
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,15 @@ layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
theme = SubResource("2")
script = ExtResource("3")

[node name="SubViewportContainer" type="SubViewportContainer" parent="."]
texture_filter = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
stretch = true

[node name="SubViewport" type="SubViewport" parent="SubViewportContainer"]
handle_input_locally = false
size = Vector2i(1152, 648)
render_target_update_mode = 4

[node name="Cubes" parent="SubViewportContainer/SubViewport" instance=ExtResource("2")]
[node name="Cubes" parent="." instance=ExtResource("2")]

[node name="Help" type="Label" parent="."]
anchors_preset = 2
layout_mode = 0
anchor_top = 1.0
anchor_bottom = 1.0
offset_left = 16.0
Expand All @@ -40,18 +30,16 @@ Press Space to adjust the 3D viewport's resolution scaling.
Press Enter to toggle filtering."

[node name="VBoxContainer" type="VBoxContainer" parent="."]
layout_mode = 0
offset_left = 16.0
offset_top = 16.0
offset_right = 124.0
offset_bottom = 76.0

[node name="Scale" type="Label" parent="VBoxContainer"]
offset_right = 111.0
offset_bottom = 26.0
layout_mode = 2
text = "Scale: 100%"

[node name="Filter" type="Label" parent="VBoxContainer"]
offset_top = 30.0
offset_right = 111.0
offset_bottom = 56.0
text = "Filter: Enabled"
layout_mode = 2
text = "Scaling 3d Mode Fsr"
2 changes: 1 addition & 1 deletion viewport/3d_scaling/icon.png.import
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ dest_files=["res://.godot/imported/icon.png-487276ed1e3a0c39cad0279d744ee560.cte
[params]

compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/bptc_ldr=0
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
Expand Down
1 change: 1 addition & 0 deletions viewport/3d_scaling/noto_sans_ui_regular.ttf.import
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ generate_mipmaps=false
multichannel_signed_distance_field=false
msdf_pixel_range=8
msdf_size=48
allow_system_fallback=true
force_autohinter=false
hinting=1
subpixel_positioning=1
Expand Down
4 changes: 2 additions & 2 deletions viewport/3d_scaling/project.godot
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@ window/stretch/aspect="expand"

cycle_viewport_resolution={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":32,"physical_keycode":0,"unicode":0,"echo":false,"script":null)
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":32,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null)
]
}
toggle_filtering={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194309,"physical_keycode":0,"unicode":0,"echo":false,"script":null)
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194309,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null)
]
}

Expand Down
Binary file modified viewport/3d_scaling/screenshots/high.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified viewport/3d_scaling/screenshots/low.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 21 additions & 0 deletions viewport/3d_scaling_compat/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# 3D Viewport Scaling for Compatibility Renderer

This demo shows how to scale the 3D viewport rendering without affecting 2D
elements such as the HUD. It also demonstrates how to toggle filtering on a
viewport. This technique can be useful in 2D games as well. For instance, it can
be used to have a "pixel art" viewport for the main game area and a
non-pixel-art viewport for HUD elements.

If you're using the `Forward+` renderer, see ../3d_scaling instead.

Language: GDScript

Renderer: Compatibility

Check out this demo on the asset library: https://godotengine.org/asset-library/asset/586

## Screenshots

![Screenshot](screenshots/high.png)

![Screenshot](screenshots/low.png)
22 changes: 22 additions & 0 deletions viewport/3d_scaling_compat/cubes.tscn
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[gd_scene load_steps=2 format=3 uid="uid://bbnebk7xoaoto"]

[sub_resource type="BoxMesh" id="1"]
size = Vector3(2, 2, 2)

[node name="Cubes" type="Node3D"]

[node name="MeshInstance1" type="MeshInstance3D" parent="."]
mesh = SubResource("1")

[node name="MeshInstance2" type="MeshInstance3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, -1)
mesh = SubResource("1")

[node name="Camera3D" type="Camera3D" parent="."]
transform = Transform3D(0.877582, 0.229849, -0.420736, 0, 0.877582, 0.479426, 0.479426, -0.420736, 0.770151, -1.68294, 2.25571, 3.0806)
fov = 74.0

[node name="OmniLight3D" type="OmniLight3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.3, 2, 1)
shadow_enabled = true
shadow_bias = 0.08
10 changes: 10 additions & 0 deletions viewport/3d_scaling_compat/default_env.tres
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[gd_resource type="Environment" load_steps=3 format=3 uid="uid://gvgtl0xxtewa"]

[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_fikmw"]

[sub_resource type="Sky" id="1"]
sky_material = SubResource("ProceduralSkyMaterial_fikmw")

[resource]
background_mode = 2
sky = SubResource("1")
26 changes: 26 additions & 0 deletions viewport/3d_scaling_compat/hud.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
extends Control

# The 3D viewport's shrink factor. For instance, 1 is full resolution,
# 2 is half resolution and 4 is quarter resolution. Lower values look
# sharper but are slower to render.
var scale_factor = 1
var filter_mode = TEXTURE_FILTER_NEAREST

@onready var viewport_container = $SubViewportContainer
@onready var viewport = $SubViewportContainer/SubViewport
@onready var scale_label = $VBoxContainer/Scale
@onready var filter_label = $VBoxContainer/Filter

func _ready():
viewport_container.texture_filter = CanvasItem.TEXTURE_FILTER_LINEAR

func _unhandled_input(event):
if event.is_action_pressed("cycle_viewport_resolution"):
scale_factor = wrapi(scale_factor + 1, 1, 5)
viewport_container.stretch_shrink = scale_factor
scale_label.text = "Scale: %3.0f%%" % (100.0 / scale_factor)

if event.is_action_pressed("toggle_filtering"):
filter_mode = wrapi(filter_mode + 1, TEXTURE_FILTER_LINEAR, TEXTURE_FILTER_MAX) as TextureFilter
viewport_container.texture_filter = filter_mode
filter_label.text = ClassDB.class_get_enum_constants("CanvasItem", "TextureFilter")[filter_mode].capitalize()
57 changes: 57 additions & 0 deletions viewport/3d_scaling_compat/hud.tscn
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
[gd_scene load_steps=4 format=3 uid="uid://c5uc5vwuqvck5"]

[ext_resource type="PackedScene" uid="uid://bbnebk7xoaoto" path="res://cubes.tscn" id="2"]
[ext_resource type="Script" path="res://hud.gd" id="3"]

[sub_resource type="Theme" id="2"]

[node name="HUD" type="Control"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
theme = SubResource("2")
script = ExtResource("3")

[node name="SubViewportContainer" type="SubViewportContainer" parent="."]
texture_filter = 1
layout_mode = 0
anchor_right = 1.0
anchor_bottom = 1.0
stretch = true

[node name="SubViewport" type="SubViewport" parent="SubViewportContainer"]
handle_input_locally = false
size = Vector2i(1152, 648)
render_target_update_mode = 4

[node name="Cubes" parent="SubViewportContainer/SubViewport" instance=ExtResource("2")]

[node name="Help" type="Label" parent="."]
layout_mode = 0
anchor_top = 1.0
anchor_bottom = 1.0
offset_left = 16.0
offset_top = -106.0
offset_right = 554.0
offset_bottom = -16.0
text = "This text will always render at the native resolution.
Press Space to adjust the 3D viewport's resolution scaling.
Press Enter to toggle filtering."

[node name="VBoxContainer" type="VBoxContainer" parent="."]
layout_mode = 0
offset_left = 16.0
offset_top = 16.0
offset_right = 124.0
offset_bottom = 76.0

[node name="Scale" type="Label" parent="VBoxContainer"]
layout_mode = 2
text = "Scale: 100%"

[node name="Filter" type="Label" parent="VBoxContainer"]
layout_mode = 2
text = "Texture Filter Nearest"
Binary file added viewport/3d_scaling_compat/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
34 changes: 34 additions & 0 deletions viewport/3d_scaling_compat/icon.png.import
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
[remap]

importer="texture"
type="CompressedTexture2D"
uid="uid://t7xypb53csjt"
path="res://.godot/imported/icon.png-487276ed1e3a0c39cad0279d744ee560.ctex"
metadata={
"vram_texture": false
}

[deps]

source_file="res://icon.png"
dest_files=["res://.godot/imported/icon.png-487276ed1e3a0c39cad0279d744ee560.ctex"]

[params]

compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
Binary file not shown.
33 changes: 33 additions & 0 deletions viewport/3d_scaling_compat/noto_sans_ui_regular.ttf.import
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
[remap]

importer="font_data_dynamic"
type="FontFile"
uid="uid://dj5xxi41l3y1r"
path="res://.godot/imported/noto_sans_ui_regular.ttf-37da988dfa3a55ebf3ea2c9fc7b383a8.fontdata"

[deps]

source_file="res://noto_sans_ui_regular.ttf"
dest_files=["res://.godot/imported/noto_sans_ui_regular.ttf-37da988dfa3a55ebf3ea2c9fc7b383a8.fontdata"]

[params]

Rendering=null
antialiasing=1
generate_mipmaps=false
multichannel_signed_distance_field=false
msdf_pixel_range=8
msdf_size=48
allow_system_fallback=true
force_autohinter=false
hinting=1
subpixel_positioning=1
oversampling=0.0
Fallbacks=null
fallbacks=[]
Compress=null
compress=true
preload=[]
language_support={}
script_support={}
opentype_features={}
Loading

0 comments on commit 37aab55

Please sign in to comment.