Update viewport scaling demo to 4.x

The 3d_scaling demo was updated to use the built-in 3D scaling mechanisms
in the Forward+ and Mobile renderer (Compatibility in 4.3).

Co-authored-by: A Thousand Ships <96648715+AThousandShips@users.noreply.github.com>
This commit is contained in:
Ryan Roden-Corrent
2023-03-18 07:42:58 -04:00
committed by Hugo Locurcio
parent 4d01a2678f
commit 722bd11689
9 changed files with 146 additions and 79 deletions

View File

@@ -1,19 +1,15 @@
# 3D Viewport Scaling # 3D Resolution Scaling
This demo shows how to scale the 3D viewport rendering without affecting 2D This demo shows how to downscale the 3D resolution without affecting 2D
elements such as the HUD. It also demonstrates how to toggle filtering on a elements, to improve performance without making the UI blurry.
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 See [Resolution scaling](https://docs.godotengine.org/en/stable/tutorials/3d/resolution_scaling.html)
non-pixel-art viewport for HUD elements. in the documentation for details.
Language: GDScript Language: GDScript
Renderer: GLES 2 Renderer: Forward+
Check out this demo on the asset library: https://godotengine.org/asset-library/asset/586 ## Screenshot
## Screenshots ![3D Resolution Scaling](screenshots/3d_scaling.webp)
![Screenshot](screenshots/high.png)
![Screenshot](screenshots/low.png)

View File

@@ -1,10 +1,80 @@
[gd_scene load_steps=2 format=3 uid="uid://bbnebk7xoaoto"] [gd_scene load_steps=14 format=3 uid="uid://bbnebk7xoaoto"]
[sub_resource type="Gradient" id="Gradient_20ov5"]
offsets = PackedFloat32Array(0, 0.269231, 0.538462, 1)
colors = PackedColorArray(0, 0, 0, 1, 0.211332, 0.268774, 0.382711, 1, 0.248048, 0.560964, 0.645926, 1, 1, 1, 1, 1)
[sub_resource type="FastNoiseLite" id="FastNoiseLite_ja65t"]
fractal_type = 2
fractal_gain = 0.333
[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_gdmpo"]
height = 256
seamless = true
color_ramp = SubResource("Gradient_20ov5")
noise = SubResource("FastNoiseLite_ja65t")
[sub_resource type="PanoramaSkyMaterial" id="PanoramaSkyMaterial_me6gu"]
panorama = SubResource("NoiseTexture2D_gdmpo")
[sub_resource type="Sky" id="Sky_5j6vf"]
sky_material = SubResource("PanoramaSkyMaterial_me6gu")
[sub_resource type="Environment" id="Environment_0v44j"]
background_mode = 2
sky = SubResource("Sky_5j6vf")
tonemap_mode = 2
tonemap_white = 6.0
[sub_resource type="Gradient" id="Gradient_1dao0"]
[sub_resource type="FastNoiseLite" id="FastNoiseLite_y7cc2"]
frequency = 0.001
fractal_type = 2
fractal_lacunarity = 3.0
fractal_gain = 1.4
fractal_weighted_strength = 0.25
domain_warp_enabled = true
domain_warp_type = 2
[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_42rpi"]
seamless = true
color_ramp = SubResource("Gradient_1dao0")
noise = SubResource("FastNoiseLite_y7cc2")
[sub_resource type="FastNoiseLite" id="FastNoiseLite_rxfm5"]
frequency = 0.001
fractal_type = 2
fractal_octaves = 2
fractal_lacunarity = 3.0
fractal_gain = 1.4
fractal_weighted_strength = 0.25
domain_warp_enabled = true
domain_warp_type = 2
[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_gwux6"]
seamless = true
as_normal_map = true
bump_strength = 10.0
color_ramp = SubResource("Gradient_1dao0")
noise = SubResource("FastNoiseLite_rxfm5")
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_sany7"]
albedo_texture = SubResource("NoiseTexture2D_42rpi")
normal_enabled = true
normal_texture = SubResource("NoiseTexture2D_gwux6")
uv1_scale = Vector3(6, 4, 1)
texture_filter = 5
[sub_resource type="BoxMesh" id="1"] [sub_resource type="BoxMesh" id="1"]
material = SubResource("StandardMaterial3D_sany7")
size = Vector3(2, 2, 2) size = Vector3(2, 2, 2)
[node name="Cubes" type="Node3D"] [node name="Cubes" type="Node3D"]
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
environment = SubResource("Environment_0v44j")
[node name="MeshInstance1" type="MeshInstance3D" parent="."] [node name="MeshInstance1" type="MeshInstance3D" parent="."]
mesh = SubResource("1") mesh = SubResource("1")
@@ -12,11 +82,36 @@ mesh = SubResource("1")
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, -1) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, -1)
mesh = SubResource("1") mesh = SubResource("1")
[node name="MeshInstance3" type="MeshInstance3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 3, 0, 0)
mesh = SubResource("1")
[node name="MeshInstance4" type="MeshInstance3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 4, 1, -1)
mesh = SubResource("1")
[node name="MeshInstance5" type="MeshInstance3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 6, 0, 0)
mesh = SubResource("1")
[node name="MeshInstance6" type="MeshInstance3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 7, 1, -1)
mesh = SubResource("1")
[node name="MeshInstance7" type="MeshInstance3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -3, 0, 0)
mesh = SubResource("1")
[node name="MeshInstance8" type="MeshInstance3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -2, 1, -1)
mesh = SubResource("1")
[node name="Camera3D" type="Camera3D" parent="."] [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) 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 fov = 74.0
[node name="OmniLight3D" type="OmniLight3D" parent="."] [node name="OmniLight3D" type="OmniLight3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.3, 2, 1) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.3, 2, 1)
light_energy = 3.0
shadow_enabled = true shadow_enabled = true
shadow_bias = 0.08 shadow_bias = 0.02

View File

@@ -1,10 +0,0 @@
[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")

View File

@@ -1,42 +1,34 @@
extends Control 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
@onready var viewport_container = $SubViewportContainer # The 3D viewport's shrink factor. For instance, 1 is full resolution,
@onready var viewport = $SubViewportContainer/SubViewport # 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 = get_tree().root
@onready var scale_label = $VBoxContainer/Scale @onready var scale_label = $VBoxContainer/Scale
@onready var filter_label = $VBoxContainer/Filter @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. func _ready():
viewport.size_changed.connect(self._root_viewport_size_changed) viewport.scaling_3d_mode = Viewport.SCALING_3D_MODE_BILINEAR
func _unhandled_input(event): func _unhandled_input(event):
if event.is_action_pressed("cycle_viewport_resolution"): if event.is_action_pressed("cycle_viewport_resolution"):
scale_factor = wrapf(scale_factor + 0.25, 0.25, 2.25) scale_factor = wrapi(scale_factor + 1, 1, 5)
viewport.size = get_viewport().size * scale_factor viewport.scaling_3d_scale = 1.0 / scale_factor
scale_label.text = "Scale: %s%%" % str(scale_factor * 100) scale_label.text = "Scale: %3.0f%%" % (100.0 / scale_factor)
if event.is_action_pressed("toggle_filtering"): if event.is_action_pressed("toggle_filtering"):
# Toggle the Filter flag on the ViewportTexture. filter_mode = wrapi(filter_mode + 1, Viewport.SCALING_3D_MODE_BILINEAR, Viewport.SCALING_3D_MODE_MAX) as Viewport.Scaling3DMode
if viewport_container.texture_filter == CanvasItem.TEXTURE_FILTER_LINEAR: viewport.scaling_3d_mode = filter_mode
viewport_container.texture_filter = CanvasItem.TEXTURE_FILTER_NEAREST filter_label.text = (
filter_label.text = "Filter: Disabled" ClassDB.class_get_enum_constants("Viewport", "Scaling3DMode")[filter_mode]
else: .capitalize()
viewport_container.texture_filter = CanvasItem.TEXTURE_FILTER_LINEAR .replace("3d", "3D")
filter_label.text = "Filter: Enabled" .replace("Mode", "Mode:")
.replace("Fsr", "FSR")
)
# 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

View File

@@ -10,48 +10,42 @@ layout_mode = 3
anchors_preset = 15 anchors_preset = 15
anchor_right = 1.0 anchor_right = 1.0
anchor_bottom = 1.0 anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
theme = SubResource("2") theme = SubResource("2")
script = ExtResource("3") script = ExtResource("3")
[node name="SubViewportContainer" type="SubViewportContainer" parent="."] [node name="Cubes" parent="." instance=ExtResource("2")]
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="Help" type="Label" parent="."] [node name="Help" type="Label" parent="."]
anchors_preset = 2 layout_mode = 0
anchor_top = 1.0 anchor_top = 1.0
anchor_bottom = 1.0 anchor_bottom = 1.0
offset_left = 16.0 offset_left = 16.0
offset_top = -106.0 offset_top = -106.0
offset_right = 554.0 offset_right = 554.0
offset_bottom = -16.0 offset_bottom = -16.0
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
theme_override_constants/outline_size = 4
text = "This text will always render at the native resolution. text = "This text will always render at the native resolution.
Press Space to adjust the 3D viewport's resolution scaling. Press Space to adjust the 3D viewport's resolution scaling.
Press Enter to toggle filtering." Press Enter to cycle filtering modes."
[node name="VBoxContainer" type="VBoxContainer" parent="."] [node name="VBoxContainer" type="VBoxContainer" parent="."]
layout_mode = 0
offset_left = 16.0 offset_left = 16.0
offset_top = 16.0 offset_top = 16.0
offset_right = 124.0 offset_right = 124.0
offset_bottom = 76.0 offset_bottom = 76.0
[node name="Scale" type="Label" parent="VBoxContainer"] [node name="Scale" type="Label" parent="VBoxContainer"]
offset_right = 111.0 layout_mode = 2
offset_bottom = 26.0 theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
theme_override_constants/outline_size = 4
text = "Scale: 100%" text = "Scale: 100%"
[node name="Filter" type="Label" parent="VBoxContainer"] [node name="Filter" type="Label" parent="VBoxContainer"]
offset_top = 30.0 layout_mode = 2
offset_right = 111.0 theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
offset_bottom = 56.0 theme_override_constants/outline_size = 4
text = "Filter: Enabled" text = "Scaling 3D Mode: Bilinear"

View File

@@ -18,7 +18,7 @@ be used to have a \"pixel art\" viewport for the main game area and a
non-pixel-art viewport for HUD elements." non-pixel-art viewport for HUD elements."
config/tags=PackedStringArray("3d", "demo", "official", "rendering") config/tags=PackedStringArray("3d", "demo", "official", "rendering")
run/main_scene="res://hud.tscn" run/main_scene="res://hud.tscn"
config/features=PackedStringArray("4.2") config/features=PackedStringArray("4.3")
config/icon="res://icon.webp" config/icon="res://icon.webp"
[display] [display]
@@ -30,15 +30,15 @@ window/stretch/aspect="expand"
cycle_viewport_resolution={ cycle_viewport_resolution={
"deadzone": 0.5, "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,"key_label":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,"location":0,"echo":false,"script":null)
] ]
} }
toggle_filtering={ toggle_filtering={
"deadzone": 0.5, "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,"key_label":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,"location":0,"echo":false,"script":null)
] ]
} }
[rendering] [rendering]
environment/defaults/default_environment="res://default_env.tres" textures/default_filters/anisotropic_filtering_level=4

Binary file not shown.

After

Width:  |  Height:  |  Size: 322 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB