From 73c6e19acc69b7367c4fa67cd4377e2207faf898 Mon Sep 17 00:00:00 2001 From: Hugo Locurcio Date: Sun, 29 Aug 2021 14:44:09 +0200 Subject: [PATCH] Allow any floating-point value as a 3D rendering scale option This allows for finer control over 3D rendering resolution. Supersampling can also be performed by setting a 3D rendering resolution above 1.0, which is useful for offline rendering or for very high-end GPUs. --- doc/classes/ProjectSettings.xml | 7 ++-- doc/classes/RenderingServer.xml | 12 +----- doc/classes/Viewport.xml | 17 ++------ scene/main/viewport.cpp | 22 ++++------ scene/main/viewport.h | 15 ++----- servers/rendering/renderer_viewport.cpp | 43 +++++++------------- servers/rendering/renderer_viewport.h | 4 +- servers/rendering/rendering_server_default.h | 2 +- servers/rendering_server.cpp | 12 ++---- servers/rendering_server.h | 12 +----- 10 files changed, 43 insertions(+), 103 deletions(-) diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index b3872121bfa0..5403bd48d564 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -1479,11 +1479,12 @@ - - Scale the 3D render buffer based on the viewport size. The smaller the faster 3D rendering is performed but at the cost of quality. + + Scales the 3D render buffer based on the viewport size and displays the result with linear filtering. Values lower than [code]1.0[/code] can be used to speed up 3D rendering at the cost of quality (undersampling). Values greater than [code]1.0[/code] can be used to improve 3D rendering quality at a high performance cost (supersampling). See also [member rendering/anti_aliasing/quality/msaa] for multi-sample antialiasing, which is significantly cheaper but only smoothens the edges of polygons. + [b]Note:[/b] This property is only read when the project starts. To change the 3D rendering resolution scale at runtime, set [member Viewport.scale_3d] instead. - Sets the number of MSAA samples to use (as a power of two). MSAA is used to reduce aliasing around the edges of polygons. A higher MSAA value results in smoother edges but can be significantly slower on some hardware. + Sets the number of MSAA samples to use (as a power of two). MSAA is used to reduce aliasing around the edges of polygons. A higher MSAA value results in smoother edges but can be significantly slower on some hardware. See also [member rendering/3d/viewport/scale] for supersampling, which provides higher quality but is much more expensive. Sets the screen-space antialiasing mode for the default screen [Viewport]. Screen-space antialiasing works by selectively blurring edges in a post-process shader. It differs from MSAA which takes multiple coverage samples while rendering objects. Screen-space AA methods are typically faster than MSAA and will smooth out specular aliasing, but tend to make scenes appear blurry. diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml index 65b7e53ecdd3..6f19114c16a1 100644 --- a/doc/classes/RenderingServer.xml +++ b/doc/classes/RenderingServer.xml @@ -3102,7 +3102,7 @@ - + Sets the scale at which we render 3D contents. @@ -3918,16 +3918,6 @@ - - - - - - - - - - diff --git a/doc/classes/Viewport.xml b/doc/classes/Viewport.xml index cdb9e7632be8..e79cf0d23347 100644 --- a/doc/classes/Viewport.xml +++ b/doc/classes/Viewport.xml @@ -204,7 +204,7 @@ - The multisample anti-aliasing mode. A higher number results in smoother edges at the cost of significantly worse performance. A value of 4 is best unless targeting very high-end systems. + The multisample anti-aliasing mode. A higher number results in smoother edges at the cost of significantly worse performance. A value of 2 or 4 is best unless targeting very high-end systems. See also [member scale_3d] for supersampling, which provides higher quality but is much more expensive. If [code]true[/code], the viewport will use the [World3D] defined in [member world_3d]. @@ -212,8 +212,9 @@ If [code]true[/code], the objects rendered by viewport become subjects of mouse picking process. - - The scale at which 3D content is rendered. + + Scales the 3D render buffer based on the viewport size and displays the result with linear filtering. Values lower than [code]1.0[/code] can be used to speed up 3D rendering at the cost of quality (undersampling). Values greater than [code]1.0[/code] can be used to improve 3D rendering quality at a high performance cost (supersampling). See also [member msaa] for multi-sample antialiasing, which is significantly cheaper but only smoothens the edges of polygons. + To control this property on the root viewport, set the [member ProjectSettings.rendering/3d/viewport/scale] project setting. Sets the screen-space antialiasing method used. Screen-space antialiasing works by selectively blurring edges in a post-process shader. It differs from MSAA which takes multiple coverage samples while rendering objects. Screen-space AA methods are typically faster than MSAA and will smooth out specular aliasing, but tend to make scenes appear blurry. @@ -275,16 +276,6 @@ - - - - - - - - - - This quadrant will not be used. diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index e88bb3b952b1..3ab6e12e01c9 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -3443,13 +3443,16 @@ bool Viewport::is_using_xr() { return use_xr; } -void Viewport::set_scale_3d(const Scale3D p_scale_3d) { - scale_3d = p_scale_3d; +void Viewport::set_scale_3d(float p_scale_3d) { + // Clamp to reasonable values that are actually useful. + // Values above 2.0 don't serve a practical purpose since the viewport + // isn't displayed with mipmaps. + scale_3d = CLAMP(p_scale_3d, 0.1, 2.0); - RS::get_singleton()->viewport_set_scale_3d(viewport, RS::ViewportScale3D(scale_3d)); + RS::get_singleton()->viewport_set_scale_3d(viewport, scale_3d); } -Viewport::Scale3D Viewport::get_scale_3d() const { +float Viewport::get_scale_3d() const { return scale_3d; } @@ -3582,7 +3585,7 @@ void Viewport::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disable_3d"), "set_disable_3d", "is_3d_disabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_xr"), "set_use_xr", "is_using_xr"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "scale_3d", PROPERTY_HINT_ENUM, String::utf8("Disabled,75%,50%,33%,25%")), "set_scale_3d", "get_scale_3d"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "scale_3d", PROPERTY_HINT_RANGE, "0.25,2.0,0.01"), "set_scale_3d", "get_scale_3d"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "audio_listener_enable_3d"), "set_as_audio_listener_3d", "is_audio_listener_3d"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "own_world_3d"), "set_use_own_world_3d", "is_using_own_world_3d"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "world_3d", PROPERTY_HINT_RESOURCE_TYPE, "World3D"), "set_world_3d", "get_world_3d"); @@ -3626,12 +3629,6 @@ void Viewport::_bind_methods() { ADD_SIGNAL(MethodInfo("size_changed")); ADD_SIGNAL(MethodInfo("gui_focus_changed", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Control"))); - BIND_ENUM_CONSTANT(SCALE_3D_DISABLED); - BIND_ENUM_CONSTANT(SCALE_3D_75_PERCENT); - BIND_ENUM_CONSTANT(SCALE_3D_50_PERCENT); - BIND_ENUM_CONSTANT(SCALE_3D_33_PERCENT); - BIND_ENUM_CONSTANT(SCALE_3D_25_PERCENT); - BIND_ENUM_CONSTANT(SHADOW_ATLAS_QUADRANT_SUBDIV_DISABLED); BIND_ENUM_CONSTANT(SHADOW_ATLAS_QUADRANT_SUBDIV_1); BIND_ENUM_CONSTANT(SHADOW_ATLAS_QUADRANT_SUBDIV_4); @@ -3744,8 +3741,7 @@ Viewport::Viewport() { ProjectSettings::get_singleton()->set_custom_property_info("gui/timers/tooltip_delay_sec", PropertyInfo(Variant::FLOAT, "gui/timers/tooltip_delay_sec", PROPERTY_HINT_RANGE, "0,5,0.01,or_greater")); // No negative numbers #ifndef _3D_DISABLED - int scale = GLOBAL_GET("rendering/3d/viewport/scale"); - set_scale_3d((Scale3D)scale); + set_scale_3d(GLOBAL_GET("rendering/3d/viewport/scale")); #endif // _3D_DISABLED set_sdf_oversize(sdf_oversize); // Set to server. diff --git a/scene/main/viewport.h b/scene/main/viewport.h index 3732f9cfd182..1f19ff04c9b9 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -89,14 +89,6 @@ class Viewport : public Node { GDCLASS(Viewport, Node); public: - enum Scale3D { - SCALE_3D_DISABLED, - SCALE_3D_75_PERCENT, - SCALE_3D_50_PERCENT, - SCALE_3D_33_PERCENT, - SCALE_3D_25_PERCENT - }; - enum ShadowAtlasQuadrantSubdiv { SHADOW_ATLAS_QUADRANT_SUBDIV_DISABLED, SHADOW_ATLAS_QUADRANT_SUBDIV_1, @@ -592,7 +584,7 @@ class Viewport : public Node { #ifndef _3D_DISABLED bool use_xr = false; - Scale3D scale_3d = SCALE_3D_DISABLED; + float scale_3d = 1.0; friend class AudioListener3D; AudioListener3D *audio_listener_3d = nullptr; Set audio_listener_3d_set; @@ -664,8 +656,8 @@ class Viewport : public Node { void set_use_xr(bool p_use_xr); bool is_using_xr(); - void set_scale_3d(const Scale3D p_scale_3d); - Scale3D get_scale_3d() const; + void set_scale_3d(float p_scale_3d); + float get_scale_3d() const; #endif // _3D_DISABLED Viewport(); @@ -724,7 +716,6 @@ VARIANT_ENUM_CAST(SubViewport::UpdateMode); VARIANT_ENUM_CAST(Viewport::ShadowAtlasQuadrantSubdiv); VARIANT_ENUM_CAST(Viewport::MSAA); VARIANT_ENUM_CAST(Viewport::ScreenSpaceAA); -VARIANT_ENUM_CAST(Viewport::Scale3D); VARIANT_ENUM_CAST(Viewport::DebugDraw); VARIANT_ENUM_CAST(Viewport::SDFScale); VARIANT_ENUM_CAST(Viewport::SDFOversize); diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp index 74f18b1da534..b67b1cd80614 100644 --- a/servers/rendering/renderer_viewport.cpp +++ b/servers/rendering/renderer_viewport.cpp @@ -77,33 +77,17 @@ void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) { RSG::scene->free(p_viewport->render_buffers); p_viewport->render_buffers = RID(); } else { - RS::ViewportScale3D scale_3d = p_viewport->scale_3d; - if (Engine::get_singleton()->is_editor_hint()) { // ignore this inside of the editor - scale_3d = RS::VIEWPORT_SCALE_3D_DISABLED; + float scale_3d = p_viewport->scale_3d; + if (Engine::get_singleton()->is_editor_hint()) { + // Ignore the 3D viewport render scaling inside of the editor. + // The Half Resolution 3D editor viewport option should be used instead. + scale_3d = 1.0; } - int width = p_viewport->size.width; - int height = p_viewport->size.height; - switch (scale_3d) { - case RS::VIEWPORT_SCALE_3D_75_PERCENT: { - width = (width * 3) / 4; - height = (height * 3) / 4; - }; break; - case RS::VIEWPORT_SCALE_3D_50_PERCENT: { - width = width >> 1; - height = height >> 1; - }; break; - case RS::VIEWPORT_SCALE_3D_33_PERCENT: { - width = width / 3; - height = height / 3; - }; break; - case RS::VIEWPORT_SCALE_3D_25_PERCENT: { - width = width >> 2; - height = height >> 2; - }; break; - default: - break; - } + // Clamp 3D rendering resolution to reasonable values supported on most hardware. + // This prevents freezing the engine or outright crashing on lower-end GPUs. + const int width = CLAMP(p_viewport->size.width * scale_3d, 1, 16384); + const int height = CLAMP(p_viewport->size.height * scale_3d, 1, 16384); RSG::scene->render_buffers_configure(p_viewport->render_buffers, p_viewport->render_target, width, height, p_viewport->msaa, p_viewport->screen_space_aa, p_viewport->use_debanding, p_viewport->get_view_count()); } } @@ -690,15 +674,18 @@ void RendererViewport::viewport_set_use_xr(RID p_viewport, bool p_use_xr) { _configure_3d_render_buffers(viewport); } -void RendererViewport::viewport_set_scale_3d(RID p_viewport, RenderingServer::ViewportScale3D p_scale_3d) { +void RendererViewport::viewport_set_scale_3d(RID p_viewport, float p_scale_3d) { Viewport *viewport = viewport_owner.get_or_null(p_viewport); ERR_FAIL_COND(!viewport); - if (viewport->scale_3d == p_scale_3d) { + // Clamp to reasonable values that are actually useful. + // Values above 2.0 don't serve a practical purpose since the viewport + // isn't displayed with mipmaps. + if (viewport->scale_3d == CLAMP(p_scale_3d, 0.1, 2.0)) { return; } - viewport->scale_3d = p_scale_3d; + viewport->scale_3d = CLAMP(p_scale_3d, 0.1, 2.0); _configure_3d_render_buffers(viewport); } diff --git a/servers/rendering/renderer_viewport.h b/servers/rendering/renderer_viewport.h index 41d818cf990a..f6e6cc8e8421 100644 --- a/servers/rendering/renderer_viewport.h +++ b/servers/rendering/renderer_viewport.h @@ -49,7 +49,7 @@ class RendererViewport { bool use_xr; /* use xr interface to override camera positioning and projection matrices and control output */ - RS::ViewportScale3D scale_3d = RenderingServer::VIEWPORT_SCALE_3D_DISABLED; + float scale_3d = 1.0; Size2i size; RID camera; @@ -207,7 +207,7 @@ class RendererViewport { void viewport_initialize(RID p_rid); void viewport_set_use_xr(RID p_viewport, bool p_use_xr); - void viewport_set_scale_3d(RID p_viewport, RenderingServer::ViewportScale3D p_scale_3d); + void viewport_set_scale_3d(RID p_viewport, float p_scale_3d); void viewport_set_size(RID p_viewport, int p_width, int p_height); diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h index 49ade3c6a15e..911d4c463bad 100644 --- a/servers/rendering/rendering_server_default.h +++ b/servers/rendering/rendering_server_default.h @@ -526,7 +526,7 @@ class RenderingServerDefault : public RenderingServer { FUNCRIDSPLIT(viewport) FUNC2(viewport_set_use_xr, RID, bool) - FUNC2(viewport_set_scale_3d, RID, ViewportScale3D) + FUNC2(viewport_set_scale_3d, RID, float) FUNC3(viewport_set_size, RID, int, int) FUNC2(viewport_set_active, RID, bool) diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index 93919a5ec620..7e66ddbb0f56 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -2269,12 +2269,6 @@ void RenderingServer::_bind_methods() { BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_CLUSTER_REFLECTION_PROBES); BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_OCCLUDERS); - BIND_ENUM_CONSTANT(VIEWPORT_SCALE_3D_DISABLED); - BIND_ENUM_CONSTANT(VIEWPORT_SCALE_3D_75_PERCENT); - BIND_ENUM_CONSTANT(VIEWPORT_SCALE_3D_50_PERCENT); - BIND_ENUM_CONSTANT(VIEWPORT_SCALE_3D_33_PERCENT); - BIND_ENUM_CONSTANT(VIEWPORT_SCALE_3D_25_PERCENT); - /* SKY API */ ClassDB::bind_method(D_METHOD("sky_create"), &RenderingServer::sky_create); @@ -2817,11 +2811,11 @@ RenderingServer::RenderingServer() { "rendering/vulkan/rendering/back_end", PROPERTY_HINT_ENUM, "Forward Clustered (Supports Desktop Only),Forward Mobile (Supports Desktop and Mobile)")); - GLOBAL_DEF("rendering/3d/viewport/scale", 0); + GLOBAL_DEF("rendering/3d/viewport/scale", 1.0); ProjectSettings::get_singleton()->set_custom_property_info("rendering/3d/viewport/scale", - PropertyInfo(Variant::INT, + PropertyInfo(Variant::FLOAT, "rendering/3d/viewport/scale", - PROPERTY_HINT_ENUM, "Disabled,75%,50%,33%,25%")); + PROPERTY_HINT_RANGE, "0.25,2.0,0.01")); GLOBAL_DEF("rendering/shader_compiler/shader_cache/enabled", true); GLOBAL_DEF("rendering/shader_compiler/shader_cache/compress", true); diff --git a/servers/rendering_server.h b/servers/rendering_server.h index 2dffa6bc75e6..b50da66d0317 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -752,19 +752,10 @@ class RenderingServer : public Object { CANVAS_ITEM_TEXTURE_REPEAT_MAX, }; - enum ViewportScale3D { - VIEWPORT_SCALE_3D_DISABLED, - VIEWPORT_SCALE_3D_75_PERCENT, - VIEWPORT_SCALE_3D_50_PERCENT, - VIEWPORT_SCALE_3D_33_PERCENT, - VIEWPORT_SCALE_3D_25_PERCENT, - VIEWPORT_SCALE_3D_MAX, - }; - virtual RID viewport_create() = 0; virtual void viewport_set_use_xr(RID p_viewport, bool p_use_xr) = 0; - virtual void viewport_set_scale_3d(RID p_viewport, ViewportScale3D p_scale_3d) = 0; + virtual void viewport_set_scale_3d(RID p_viewport, float p_scale_3d) = 0; virtual void viewport_set_size(RID p_viewport, int p_width, int p_height) = 0; virtual void viewport_set_active(RID p_viewport, bool p_active) = 0; virtual void viewport_set_parent_viewport(RID p_viewport, RID p_parent_viewport) = 0; @@ -1553,7 +1544,6 @@ VARIANT_ENUM_CAST(RenderingServer::ViewportDebugDraw); VARIANT_ENUM_CAST(RenderingServer::ViewportOcclusionCullingBuildQuality); VARIANT_ENUM_CAST(RenderingServer::ViewportSDFOversize); VARIANT_ENUM_CAST(RenderingServer::ViewportSDFScale); -VARIANT_ENUM_CAST(RenderingServer::ViewportScale3D); VARIANT_ENUM_CAST(RenderingServer::SkyMode); VARIANT_ENUM_CAST(RenderingServer::EnvironmentBG); VARIANT_ENUM_CAST(RenderingServer::EnvironmentAmbientSource);