Skip to content

Commit 3b1eaff

Browse files
committed
Add support for contrast-adaptive sharpening in 3D
This is an older, easier to implement variant of CAS as a pure fragment shader. It doesn't support upscaling, but we won't make use of it (at least for now). The sharpening intensity can be adjusted on a per-Viewport basis. For the root viewport, it can be adjusted in the Project Settings.
1 parent 2a9c4a5 commit 3b1eaff

21 files changed

+152
-16
lines changed

doc/classes/ProjectSettings.xml

+5-2
Original file line numberDiff line numberDiff line change
@@ -1477,10 +1477,13 @@
14771477
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.
14781478
</member>
14791479
<member name="rendering/anti_aliasing/quality/screen_space_aa" type="int" setter="" getter="" default="0">
1480-
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.
1481-
Another way to combat specular aliasing is to enable [member rendering/anti_aliasing/screen_space_roughness_limiter/enabled].
1480+
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]).
1481+
</member>
1482+
<member name="rendering/anti_aliasing/quality/sharpen_intensity" type="float" setter="" getter="" default="0.0">
1483+
If set to a value greater than [code]0.0[/code], contrast-adaptive sharpening will be applied to the 3D viewport. This has a low 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].
14821484
</member>
14831485
<member name="rendering/anti_aliasing/quality/use_debanding" type="bool" setter="" getter="" default="false">
1486+
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.
14841487
</member>
14851488
<member name="rendering/anti_aliasing/screen_space_roughness_limiter/amount" type="float" setter="" getter="" default="0.25">
14861489
</member>

doc/classes/RenderingServer.xml

+11
Original file line numberDiff line numberDiff line change
@@ -3124,6 +3124,17 @@
31243124
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.
31253125
</description>
31263126
</method>
3127+
<method name="viewport_set_sharpen_intensity">
3128+
<return type="void">
3129+
</return>
3130+
<argument index="0" name="viewport" type="RID">
3131+
</argument>
3132+
<argument index="1" name="intensity" type="float">
3133+
</argument>
3134+
<description>
3135+
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 low 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.
3136+
</description>
3137+
</method>
31273138
<method name="viewport_set_size">
31283139
<return type="void" />
31293140
<argument index="0" name="viewport" type="RID" />

doc/classes/Viewport.xml

+4-1
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@
212212
If [code]true[/code], the objects rendered by viewport become subjects of mouse picking process.
213213
</member>
214214
<member name="screen_space_aa" type="int" setter="set_screen_space_aa" getter="get_screen_space_aa" enum="Viewport.ScreenSpaceAA" default="0">
215-
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.
215+
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]).
216216
</member>
217217
<member name="sdf_oversize" type="int" setter="set_sdf_oversize" getter="get_sdf_oversize" enum="Viewport.SDFOversize" default="1">
218218
</member>
@@ -236,6 +236,9 @@
236236
The shadow atlas' resolution (used for omni and spot lights). The value will be rounded up to the nearest power of 2.
237237
[b]Note:[/b] If this is set to 0, shadows won't be visible.
238238
</member>
239+
<member name="sharpen_intensity" type="float" setter="set_sharpen_intensity" getter="get_sharpen_intensity" default="0.0">
240+
If set to a value greater than [code]0.0[/code], contrast-adaptive sharpening will be applied to the 3D viewport. This has a low 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].
241+
</member>
239242
<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">
240243
</member>
241244
<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">

editor/plugins/node_3d_editor_plugin.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -2617,6 +2617,8 @@ void Node3DEditorViewport::_project_settings_changed() {
26172617
viewport->set_screen_space_aa(Viewport::ScreenSpaceAA(ssaa_mode));
26182618
const bool use_debanding = GLOBAL_GET("rendering/anti_aliasing/quality/use_debanding");
26192619
viewport->set_use_debanding(use_debanding);
2620+
const float sharpen_intensity = GLOBAL_GET("rendering/anti_aliasing/quality/sharpen_intensity");
2621+
viewport->set_sharpen_intensity(sharpen_intensity);
26202622

26212623
const bool use_occlusion_culling = GLOBAL_GET("rendering/occlusion_culling/use_occlusion_culling");
26222624
viewport->set_use_occlusion_culling(use_occlusion_culling);

scene/main/scene_tree.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -1357,6 +1357,9 @@ SceneTree::SceneTree() {
13571357
const bool use_debanding = GLOBAL_DEF("rendering/anti_aliasing/quality/use_debanding", false);
13581358
root->set_use_debanding(use_debanding);
13591359

1360+
const float sharpen_intensity = GLOBAL_GET("rendering/anti_aliasing/quality/sharpen_intensity");
1361+
root->set_sharpen_intensity(sharpen_intensity);
1362+
13601363
const bool use_occlusion_culling = GLOBAL_DEF("rendering/occlusion_culling/use_occlusion_culling", false);
13611364
root->set_use_occlusion_culling(use_occlusion_culling);
13621365

scene/main/viewport.cpp

+24-1
Original file line numberDiff line numberDiff line change
@@ -2844,6 +2844,18 @@ bool Viewport::is_using_debanding() const {
28442844
return use_debanding;
28452845
}
28462846

2847+
void Viewport::set_sharpen_intensity(float p_intensity) {
2848+
if (sharpen_intensity == p_intensity) {
2849+
return;
2850+
}
2851+
sharpen_intensity = p_intensity;
2852+
RS::get_singleton()->viewport_set_sharpen_intensity(viewport, p_intensity);
2853+
}
2854+
2855+
float Viewport::get_sharpen_intensity() const {
2856+
return sharpen_intensity;
2857+
}
2858+
28472859
void Viewport::set_lod_threshold(float p_pixels) {
28482860
lod_threshold = p_pixels;
28492861
RS::get_singleton()->viewport_set_lod_threshold(viewport, lod_threshold);
@@ -3501,6 +3513,9 @@ void Viewport::_bind_methods() {
35013513
ClassDB::bind_method(D_METHOD("set_use_debanding", "enable"), &Viewport::set_use_debanding);
35023514
ClassDB::bind_method(D_METHOD("is_using_debanding"), &Viewport::is_using_debanding);
35033515

3516+
ClassDB::bind_method(D_METHOD("set_sharpen_intensity", "intensity"), &Viewport::set_sharpen_intensity);
3517+
ClassDB::bind_method(D_METHOD("get_sharpen_intensity"), &Viewport::get_sharpen_intensity);
3518+
35043519
ClassDB::bind_method(D_METHOD("set_use_occlusion_culling", "enable"), &Viewport::set_use_occlusion_culling);
35053520
ClassDB::bind_method(D_METHOD("is_using_occlusion_culling"), &Viewport::is_using_occlusion_culling);
35063521

@@ -3600,7 +3615,6 @@ void Viewport::_bind_methods() {
36003615

36013616
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disable_3d"), "set_disable_3d", "is_3d_disabled");
36023617
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_xr"), "set_use_xr", "is_using_xr");
3603-
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "audio_listener_enable_3d"), "set_as_audio_listener_3d", "is_audio_listener_3d");
36043618
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "own_world_3d"), "set_use_own_world_3d", "is_using_own_world_3d");
36053619
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "world_3d", PROPERTY_HINT_RESOURCE_TYPE, "World3D"), "set_world_3d", "get_world_3d");
36063620
#endif // _3D_DISABLED
@@ -3609,27 +3623,36 @@ void Viewport::_bind_methods() {
36093623
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "handle_input_locally"), "set_handle_input_locally", "is_handling_input_locally");
36103624
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "snap_2d_transforms_to_pixel"), "set_snap_2d_transforms_to_pixel", "is_snap_2d_transforms_to_pixel_enabled");
36113625
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "snap_2d_vertices_to_pixel"), "set_snap_2d_vertices_to_pixel", "is_snap_2d_vertices_to_pixel_enabled");
3626+
36123627
ADD_GROUP("Rendering", "");
36133628
ADD_PROPERTY(PropertyInfo(Variant::INT, "msaa", PROPERTY_HINT_ENUM, String::utf8("Disabled (Fastest),2× (Fast),4× (Average),8× (Slow),16× (Slower)")), "set_msaa", "get_msaa");
36143629
ADD_PROPERTY(PropertyInfo(Variant::INT, "screen_space_aa", PROPERTY_HINT_ENUM, "Disabled (Fastest),FXAA (Fast)"), "set_screen_space_aa", "get_screen_space_aa");
36153630
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_debanding"), "set_use_debanding", "is_using_debanding");
3631+
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sharpen_intensity"), "set_sharpen_intensity", "get_sharpen_intensity");
36163632
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_occlusion_culling"), "set_use_occlusion_culling", "is_using_occlusion_culling");
36173633
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lod_threshold", PROPERTY_HINT_RANGE, "0,1024,0.1"), "set_lod_threshold", "get_lod_threshold");
36183634
ADD_PROPERTY(PropertyInfo(Variant::INT, "debug_draw", PROPERTY_HINT_ENUM, "Disabled,Unshaded,Overdraw,Wireframe"), "set_debug_draw", "get_debug_draw");
3635+
36193636
ADD_GROUP("Canvas Items", "canvas_item_");
36203637
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");
36213638
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");
3639+
36223640
ADD_GROUP("Audio Listener", "audio_listener_");
36233641
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "audio_listener_enable_2d"), "set_as_audio_listener_2d", "is_audio_listener_2d");
3642+
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "audio_listener_enable_3d"), "set_as_audio_listener_3d", "is_audio_listener_3d");
3643+
36243644
ADD_GROUP("Physics", "physics_");
36253645
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "physics_object_picking"), "set_physics_object_picking", "get_physics_object_picking");
3646+
36263647
ADD_GROUP("GUI", "gui_");
36273648
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gui_disable_input"), "set_disable_input", "is_input_disabled");
36283649
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gui_snap_controls_to_pixels"), "set_snap_controls_to_pixels", "is_snap_controls_to_pixels_enabled");
36293650
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gui_embed_subwindows"), "set_embed_subwindows_hint", "get_embed_subwindows_hint");
3651+
36303652
ADD_GROUP("SDF", "sdf_");
36313653
ADD_PROPERTY(PropertyInfo(Variant::INT, "sdf_oversize", PROPERTY_HINT_ENUM, "100%,120%,150%,200%"), "set_sdf_oversize", "get_sdf_oversize");
36323654
ADD_PROPERTY(PropertyInfo(Variant::INT, "sdf_scale", PROPERTY_HINT_ENUM, "100%,50%,25%"), "set_sdf_scale", "get_sdf_scale");
3655+
36333656
ADD_GROUP("Shadow Atlas", "shadow_atlas_");
36343657
ADD_PROPERTY(PropertyInfo(Variant::INT, "shadow_atlas_size"), "set_shadow_atlas_size", "get_shadow_atlas_size");
36353658
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shadow_atlas_16_bits"), "set_shadow_atlas_16_bits", "get_shadow_atlas_16_bits");

scene/main/viewport.h

+4
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,7 @@ class Viewport : public Node {
283283
MSAA msaa = MSAA_DISABLED;
284284
ScreenSpaceAA screen_space_aa = SCREEN_SPACE_AA_DISABLED;
285285
bool use_debanding = false;
286+
float sharpen_intensity = 0.0;
286287
float lod_threshold = 1.0;
287288
bool use_occlusion_culling = false;
288289

@@ -499,6 +500,9 @@ class Viewport : public Node {
499500
void set_use_debanding(bool p_use_debanding);
500501
bool is_using_debanding() const;
501502

503+
void set_sharpen_intensity(float p_intensity);
504+
float get_sharpen_intensity() const;
505+
502506
void set_lod_threshold(float p_pixels);
503507
float get_lod_threshold() const;
504508

servers/rendering/rasterizer_dummy.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ class RasterizerSceneDummy : public RendererSceneRender {
186186
void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) override {}
187187

188188
RID render_buffers_create() override { return RID(); }
189-
void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) override {}
189+
void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, float p_sharpen_intensity, uint32_t p_view_count) override {}
190190
void gi_set_use_half_resolution(bool p_enable) override {}
191191

192192
void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_curve) override {}

servers/rendering/renderer_rd/effects_rd.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -815,6 +815,7 @@ void EffectsRD::tonemapper(RID p_source_color, RID p_dst_framebuffer, const Tone
815815

816816
tonemap.push_constant.use_fxaa = p_settings.use_fxaa;
817817
tonemap.push_constant.use_debanding = p_settings.use_debanding;
818+
tonemap.push_constant.sharpen_intensity = p_settings.sharpen_intensity;
818819
tonemap.push_constant.pixel_size[0] = 1.0 / p_settings.texture_size.x;
819820
tonemap.push_constant.pixel_size[1] = 1.0 / p_settings.texture_size.y;
820821

servers/rendering/renderer_rd/effects_rd.h

+4
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,9 @@ class EffectsRD {
260260
float pixel_size[2]; // 8 - 104
261261
uint32_t use_fxaa; // 4 - 108
262262
uint32_t use_debanding; // 4 - 112
263+
264+
float sharpen_intensity; // 4 - 116
265+
uint32_t pad[3]; // 12 - 128
263266
};
264267

265268
/* tonemap actually writes to a framebuffer, which is
@@ -831,6 +834,7 @@ class EffectsRD {
831834

832835
bool use_fxaa = false;
833836
bool use_debanding = false;
837+
float sharpen_intensity = 0.0;
834838
Vector2i texture_size;
835839
uint32_t view_count = 1;
836840
};

servers/rendering/renderer_rd/renderer_scene_render_rd.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -2130,6 +2130,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
21302130
}
21312131

21322132
tonemap.use_debanding = rb->use_debanding;
2133+
tonemap.sharpen_intensity = rb->sharpen_intensity;
21332134
tonemap.texture_size = Vector2i(rb->width, rb->height);
21342135

21352136
if (env) {
@@ -2498,7 +2499,7 @@ bool RendererSceneRenderRD::_render_buffers_can_be_storage() {
24982499
return true;
24992500
}
25002501

2501-
void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) {
2502+
void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, float p_sharpen_intensity, uint32_t p_view_count) {
25022503
ERR_FAIL_COND_MSG(p_view_count == 0, "Must have at least 1 view");
25032504

25042505
RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
@@ -2508,6 +2509,7 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
25082509
rb->msaa = p_msaa;
25092510
rb->screen_space_aa = p_screen_space_aa;
25102511
rb->use_debanding = p_use_debanding;
2512+
rb->sharpen_intensity = p_sharpen_intensity;
25112513
rb->view_count = p_view_count;
25122514

25132515
if (is_clustered_enabled()) {

servers/rendering/renderer_rd/renderer_scene_render_rd.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,7 @@ class RendererSceneRenderRD : public RendererSceneRender {
449449
RS::ViewportMSAA msaa = RS::VIEWPORT_MSAA_DISABLED;
450450
RS::ViewportScreenSpaceAA screen_space_aa = RS::VIEWPORT_SCREEN_SPACE_AA_DISABLED;
451451
bool use_debanding = false;
452+
float sharpen_intensity = 0.0;
452453
uint32_t view_count = 1;
453454

454455
RID render_target;
@@ -1184,7 +1185,7 @@ class RendererSceneRenderRD : public RendererSceneRender {
11841185
virtual RD::DataFormat _render_buffers_get_color_format();
11851186
virtual bool _render_buffers_can_be_storage();
11861187
virtual RID render_buffers_create() override;
1187-
virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) override;
1188+
virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, float p_sharpen_intensity, uint32_t p_view_count) override;
11881189
virtual void gi_set_use_half_resolution(bool p_enable) override;
11891190

11901191
RID render_buffers_get_ao_texture(RID p_render_buffers);

servers/rendering/renderer_rd/shaders/tonemap.glsl

+55
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ layout(push_constant, binding = 1, std430) uniform Params {
7676
vec2 pixel_size;
7777
bool use_fxaa;
7878
bool use_debanding;
79+
float sharpen_intensity;
7980
}
8081
params;
8182

@@ -347,6 +348,54 @@ vec3 do_fxaa(vec3 color, float exposure, vec2 uv_interp) {
347348
return rgbB;
348349
}
349350
}
351+
352+
// Adapted from https://github.com/DadSchoorse/vkBasalt/blob/b929505ba71dea21d6c32a5a59f2d241592b30c4/src/shader/cas.frag.glsl
353+
// (MIT license).
354+
vec3 do_cas(vec3 color, float exposure, vec2 uv_interp, float sharpen_intensity) {
355+
// Fetch a 3x3 neighborhood around the pixel 'e',
356+
// a b c
357+
// d(e)f
358+
// g h i
359+
vec3 a = textureLodOffset(source_color, uv_interp, 0.0, ivec2(-1, -1)).rgb * exposure;
360+
vec3 b = textureLodOffset(source_color, uv_interp, 0.0, ivec2(0, -1)).rgb * exposure;
361+
vec3 c = textureLodOffset(source_color, uv_interp, 0.0, ivec2(1, -1)).rgb * exposure;
362+
vec3 d = textureLodOffset(source_color, uv_interp, 0.0, ivec2(-1, 0)).rgb * exposure;
363+
vec3 e = color.rgb;
364+
vec3 f = textureLodOffset(source_color, uv_interp, 0.0, ivec2(1, 0)).rgb * exposure;
365+
vec3 g = textureLodOffset(source_color, uv_interp, 0.0, ivec2(-1, 1)).rgb * exposure;
366+
vec3 h = textureLodOffset(source_color, uv_interp, 0.0, ivec2(0, 1)).rgb * exposure;
367+
vec3 i = textureLodOffset(source_color, uv_interp, 0.0, ivec2(1, 1)).rgb * exposure;
368+
369+
// Soft min and max.
370+
// a b c b
371+
// d e f * 0.5 + d e f * 0.5
372+
// g h i h
373+
// These are 2.0x bigger (factored out the extra multiply).
374+
vec3 min_rgb = min(min(min(d, e), min(f, b)), h);
375+
vec3 min_rgb2 = min(min(min(min_rgb, a), min(g, c)), i);
376+
min_rgb += min_rgb2;
377+
378+
vec3 max_rgb = max(max(max(d, e), max(f, b)), h);
379+
vec3 max_rgb2 = max(max(max(max_rgb, a), max(g, c)), i);
380+
max_rgb += max_rgb2;
381+
382+
// Smooth minimum distance to signal limit divided by smooth max.
383+
vec3 rcp_max_rgb = vec3(1.0) / max_rgb;
384+
vec3 amp_rgb = clamp((min(min_rgb, 2.0 - max_rgb) * rcp_max_rgb), 0.0, 1.0);
385+
386+
// Shaping amount of sharpening.
387+
amp_rgb = inversesqrt(amp_rgb);
388+
float peak = 8.0 - 3.0 * sharpen_intensity;
389+
vec3 w_rgb = -vec3(1) / (amp_rgb * peak);
390+
vec3 rcp_weight_rgb = vec3(1.0) / (1.0 + 4.0 * w_rgb);
391+
392+
// 0 w 0
393+
// Filter shape: w 1 w
394+
// 0 w 0
395+
vec3 window = b + d + f + h;
396+
397+
return max(vec3(0.0), (window * w_rgb + e) * rcp_weight_rgb);
398+
}
350399
#endif // !SUBPASS
351400

352401
// From http://alex.vlachos.com/graphics/Alex_Vlachos_Advanced_VR_Rendering_GDC2015.pdf
@@ -393,6 +442,12 @@ void main() {
393442
if (params.use_fxaa) {
394443
color = do_fxaa(color, exposure, uv_interp);
395444
}
445+
446+
if (params.sharpen_intensity >= 0.001) {
447+
// CAS gives best results when applied after tonemapping, but `source_color` isn't tonemapped.
448+
// As a workaround, apply CAS before tonemapping so that the image still has a correct appearance when tonemapped.
449+
color = do_cas(color, exposure, uv_interp, params.sharpen_intensity);
450+
}
396451
#endif
397452

398453
if (params.use_debanding) {

0 commit comments

Comments
 (0)