瀏覽代碼

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.
Hugo Locurcio 4 年之前
父節點
當前提交
73c6e19acc

+ 4 - 3
doc/classes/ProjectSettings.xml

@@ -1479,11 +1479,12 @@
 		</member>
 		<member name="rendering/2d/snap/snap_2d_vertices_to_pixel" type="bool" setter="" getter="" default="false">
 		</member>
-		<member name="rendering/3d/viewport/scale" type="int" setter="" getter="" default="0">
-			Scale the 3D render buffer based on the viewport size. The smaller the faster 3D rendering is performed but at the cost of quality.
+		<member name="rendering/3d/viewport/scale" type="float" setter="" getter="" default="1.0">
+			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.
 		</member>
 		<member name="rendering/anti_aliasing/quality/msaa" type="int" setter="" getter="" default="0">
-			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.
 		</member>
 		<member name="rendering/anti_aliasing/quality/screen_space_aa" type="int" setter="" getter="" default="0">
 			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.

+ 1 - 11
doc/classes/RenderingServer.xml

@@ -3102,7 +3102,7 @@
 		<method name="viewport_set_scale_3d">
 			<return type="void" />
 			<argument index="0" name="viewport" type="RID" />
-			<argument index="1" name="scale" type="int" enum="RenderingServer.ViewportScale3D" />
+			<argument index="1" name="scale" type="float" />
 			<description>
 				Sets the scale at which we render 3D contents.
 			</description>
@@ -3918,16 +3918,6 @@
 		</constant>
 		<constant name="VIEWPORT_DEBUG_DRAW_OCCLUDERS" value="23" enum="ViewportDebugDraw">
 		</constant>
-		<constant name="VIEWPORT_SCALE_3D_DISABLED" value="0" enum="ViewportScale3D">
-		</constant>
-		<constant name="VIEWPORT_SCALE_3D_75_PERCENT" value="1" enum="ViewportScale3D">
-		</constant>
-		<constant name="VIEWPORT_SCALE_3D_50_PERCENT" value="2" enum="ViewportScale3D">
-		</constant>
-		<constant name="VIEWPORT_SCALE_3D_33_PERCENT" value="3" enum="ViewportScale3D">
-		</constant>
-		<constant name="VIEWPORT_SCALE_3D_25_PERCENT" value="4" enum="ViewportScale3D">
-		</constant>
 		<constant name="SKY_MODE_AUTOMATIC" value="0" enum="SkyMode">
 		</constant>
 		<constant name="SKY_MODE_QUALITY" value="1" enum="SkyMode">

+ 4 - 13
doc/classes/Viewport.xml

@@ -204,7 +204,7 @@
 		<member name="lod_threshold" type="float" setter="set_lod_threshold" getter="get_lod_threshold" default="1.0">
 		</member>
 		<member name="msaa" type="int" setter="set_msaa" getter="get_msaa" enum="Viewport.MSAA" default="0">
-			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.
 		</member>
 		<member name="own_world_3d" type="bool" setter="set_use_own_world_3d" getter="is_using_own_world_3d" default="false">
 			If [code]true[/code], the viewport will use the [World3D] defined in [member world_3d].
@@ -212,8 +212,9 @@
 		<member name="physics_object_picking" type="bool" setter="set_physics_object_picking" getter="get_physics_object_picking" default="false">
 			If [code]true[/code], the objects rendered by viewport become subjects of mouse picking process.
 		</member>
-		<member name="scale_3d" type="int" setter="set_scale_3d" getter="get_scale_3d" enum="Viewport.Scale3D" default="0">
-			The scale at which 3D content is rendered.
+		<member name="scale_3d" type="float" setter="set_scale_3d" getter="get_scale_3d" default="1.0">
+			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.
 		</member>
 		<member name="screen_space_aa" type="int" setter="set_screen_space_aa" getter="get_screen_space_aa" enum="Viewport.ScreenSpaceAA" default="0">
 			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 @@
 		</signal>
 	</signals>
 	<constants>
-		<constant name="SCALE_3D_DISABLED" value="0" enum="Scale3D">
-		</constant>
-		<constant name="SCALE_3D_75_PERCENT" value="1" enum="Scale3D">
-		</constant>
-		<constant name="SCALE_3D_50_PERCENT" value="2" enum="Scale3D">
-		</constant>
-		<constant name="SCALE_3D_33_PERCENT" value="3" enum="Scale3D">
-		</constant>
-		<constant name="SCALE_3D_25_PERCENT" value="4" enum="Scale3D">
-		</constant>
 		<constant name="SHADOW_ATLAS_QUADRANT_SUBDIV_DISABLED" value="0" enum="ShadowAtlasQuadrantSubdiv">
 			This quadrant will not be used.
 		</constant>

+ 9 - 13
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.

+ 3 - 12
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 @@ public:
 
 #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<AudioListener3D *> audio_listener_3d_set;
@@ -664,8 +656,8 @@ public:
 	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);

+ 15 - 28
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);
 }
 

+ 2 - 2
servers/rendering/renderer_viewport.h

@@ -49,7 +49,7 @@ public:
 
 		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 @@ public:
 	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);
 

+ 1 - 1
servers/rendering/rendering_server_default.h

@@ -526,7 +526,7 @@ public:
 	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)

+ 3 - 9
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);

+ 1 - 11
servers/rendering_server.h

@@ -752,19 +752,10 @@ public:
 		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);