Add a debanding property to Viewport
It can be enabled in the Project Settings (`rendering/quality/screen_filters/use_debanding`). It's disabled by default as it has a small performance impact and can make PNG screenshots much larger (due to how dithering works). It will also slightly brighten the scene's dark areas. As a result, it should be enabled only when banding is noticeable enough. This closes #17006.
This commit is contained in:
parent
aded76cb84
commit
8891579068
16 changed files with 82 additions and 14 deletions
|
@ -2447,12 +2447,14 @@ void Node3DEditorViewport::_notification(int p_what) {
|
|||
subviewport_container->set_stretch_shrink(shrink ? 2 : 1);
|
||||
}
|
||||
|
||||
//update msaa if changed
|
||||
// Update MSAA, screen-space AA and debanding if changed
|
||||
|
||||
int msaa_mode = ProjectSettings::get_singleton()->get("rendering/quality/screen_filters/msaa");
|
||||
const int msaa_mode = ProjectSettings::get_singleton()->get("rendering/quality/screen_filters/msaa");
|
||||
viewport->set_msaa(Viewport::MSAA(msaa_mode));
|
||||
int ssaa_mode = GLOBAL_GET("rendering/quality/screen_filters/screen_space_aa");
|
||||
const int ssaa_mode = GLOBAL_GET("rendering/quality/screen_filters/screen_space_aa");
|
||||
viewport->set_screen_space_aa(Viewport::ScreenSpaceAA(ssaa_mode));
|
||||
const bool use_debanding = GLOBAL_GET("rendering/quality/screen_filters/use_debanding");
|
||||
viewport->set_use_debanding(use_debanding);
|
||||
|
||||
bool show_info = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_INFORMATION));
|
||||
if (show_info != info_label->is_visible()) {
|
||||
|
|
|
@ -1383,14 +1383,17 @@ SceneTree::SceneTree() {
|
|||
root->set_as_audio_listener_2d(true);
|
||||
current_scene = nullptr;
|
||||
|
||||
int msaa_mode = GLOBAL_DEF("rendering/quality/screen_filters/msaa", 0);
|
||||
const int msaa_mode = GLOBAL_DEF("rendering/quality/screen_filters/msaa", 0);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/screen_filters/msaa", PropertyInfo(Variant::INT, "rendering/quality/screen_filters/msaa", PROPERTY_HINT_ENUM, "Disabled (Fastest),2x (Fast),4x (Average),8x (Slow),16x (Slower)"));
|
||||
root->set_msaa(Viewport::MSAA(msaa_mode));
|
||||
|
||||
int ssaa_mode = GLOBAL_DEF("rendering/quality/screen_filters/screen_space_aa", 0);
|
||||
const int ssaa_mode = GLOBAL_DEF("rendering/quality/screen_filters/screen_space_aa", 0);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/screen_filters/screen_space_aa", PropertyInfo(Variant::INT, "rendering/quality/screen_filters/screen_space_aa", PROPERTY_HINT_ENUM, "Disabled (Fastest),FXAA (Fast)"));
|
||||
root->set_screen_space_aa(Viewport::ScreenSpaceAA(ssaa_mode));
|
||||
|
||||
const bool use_debanding = GLOBAL_DEF("rendering/quality/screen_filters/use_debanding", false);
|
||||
root->set_use_debanding(use_debanding);
|
||||
|
||||
{ //load default fallback environment
|
||||
//get possible extensions
|
||||
List<String> exts;
|
||||
|
|
|
@ -3133,6 +3133,17 @@ Viewport::ScreenSpaceAA Viewport::get_screen_space_aa() const {
|
|||
return screen_space_aa;
|
||||
}
|
||||
|
||||
void Viewport::set_use_debanding(bool p_use_debanding) {
|
||||
if (use_debanding == p_use_debanding)
|
||||
return;
|
||||
use_debanding = p_use_debanding;
|
||||
RS::get_singleton()->viewport_set_use_debanding(viewport, p_use_debanding);
|
||||
}
|
||||
|
||||
bool Viewport::is_using_debanding() const {
|
||||
return use_debanding;
|
||||
}
|
||||
|
||||
void Viewport::set_debug_draw(DebugDraw p_debug_draw) {
|
||||
debug_draw = p_debug_draw;
|
||||
RS::get_singleton()->viewport_set_debug_draw(viewport, RS::ViewportDebugDraw(p_debug_draw));
|
||||
|
@ -3319,6 +3330,9 @@ void Viewport::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("set_screen_space_aa", "screen_space_aa"), &Viewport::set_screen_space_aa);
|
||||
ClassDB::bind_method(D_METHOD("get_screen_space_aa"), &Viewport::get_screen_space_aa);
|
||||
|
||||
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_debug_draw", "debug_draw"), &Viewport::set_debug_draw);
|
||||
ClassDB::bind_method(D_METHOD("get_debug_draw"), &Viewport::get_debug_draw);
|
||||
|
||||
|
@ -3392,6 +3406,7 @@ void Viewport::_bind_methods() {
|
|||
ADD_GROUP("Rendering", "");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "msaa", PROPERTY_HINT_ENUM, "Disabled,2x,4x,8x,16x,AndroidVR 2x,AndroidVR 4x"), "set_msaa", "get_msaa");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "screen_space_aa", PROPERTY_HINT_ENUM, "Disabled,FXAA"), "set_screen_space_aa", "get_screen_space_aa");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_debanding"), "set_use_debanding", "is_using_debanding");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "debug_draw", PROPERTY_HINT_ENUM, "Disabled,Unshaded,Overdraw,Wireframe"), "set_debug_draw", "get_debug_draw");
|
||||
ADD_GROUP("Canvas Items", "canvas_item_");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "canvas_item_default_texture_filter", PROPERTY_HINT_ENUM, "Nearest,Linear,MipmapLinear,MipmapNearest"), "set_default_canvas_item_texture_filter", "get_default_canvas_item_texture_filter");
|
||||
|
|
|
@ -279,6 +279,7 @@ private:
|
|||
|
||||
MSAA msaa;
|
||||
ScreenSpaceAA screen_space_aa;
|
||||
bool use_debanding;
|
||||
Ref<ViewportTexture> default_texture;
|
||||
Set<ViewportTexture *> viewport_textures;
|
||||
|
||||
|
@ -521,6 +522,9 @@ public:
|
|||
void set_screen_space_aa(ScreenSpaceAA p_screen_space_aa);
|
||||
ScreenSpaceAA get_screen_space_aa() const;
|
||||
|
||||
void set_use_debanding(bool p_use_debanding);
|
||||
bool is_using_debanding() const;
|
||||
|
||||
Vector2 get_camera_coords(const Vector2 &p_viewport_coords) const;
|
||||
Vector2 get_camera_rect_size() const;
|
||||
|
||||
|
|
|
@ -304,7 +304,7 @@ public:
|
|||
virtual void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) = 0;
|
||||
|
||||
virtual RID render_buffers_create() = 0;
|
||||
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) = 0;
|
||||
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) = 0;
|
||||
|
||||
virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_limit) = 0;
|
||||
virtual bool screen_space_roughness_limiter_is_active() const = 0;
|
||||
|
|
|
@ -708,6 +708,7 @@ void RasterizerEffectsRD::tonemapper(RID p_source_color, RID p_dst_framebuffer,
|
|||
tonemap.push_constant.use_color_correction = p_settings.use_color_correction;
|
||||
|
||||
tonemap.push_constant.use_fxaa = p_settings.use_fxaa;
|
||||
tonemap.push_constant.use_debanding = p_settings.use_debanding;
|
||||
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;
|
||||
|
||||
|
|
|
@ -184,7 +184,7 @@ class RasterizerEffectsRD {
|
|||
|
||||
float pixel_size[2];
|
||||
uint32_t use_fxaa;
|
||||
uint32_t pad;
|
||||
uint32_t use_debanding;
|
||||
};
|
||||
|
||||
/* tonemap actually writes to a framebuffer, which is
|
||||
|
@ -628,6 +628,7 @@ public:
|
|||
RID color_correction_texture;
|
||||
|
||||
bool use_fxaa = false;
|
||||
bool use_debanding = false;
|
||||
Vector2i texture_size;
|
||||
};
|
||||
|
||||
|
|
|
@ -5250,6 +5250,7 @@ void RasterizerSceneRD::_render_buffers_post_process_and_tonemap(RID p_render_bu
|
|||
tonemap.use_fxaa = true;
|
||||
}
|
||||
|
||||
tonemap.use_debanding = rb->use_debanding;
|
||||
tonemap.texture_size = Vector2i(rb->width, rb->height);
|
||||
|
||||
if (env) {
|
||||
|
@ -5618,13 +5619,14 @@ float RasterizerSceneRD::render_buffers_get_volumetric_fog_detail_spread(RID p_r
|
|||
return rb->volumetric_fog->spread;
|
||||
}
|
||||
|
||||
void RasterizerSceneRD::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) {
|
||||
void RasterizerSceneRD::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) {
|
||||
RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
|
||||
rb->width = p_width;
|
||||
rb->height = p_height;
|
||||
rb->render_target = p_render_target;
|
||||
rb->msaa = p_msaa;
|
||||
rb->screen_space_aa = p_screen_space_aa;
|
||||
rb->use_debanding = p_use_debanding;
|
||||
_free_render_buffer_data(rb);
|
||||
|
||||
{
|
||||
|
|
|
@ -788,6 +788,7 @@ private:
|
|||
int width = 0, height = 0;
|
||||
RS::ViewportMSAA msaa = RS::VIEWPORT_MSAA_DISABLED;
|
||||
RS::ViewportScreenSpaceAA screen_space_aa = RS::VIEWPORT_SCREEN_SPACE_AA_DISABLED;
|
||||
bool use_debanding = false;
|
||||
|
||||
RID render_target;
|
||||
|
||||
|
@ -1815,7 +1816,7 @@ public:
|
|||
}
|
||||
*/
|
||||
RID render_buffers_create();
|
||||
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);
|
||||
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);
|
||||
|
||||
RID render_buffers_get_ao_texture(RID p_render_buffers);
|
||||
RID render_buffers_get_back_buffer_texture(RID p_render_buffers);
|
||||
|
|
|
@ -46,7 +46,7 @@ layout(push_constant, binding = 1, std430) uniform Params {
|
|||
|
||||
vec2 pixel_size;
|
||||
bool use_fxaa;
|
||||
uint pad;
|
||||
bool use_debanding;
|
||||
}
|
||||
params;
|
||||
|
||||
|
@ -299,6 +299,19 @@ vec3 do_fxaa(vec3 color, float exposure, vec2 uv_interp) {
|
|||
}
|
||||
}
|
||||
|
||||
#define QUARTER_COLOR 1.0 / 1024.0
|
||||
|
||||
// From http://alex.vlachos.com/graphics/Alex_Vlachos_Advanced_VR_Rendering_GDC2015.pdf
|
||||
// and https://www.shadertoy.com/view/MslGR8 (5th one starting from the bottom)
|
||||
// NOTE: `frag_coord` is in pixels (i.e. not normalized UV).
|
||||
vec3 screen_space_dither(vec2 frag_coord) {
|
||||
// Iestyn's RGB dither (7 asm instructions) from Portal 2 X360, slightly modified for VR.
|
||||
vec3 dither = vec3(dot(vec2(171.0, 231.0), frag_coord));
|
||||
dither.rgb = fract(dither.rgb / vec3(103.0, 71.0, 97.0));
|
||||
|
||||
return dither.rgb / 255.0;
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec3 color = textureLod(source_color, uv_interp, 0.0f).rgb;
|
||||
|
||||
|
@ -322,6 +335,10 @@ void main() {
|
|||
if (params.use_fxaa) {
|
||||
color = do_fxaa(color, exposure, uv_interp);
|
||||
}
|
||||
if (params.use_debanding) {
|
||||
// Debanding should be done before tonemapping.
|
||||
color += screen_space_dither(gl_FragCoord.xy);
|
||||
}
|
||||
color = apply_tonemapping(color, params.white);
|
||||
|
||||
color = linear_to_srgb(color); // regular linear -> SRGB conversion
|
||||
|
|
|
@ -509,6 +509,7 @@ public:
|
|||
BIND3(viewport_set_shadow_atlas_quadrant_subdivision, RID, int, int)
|
||||
BIND2(viewport_set_msaa, RID, ViewportMSAA)
|
||||
BIND2(viewport_set_screen_space_aa, RID, ViewportScreenSpaceAA)
|
||||
BIND2(viewport_set_use_debanding, RID, bool)
|
||||
|
||||
BIND2R(int, viewport_get_render_info, RID, ViewportRenderInfo)
|
||||
BIND2(viewport_set_debug_draw, RID, ViewportDebugDraw)
|
||||
|
|
|
@ -115,7 +115,7 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, XRInterface::
|
|||
if ((scenario_draw_canvas_bg || can_draw_3d) && !p_viewport->render_buffers.is_valid()) {
|
||||
//wants to draw 3D but there is no render buffer, create
|
||||
p_viewport->render_buffers = RSG::scene_render->render_buffers_create();
|
||||
RSG::scene_render->render_buffers_configure(p_viewport->render_buffers, p_viewport->render_target, p_viewport->size.width, p_viewport->size.height, p_viewport->msaa, p_viewport->screen_space_aa);
|
||||
RSG::scene_render->render_buffers_configure(p_viewport->render_buffers, p_viewport->render_target, p_viewport->size.width, p_viewport->size.height, p_viewport->msaa, p_viewport->screen_space_aa, p_viewport->use_debanding);
|
||||
}
|
||||
|
||||
RSG::storage->render_target_request_clear(p_viewport->render_target, bgcolor);
|
||||
|
@ -491,7 +491,7 @@ void RenderingServerViewport::viewport_set_size(RID p_viewport, int p_width, int
|
|||
RSG::scene_render->free(viewport->render_buffers);
|
||||
viewport->render_buffers = RID();
|
||||
} else {
|
||||
RSG::scene_render->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, viewport->msaa, viewport->screen_space_aa);
|
||||
RSG::scene_render->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, viewport->msaa, viewport->screen_space_aa, viewport->use_debanding);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -704,7 +704,7 @@ void RenderingServerViewport::viewport_set_msaa(RID p_viewport, RS::ViewportMSAA
|
|||
}
|
||||
viewport->msaa = p_msaa;
|
||||
if (viewport->render_buffers.is_valid()) {
|
||||
RSG::scene_render->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, p_msaa, viewport->screen_space_aa);
|
||||
RSG::scene_render->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, p_msaa, viewport->screen_space_aa, viewport->use_debanding);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -717,7 +717,20 @@ void RenderingServerViewport::viewport_set_screen_space_aa(RID p_viewport, RS::V
|
|||
}
|
||||
viewport->screen_space_aa = p_mode;
|
||||
if (viewport->render_buffers.is_valid()) {
|
||||
RSG::scene_render->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, viewport->msaa, p_mode);
|
||||
RSG::scene_render->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, viewport->msaa, p_mode, viewport->use_debanding);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderingServerViewport::viewport_set_use_debanding(RID p_viewport, bool p_use_debanding) {
|
||||
Viewport *viewport = viewport_owner.getornull(p_viewport);
|
||||
ERR_FAIL_COND(!viewport);
|
||||
|
||||
if (viewport->use_debanding == p_use_debanding) {
|
||||
return;
|
||||
}
|
||||
viewport->use_debanding = p_use_debanding;
|
||||
if (viewport->render_buffers.is_valid()) {
|
||||
RSG::scene_render->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, viewport->msaa, viewport->screen_space_aa, p_use_debanding);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -59,6 +59,7 @@ public:
|
|||
|
||||
RS::ViewportMSAA msaa;
|
||||
RS::ViewportScreenSpaceAA screen_space_aa;
|
||||
bool use_debanding;
|
||||
|
||||
DisplayServer::WindowID viewport_to_screen;
|
||||
Rect2 viewport_to_screen_rect;
|
||||
|
@ -130,6 +131,7 @@ public:
|
|||
debug_draw = RS::VIEWPORT_DEBUG_DRAW_DISABLED;
|
||||
msaa = RS::VIEWPORT_MSAA_DISABLED;
|
||||
screen_space_aa = RS::VIEWPORT_SCREEN_SPACE_AA_DISABLED;
|
||||
use_debanding = false;
|
||||
|
||||
for (int i = 0; i < RS::VIEWPORT_RENDER_INFO_MAX; i++) {
|
||||
render_info[i] = 0;
|
||||
|
@ -206,6 +208,7 @@ public:
|
|||
|
||||
void viewport_set_msaa(RID p_viewport, RS::ViewportMSAA p_msaa);
|
||||
void viewport_set_screen_space_aa(RID p_viewport, RS::ViewportScreenSpaceAA p_mode);
|
||||
void viewport_set_use_debanding(RID p_viewport, bool p_use_debanding);
|
||||
|
||||
virtual int viewport_get_render_info(RID p_viewport, RS::ViewportRenderInfo p_info);
|
||||
virtual void viewport_set_debug_draw(RID p_viewport, RS::ViewportDebugDraw p_draw);
|
||||
|
|
|
@ -418,6 +418,7 @@ public:
|
|||
FUNC3(viewport_set_shadow_atlas_quadrant_subdivision, RID, int, int)
|
||||
FUNC2(viewport_set_msaa, RID, ViewportMSAA)
|
||||
FUNC2(viewport_set_screen_space_aa, RID, ViewportScreenSpaceAA)
|
||||
FUNC2(viewport_set_use_debanding, RID, bool)
|
||||
|
||||
//this passes directly to avoid stalling, but it's pretty dangerous, so don't call after freeing a viewport
|
||||
virtual int viewport_get_render_info(RID p_viewport, ViewportRenderInfo p_info) {
|
||||
|
|
|
@ -1730,6 +1730,8 @@ void RenderingServer::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("viewport_set_shadow_atlas_size", "viewport", "size"), &RenderingServer::viewport_set_shadow_atlas_size);
|
||||
ClassDB::bind_method(D_METHOD("viewport_set_shadow_atlas_quadrant_subdivision", "viewport", "quadrant", "subdivision"), &RenderingServer::viewport_set_shadow_atlas_quadrant_subdivision);
|
||||
ClassDB::bind_method(D_METHOD("viewport_set_msaa", "viewport", "msaa"), &RenderingServer::viewport_set_msaa);
|
||||
ClassDB::bind_method(D_METHOD("viewport_set_use_debanding" "viewport", "enable"), &RenderingServer::viewport_set_use_debanding);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("viewport_get_render_info", "viewport", "info"), &RenderingServer::viewport_get_render_info);
|
||||
ClassDB::bind_method(D_METHOD("viewport_set_debug_draw", "viewport", "draw"), &RenderingServer::viewport_set_debug_draw);
|
||||
|
||||
|
|
|
@ -676,6 +676,8 @@ public:
|
|||
|
||||
virtual void viewport_set_screen_space_aa(RID p_viewport, ViewportScreenSpaceAA p_mode) = 0;
|
||||
|
||||
virtual void viewport_set_use_debanding(RID p_viewport, bool p_use_debanding) = 0;
|
||||
|
||||
enum ViewportRenderInfo {
|
||||
VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME,
|
||||
VIEWPORT_RENDER_INFO_VERTICES_IN_FRAME,
|
||||
|
|
Loading…
Reference in a new issue