diff --git a/viewport/3d_scaling/README.md b/viewport/3d_scaling/README.md new file mode 100644 index 00000000..c89ba8c3 --- /dev/null +++ b/viewport/3d_scaling/README.md @@ -0,0 +1,11 @@ +# 3D 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 by using TextureRect to display the ViewportTexture +delivered by the Viewport node. 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. + +ViewportContainer can also be used to display a viewport in a GUI, but it +doesn't offer the ability to enable filtering. diff --git a/viewport/3d_scaling/default_env.tres b/viewport/3d_scaling/default_env.tres new file mode 100644 index 00000000..d1e6d466 --- /dev/null +++ b/viewport/3d_scaling/default_env.tres @@ -0,0 +1,9 @@ +[gd_resource type="Environment" load_steps=2 format=2] + +[sub_resource type="ProceduralSky" id=1] +sky_top_color = Color( 0.207843, 0.239216, 0.254902, 1 ) +sky_horizon_color = Color( 0.466667, 0.478431, 0.490196, 1 ) + +[resource] +background_mode = 2 +background_sky = SubResource( 1 ) diff --git a/viewport/3d_scaling/hud.gd b/viewport/3d_scaling/hud.gd new file mode 100644 index 00000000..5da8a58f --- /dev/null +++ b/viewport/3d_scaling/hud.gd @@ -0,0 +1,42 @@ +extends Control + +# The viewport is displayed using a TextureRect node instead of a ViewportContainer. +# This allows filtering the texture that's displayed in the root viewport. + +# 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 this to work. +var scale_factor = 1.0 + +onready var texture_rect = $TextureRect +onready var viewport = $TextureRect/Viewport +onready var scale_label = $VBoxContainer/Scale +onready var filter_label = $VBoxContainer/Filter + +func _ready(): + # Required to change the 3D viewport's size when the window is resized. + # warning-ignore:return_value_discarded + get_viewport().connect("size_changed", self, "_root_viewport_size_changed") + + +func _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) + + if event.is_action_pressed("toggle_filtering"): + # Toggle the Filter flag on the ViewportTexture. + texture_rect.texture.flags ^= ImageTexture.FLAG_FILTER + + var filter_enabled = texture_rect.texture.flags & ImageTexture.FLAG_FILTER + filter_label.text = "Filter: %s" % ("Enabled" if filter_enabled else "Disabled") + + +# 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 diff --git a/viewport/3d_scaling/hud.tscn b/viewport/3d_scaling/hud.tscn new file mode 100644 index 00000000..6720e34c --- /dev/null +++ b/viewport/3d_scaling/hud.tscn @@ -0,0 +1,104 @@ +[gd_scene load_steps=7 format=2] + +[ext_resource path="res://noto_sans_ui_regular.ttf" type="DynamicFontData" id=1] +[ext_resource path="res://spatial.tscn" type="PackedScene" id=2] +[ext_resource path="res://hud.gd" type="Script" id=3] + +[sub_resource type="DynamicFont" id=1] +size = 20 +font_data = ExtResource( 1 ) + +[sub_resource type="Theme" id=2] +default_font = SubResource( 1 ) + +[sub_resource type="ViewportTexture" id=3] +viewport_path = NodePath("TextureRect/Viewport") + +[node name="HUD" type="Control"] +anchor_right = 1.0 +anchor_bottom = 1.0 +theme = SubResource( 2 ) +script = ExtResource( 3 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="TextureRect" type="TextureRect" parent="."] +anchor_right = 1.0 +anchor_bottom = 1.0 +texture = SubResource( 3 ) +expand = true +flip_v = true +__meta__ = { +"_edit_use_anchors_": false, +"_editor_description_": "" +} + +[node name="Viewport" type="Viewport" parent="TextureRect"] +size = Vector2( 1024, 600 ) +handle_input_locally = false +usage = 3 +render_target_update_mode = 3 +shadow_atlas_size = 4096 + +[node name="Spatial" parent="TextureRect/Viewport" instance=ExtResource( 2 )] + +[node name="ViewportContainer" type="ViewportContainer" parent="."] +anchor_right = 1.0 +anchor_bottom = 1.0 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="Help" type="Label" parent="."] +anchor_top = 1.0 +anchor_bottom = 1.0 +margin_left = 16.0 +margin_top = -106.0 +margin_right = 554.0 +margin_bottom = -16.0 +custom_fonts/font = SubResource( 1 ) +custom_colors/font_color_shadow = Color( 0, 0, 0, 0.752941 ) +custom_constants/shadow_offset_x = 2 +custom_constants/shadow_offset_y = 2 +custom_constants/shadow_as_outline = 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." +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="VBoxContainer" type="VBoxContainer" parent="."] +margin_left = 16.0 +margin_top = 16.0 +margin_right = 124.0 +margin_bottom = 76.0 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="Scale" type="Label" parent="VBoxContainer"] +margin_right = 137.0 +margin_bottom = 28.0 +custom_colors/font_color_shadow = Color( 0, 0, 0, 0.752941 ) +custom_constants/shadow_offset_x = 2 +custom_constants/shadow_offset_y = 2 +custom_constants/shadow_as_outline = 0 +text = "Scale: 100%" +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="Filter" type="Label" parent="VBoxContainer"] +margin_top = 32.0 +margin_right = 137.0 +margin_bottom = 60.0 +custom_colors/font_color_shadow = Color( 0, 0, 0, 0.752941 ) +custom_constants/shadow_offset_x = 2 +custom_constants/shadow_offset_y = 2 +custom_constants/shadow_as_outline = 0 +text = "Filter: Disabled" +__meta__ = { +"_edit_use_anchors_": false +} diff --git a/viewport/3d_scaling/icon.png b/viewport/3d_scaling/icon.png new file mode 100644 index 00000000..257d8524 Binary files /dev/null and b/viewport/3d_scaling/icon.png differ diff --git a/viewport/3d_scaling/icon.png.import b/viewport/3d_scaling/icon.png.import new file mode 100644 index 00000000..96cbf462 --- /dev/null +++ b/viewport/3d_scaling/icon.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://icon.png" +dest_files=[ "res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/viewport/3d_scaling/noto_sans_ui_regular.ttf b/viewport/3d_scaling/noto_sans_ui_regular.ttf new file mode 100644 index 00000000..65b29fcf Binary files /dev/null and b/viewport/3d_scaling/noto_sans_ui_regular.ttf differ diff --git a/viewport/3d_scaling/project.godot b/viewport/3d_scaling/project.godot new file mode 100644 index 00000000..0c407cef --- /dev/null +++ b/viewport/3d_scaling/project.godot @@ -0,0 +1,43 @@ +; Engine configuration file. +; It's best edited using the editor UI and not directly, +; since the parameters that go here are not all obvious. +; +; Format: +; [section] ; section goes between [] +; param=value ; assign values to parameters + +config_version=4 + +_global_script_classes=[ ] +_global_script_class_icons={ + +} + +[application] + +config/name="3D Viewport Scaling" +run/main_scene="res://hud.tscn" +config/icon="res://icon.png" + +[display] + +window/stretch/mode="2d" +window/stretch/aspect="expand" + +[input] + +cycle_viewport_resolution={ +"deadzone": 0.5, +"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":32,"unicode":0,"echo":false,"script":null) + ] +} +toggle_filtering={ +"deadzone": 0.5, +"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777221,"unicode":0,"echo":false,"script":null) + ] +} + +[rendering] + +quality/intended_usage/framebuffer_allocation=3 +environment/default_environment="res://default_env.tres" diff --git a/viewport/3d_scaling/spatial.tscn b/viewport/3d_scaling/spatial.tscn new file mode 100644 index 00000000..fe1b8edf --- /dev/null +++ b/viewport/3d_scaling/spatial.tscn @@ -0,0 +1,23 @@ +[gd_scene load_steps=2 format=2] + +[sub_resource type="CubeMesh" id=1] + +[node name="Spatial" type="Spatial"] + +[node name="MeshInstance" type="MeshInstance" parent="."] +mesh = SubResource( 1 ) +material/0 = null + +[node name="MeshInstance2" type="MeshInstance" parent="."] +transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, -1 ) +mesh = SubResource( 1 ) +material/0 = null + +[node name="Camera" type="Camera" parent="."] +transform = Transform( 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="OmniLight" type="OmniLight" parent="."] +transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0.3, 2, 1 ) +shadow_enabled = true +shadow_bias = 0.08