Skip to content

Commit

Permalink
Add support for contrast-adaptive sharpening in 3D
Browse files Browse the repository at this point in the history
This is an older, easier to implement variant of CAS as a pure fragment
shader. It doesn't support upscaling, but the upscaling part of CAS
has been superseded by FSR 1.0 anyway.

The sharpening intensity can be adjusted on a per-Viewport basis.
For the root viewport, it can be adjusted in the Project Settings.
  • Loading branch information
Calinou committed Jun 17, 2022
1 parent 4463dd9 commit 9d97caa
Show file tree
Hide file tree
Showing 23 changed files with 145 additions and 12 deletions.
7 changes: 5 additions & 2 deletions doc/classes/ProjectSettings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1591,10 +1591,13 @@
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 bilinear scaling 3d [member rendering/scaling_3d/mode] 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.
Another way to combat specular aliasing is to enable [member rendering/anti_aliasing/screen_space_roughness_limiter/enabled].
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. Some of the lost sharpness can be recovered by enabling contrast-adaptive sharpening (see [member rendering/anti_aliasing/quality/sharpen_intensity]).
</member>
<member name="rendering/anti_aliasing/quality/sharpen_intensity" type="float" setter="" getter="" default="0.0">
If set to a value greater than [code]0.0[/code], contrast-adaptive sharpening will be applied to the 3D viewport. This has a small GPU performance cost and can be used to recover some of the sharpness lost due to screen-space antialiasing. Values around [code]0.5[/code] generally give the best results. See also [member rendering/anti_aliasing/quality/screen_space_aa].
</member>
<member name="rendering/anti_aliasing/quality/use_debanding" type="bool" setter="" getter="" default="false">
If [code]true[/code], uses a fast post-processing filter to make banding significantly less visible. In some cases, debanding may introduce a slightly noticeable dithering pattern. It's recommended to enable debanding only when actually needed since the dithering pattern will make lossless-compressed screenshots larger.
</member>
<member name="rendering/anti_aliasing/quality/use_taa" type="bool" setter="" getter="" default="false">
Enables Temporal Anti-Aliasing for the default screen [Viewport]. TAA works by jittering the camera and accumulating the images of the last rendered frames, motion vector rendering is used to account for camera and object motion.
Expand Down
8 changes: 8 additions & 0 deletions doc/classes/RenderingServer.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3287,6 +3287,14 @@
Sets the size of the shadow atlas's images (used for omni and spot lights). The value will be rounded up to the nearest power of 2.
</description>
</method>
<method name="viewport_set_sharpen_intensity">
<return type="void" />
<argument index="0" name="viewport" type="RID" />
<argument index="1" name="intensity" type="float" />
<description>
Sets the sharpening [code]intensity[/code] for the [code]viewport[/code]. If set to a value greater than [code]0.0[/code], contrast-adaptive sharpening will be applied to the 3D viewport. This has a small GPU performance cost and can be used to recover some of the sharpness lost due to screen-space antialiasing. Values around [code]0.5[/code] generally give the best results.
</description>
</method>
<method name="viewport_set_size">
<return type="void" />
<argument index="0" name="viewport" type="RID" />
Expand Down
5 changes: 4 additions & 1 deletion doc/classes/Viewport.xml
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@
To control this property on the root viewport, set the [member ProjectSettings.rendering/scaling_3d/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.
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. Some of the lost sharpness can be recovered by enabling contrast-adaptive sharpening (see [member sharpen_intensity]).
</member>
<member name="sdf_oversize" type="int" setter="set_sdf_oversize" getter="get_sdf_oversize" enum="Viewport.SDFOversize" default="1">
</member>
Expand All @@ -266,6 +266,9 @@
The shadow atlas' resolution (used for omni and spot lights). The value will be rounded up to the nearest power of 2.
[b]Note:[/b] If this is set to 0, shadows won't be visible.
</member>
<member name="sharpen_intensity" type="float" setter="set_sharpen_intensity" getter="get_sharpen_intensity" default="0.0">
If set to a value greater than [code]0.0[/code], contrast-adaptive sharpening will be applied to the 3D viewport. This has a small GPU performance cost and can be used to recover some of the sharpness lost due to screen-space antialiasing. Values around [code]0.5[/code] generally give the best results. See also [member screen_space_aa].
</member>
<member name="snap_2d_transforms_to_pixel" type="bool" setter="set_snap_2d_transforms_to_pixel" getter="is_snap_2d_transforms_to_pixel_enabled" default="false">
</member>
<member name="snap_2d_vertices_to_pixel" type="bool" setter="set_snap_2d_vertices_to_pixel" getter="is_snap_2d_vertices_to_pixel_enabled" default="false">
Expand Down
2 changes: 1 addition & 1 deletion drivers/gles3/rasterizer_scene_gles3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2507,7 +2507,7 @@ RID RasterizerSceneGLES3::render_buffers_create() {
return render_buffers_owner.make_rid(rb);
}

void RasterizerSceneGLES3::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) {
void RasterizerSceneGLES3::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, float p_sharpen_intensity, uint32_t p_view_count) {
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();

RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
Expand Down
2 changes: 1 addition & 1 deletion drivers/gles3/rasterizer_scene_gles3.h
Original file line number Diff line number Diff line change
Expand Up @@ -923,7 +923,7 @@ class RasterizerSceneGLES3 : public RendererSceneRender {
}

RID render_buffers_create() override;
void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override;
void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, float p_sharpen_intensity, uint32_t p_view_count) override;
void gi_set_use_half_resolution(bool p_enable) override;

void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_curve) override;
Expand Down
2 changes: 2 additions & 0 deletions editor/plugins/node_3d_editor_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2406,6 +2406,8 @@ void Node3DEditorViewport::_project_settings_changed() {

const bool use_debanding = GLOBAL_GET("rendering/anti_aliasing/quality/use_debanding");
viewport->set_use_debanding(use_debanding);
const float sharpen_intensity = GLOBAL_GET("rendering/anti_aliasing/quality/sharpen_intensity");
viewport->set_sharpen_intensity(sharpen_intensity);

const bool use_occlusion_culling = GLOBAL_GET("rendering/occlusion_culling/use_occlusion_culling");
viewport->set_use_occlusion_culling(use_occlusion_culling);
Expand Down
3 changes: 3 additions & 0 deletions scene/main/scene_tree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1387,6 +1387,9 @@ SceneTree::SceneTree() {
const bool use_debanding = GLOBAL_DEF("rendering/anti_aliasing/quality/use_debanding", false);
root->set_use_debanding(use_debanding);

const float sharpen_intensity = GLOBAL_GET("rendering/anti_aliasing/quality/sharpen_intensity");
root->set_sharpen_intensity(sharpen_intensity);

const bool use_occlusion_culling = GLOBAL_DEF("rendering/occlusion_culling/use_occlusion_culling", false);
root->set_use_occlusion_culling(use_occlusion_culling);

Expand Down
20 changes: 20 additions & 0 deletions scene/main/viewport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2900,6 +2900,18 @@ bool Viewport::is_using_debanding() const {
return use_debanding;
}

void Viewport::set_sharpen_intensity(float p_intensity) {
if (sharpen_intensity == p_intensity) {
return;
}
sharpen_intensity = p_intensity;
RS::get_singleton()->viewport_set_sharpen_intensity(viewport, p_intensity);
}

float Viewport::get_sharpen_intensity() const {
return sharpen_intensity;
}

void Viewport::set_mesh_lod_threshold(float p_pixels) {
mesh_lod_threshold = p_pixels;
RS::get_singleton()->viewport_set_mesh_lod_threshold(viewport, mesh_lod_threshold);
Expand Down Expand Up @@ -3629,6 +3641,9 @@ void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_use_debanding", "enable"), &Viewport::set_use_debanding);
ClassDB::bind_method(D_METHOD("is_using_debanding"), &Viewport::is_using_debanding);

ClassDB::bind_method(D_METHOD("set_sharpen_intensity", "intensity"), &Viewport::set_sharpen_intensity);
ClassDB::bind_method(D_METHOD("get_sharpen_intensity"), &Viewport::get_sharpen_intensity);

ClassDB::bind_method(D_METHOD("set_use_occlusion_culling", "enable"), &Viewport::set_use_occlusion_culling);
ClassDB::bind_method(D_METHOD("is_using_occlusion_culling"), &Viewport::is_using_occlusion_culling);

Expand Down Expand Up @@ -3751,11 +3766,13 @@ void Viewport::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "handle_input_locally"), "set_handle_input_locally", "is_handling_input_locally");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "snap_2d_transforms_to_pixel"), "set_snap_2d_transforms_to_pixel", "is_snap_2d_transforms_to_pixel_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "snap_2d_vertices_to_pixel"), "set_snap_2d_vertices_to_pixel", "is_snap_2d_vertices_to_pixel_enabled");

ADD_GROUP("Rendering", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "msaa", PROPERTY_HINT_ENUM, String::utf8("Disabled (Fastest),2× (Average),4× (Slow),8× (Slowest)")), "set_msaa", "get_msaa");
ADD_PROPERTY(PropertyInfo(Variant::INT, "screen_space_aa", PROPERTY_HINT_ENUM, "Disabled (Fastest),FXAA (Fast)"), "set_screen_space_aa", "get_screen_space_aa");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_taa"), "set_use_taa", "is_using_taa");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_debanding"), "set_use_debanding", "is_using_debanding");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sharpen_intensity"), "set_sharpen_intensity", "get_sharpen_intensity");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_occlusion_culling"), "set_use_occlusion_culling", "is_using_occlusion_culling");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mesh_lod_threshold", PROPERTY_HINT_RANGE, "0,1024,0.1"), "set_mesh_lod_threshold", "get_mesh_lod_threshold");
ADD_PROPERTY(PropertyInfo(Variant::INT, "debug_draw", PROPERTY_HINT_ENUM, "Disabled,Unshaded,Overdraw,Wireframe"), "set_debug_draw", "get_debug_draw");
Expand All @@ -3769,20 +3786,23 @@ void Viewport::_bind_methods() {
ADD_GROUP("Canvas Items", "canvas_item_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "canvas_item_default_texture_filter", PROPERTY_HINT_ENUM, "Nearest,Linear,Linear Mipmap,Nearest Mipmap"), "set_default_canvas_item_texture_filter", "get_default_canvas_item_texture_filter");
ADD_PROPERTY(PropertyInfo(Variant::INT, "canvas_item_default_texture_repeat", PROPERTY_HINT_ENUM, "Disabled,Enabled,Mirror"), "set_default_canvas_item_texture_repeat", "get_default_canvas_item_texture_repeat");

ADD_GROUP("Audio Listener", "audio_listener_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "audio_listener_enable_2d"), "set_as_audio_listener_2d", "is_audio_listener_2d");
#ifndef _3D_DISABLED
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "audio_listener_enable_3d"), "set_as_audio_listener_3d", "is_audio_listener_3d");
#endif
ADD_GROUP("Physics", "physics_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "physics_object_picking"), "set_physics_object_picking", "get_physics_object_picking");

ADD_GROUP("GUI", "gui_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gui_disable_input"), "set_disable_input", "is_input_disabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gui_snap_controls_to_pixels"), "set_snap_controls_to_pixels", "is_snap_controls_to_pixels_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gui_embed_subwindows"), "set_embedding_subwindows", "is_embedding_subwindows");
ADD_GROUP("SDF", "sdf_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "sdf_oversize", PROPERTY_HINT_ENUM, "100%,120%,150%,200%"), "set_sdf_oversize", "get_sdf_oversize");
ADD_PROPERTY(PropertyInfo(Variant::INT, "sdf_scale", PROPERTY_HINT_ENUM, "100%,50%,25%"), "set_sdf_scale", "get_sdf_scale");

ADD_GROUP("Shadow Atlas", "shadow_atlas_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "shadow_atlas_size"), "set_shadow_atlas_size", "get_shadow_atlas_size");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shadow_atlas_16_bits"), "set_shadow_atlas_16_bits", "get_shadow_atlas_16_bits");
Expand Down
4 changes: 4 additions & 0 deletions scene/main/viewport.h
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,7 @@ class Viewport : public Node {
float fsr_sharpness = 0.2f;
float fsr_mipmap_bias = 0.0f;
bool use_debanding = false;
float sharpen_intensity = 0.0;
float mesh_lod_threshold = 1.0;
bool use_occlusion_culling = false;

Expand Down Expand Up @@ -535,6 +536,9 @@ class Viewport : public Node {
void set_use_debanding(bool p_use_debanding);
bool is_using_debanding() const;

void set_sharpen_intensity(float p_intensity);
float get_sharpen_intensity() const;

void set_mesh_lod_threshold(float p_pixels);
float get_mesh_lod_threshold() const;

Expand Down
2 changes: 1 addition & 1 deletion servers/rendering/dummy/rasterizer_scene_dummy.h
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ class RasterizerSceneDummy : public RendererSceneRender {
void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) override {}

RID render_buffers_create() override { return RID(); }
void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override {}
void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, float p_sharpen_intensity, uint32_t p_view_count) override {}
void gi_set_use_half_resolution(bool p_enable) override {}

void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_curve) override {}
Expand Down
2 changes: 2 additions & 0 deletions servers/rendering/renderer_rd/effects/tone_mapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ void ToneMapper::tonemapper(RID p_source_color, RID p_dst_framebuffer, const Ton

tonemap.push_constant.use_fxaa = p_settings.use_fxaa;
tonemap.push_constant.use_debanding = p_settings.use_debanding;
tonemap.push_constant.sharpen_intensity = p_settings.sharpen_intensity;
tonemap.push_constant.pixel_size[0] = 1.0 / p_settings.texture_size.x;
tonemap.push_constant.pixel_size[1] = 1.0 / p_settings.texture_size.y;

Expand Down Expand Up @@ -208,6 +209,7 @@ void ToneMapper::tonemapper(RD::DrawListID p_subpass_draw_list, RID p_source_col
tonemap.push_constant.use_color_correction = p_settings.use_color_correction;

tonemap.push_constant.use_debanding = p_settings.use_debanding;
tonemap.push_constant.sharpen_intensity = p_settings.sharpen_intensity;
tonemap.push_constant.luminance_multiplier = p_settings.luminance_multiplier;

RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
Expand Down
4 changes: 4 additions & 0 deletions servers/rendering/renderer_rd/effects/tone_mapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ class ToneMapper {
float pixel_size[2]; // 8 - 104
uint32_t use_fxaa; // 4 - 108
uint32_t use_debanding; // 4 - 112

uint32_t pad[3]; // 12 - 128
float sharpen_intensity; // 4 - 116
};

/* tonemap actually writes to a framebuffer, which is
Expand Down Expand Up @@ -139,6 +142,7 @@ class ToneMapper {

bool use_fxaa = false;
bool use_debanding = false;
float sharpen_intensity = 0.0;
Vector2i texture_size;
uint32_t view_count = 1;
};
Expand Down
6 changes: 5 additions & 1 deletion servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2610,6 +2610,8 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
}

tonemap.use_debanding = rb->use_debanding;
tonemap.sharpen_intensity = rb->sharpen_intensity;

tonemap.texture_size = Vector2i(rb->internal_width, rb->internal_height);

if (env) {
Expand Down Expand Up @@ -2717,6 +2719,7 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr
}

tonemap.use_debanding = rb->use_debanding;
tonemap.sharpen_intensity = rb->sharpen_intensity;
tonemap.texture_size = Vector2i(rb->width, rb->height);

tonemap.luminance_multiplier = _render_buffers_get_luminance_multiplier();
Expand Down Expand Up @@ -3031,7 +3034,7 @@ bool RendererSceneRenderRD::_render_buffers_can_be_storage() {
return true;
}

void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) {
void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, float p_sharpen_intensity, uint32_t p_view_count) {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();

Expand Down Expand Up @@ -3061,6 +3064,7 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
rb->screen_space_aa = p_screen_space_aa;
rb->use_taa = p_use_taa;
rb->use_debanding = p_use_debanding;
rb->sharpen_intensity = p_sharpen_intensity;
rb->view_count = p_view_count;

if (is_clustered_enabled()) {
Expand Down
Loading

0 comments on commit 9d97caa

Please sign in to comment.