summaryrefslogtreecommitdiff
path: root/servers/rendering/renderer_rd/effects
diff options
context:
space:
mode:
Diffstat (limited to 'servers/rendering/renderer_rd/effects')
-rw-r--r--servers/rendering/renderer_rd/effects/bokeh_dof.cpp94
-rw-r--r--servers/rendering/renderer_rd/effects/bokeh_dof.h9
-rw-r--r--servers/rendering/renderer_rd/effects/copy_effects.cpp150
-rw-r--r--servers/rendering/renderer_rd/effects/copy_effects.h42
-rw-r--r--servers/rendering/renderer_rd/effects/fsr.cpp128
-rw-r--r--servers/rendering/renderer_rd/effects/fsr.h72
-rw-r--r--servers/rendering/renderer_rd/effects/resolve.h4
-rw-r--r--servers/rendering/renderer_rd/effects/ss_effects.cpp358
-rw-r--r--servers/rendering/renderer_rd/effects/ss_effects.h90
-rw-r--r--servers/rendering/renderer_rd/effects/taa.cpp138
-rw-r--r--servers/rendering/renderer_rd/effects/taa.h68
-rw-r--r--servers/rendering/renderer_rd/effects/tone_mapper.cpp4
-rw-r--r--servers/rendering/renderer_rd/effects/tone_mapper.h4
-rw-r--r--servers/rendering/renderer_rd/effects/vrs.cpp65
-rw-r--r--servers/rendering/renderer_rd/effects/vrs.h2
15 files changed, 973 insertions, 255 deletions
diff --git a/servers/rendering/renderer_rd/effects/bokeh_dof.cpp b/servers/rendering/renderer_rd/effects/bokeh_dof.cpp
index cc7441776d..27850695b0 100644
--- a/servers/rendering/renderer_rd/effects/bokeh_dof.cpp
+++ b/servers/rendering/renderer_rd/effects/bokeh_dof.cpp
@@ -33,6 +33,8 @@
#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"
+#include "servers/rendering/rendering_server_default.h"
+#include "servers/rendering/storage/camera_attributes_storage.h"
using namespace RendererRD;
@@ -84,7 +86,7 @@ BokehDOF::~BokehDOF() {
}
}
-void BokehDOF::bokeh_dof_compute(const BokehBuffers &p_buffers, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_bokeh_size, RenderingServer::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, bool p_use_jitter, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal) {
+void BokehDOF::bokeh_dof_compute(const BokehBuffers &p_buffers, RID p_camera_attributes, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal) {
ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute version of bokeh depth of field with the mobile renderer.");
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
@@ -92,22 +94,39 @@ void BokehDOF::bokeh_dof_compute(const BokehBuffers &p_buffers, bool p_dof_far,
MaterialStorage *material_storage = MaterialStorage::get_singleton();
ERR_FAIL_NULL(material_storage);
+ bool dof_far = RSG::camera_attributes->camera_attributes_get_dof_far_enabled(p_camera_attributes);
+ float dof_far_begin = RSG::camera_attributes->camera_attributes_get_dof_far_distance(p_camera_attributes);
+ float dof_far_size = RSG::camera_attributes->camera_attributes_get_dof_far_transition(p_camera_attributes);
+ bool dof_near = RSG::camera_attributes->camera_attributes_get_dof_near_enabled(p_camera_attributes);
+ float dof_near_begin = RSG::camera_attributes->camera_attributes_get_dof_near_distance(p_camera_attributes);
+ float dof_near_size = RSG::camera_attributes->camera_attributes_get_dof_near_transition(p_camera_attributes);
+ float bokeh_size = RSG::camera_attributes->camera_attributes_get_dof_blur_amount(p_camera_attributes) * 64; // Base 64 pixel radius.
+
+ bool use_jitter = RSG::camera_attributes->camera_attributes_get_dof_blur_use_jitter();
+ RS::DOFBokehShape bokeh_shape = RSG::camera_attributes->camera_attributes_get_dof_blur_bokeh_shape();
+ RS::DOFBlurQuality blur_quality = RSG::camera_attributes->camera_attributes_get_dof_blur_quality();
+
// setup our push constant
memset(&bokeh.push_constant, 0, sizeof(BokehPushConstant));
- bokeh.push_constant.blur_far_active = p_dof_far;
- bokeh.push_constant.blur_far_begin = p_dof_far_begin;
- bokeh.push_constant.blur_far_end = p_dof_far_begin + p_dof_far_size;
-
- bokeh.push_constant.blur_near_active = p_dof_near;
- bokeh.push_constant.blur_near_begin = p_dof_near_begin;
- bokeh.push_constant.blur_near_end = MAX(0, p_dof_near_begin - p_dof_near_size);
- bokeh.push_constant.use_jitter = p_use_jitter;
+ bokeh.push_constant.blur_far_active = dof_far;
+ bokeh.push_constant.blur_far_begin = dof_far_begin;
+ bokeh.push_constant.blur_far_end = dof_far_begin + dof_far_size; // Only used with non-physically-based.
+ bokeh.push_constant.use_physical_far = dof_far_size < 0.0;
+ bokeh.push_constant.blur_size_far = bokeh_size; // Only used with physically-based.
+
+ bokeh.push_constant.blur_near_active = dof_near;
+ bokeh.push_constant.blur_near_begin = dof_near_begin;
+ bokeh.push_constant.blur_near_end = dof_near_begin - dof_near_size; // Only used with non-physically-based.
+ bokeh.push_constant.use_physical_near = dof_near_size < 0.0;
+ bokeh.push_constant.blur_size_near = bokeh_size; // Only used with physically-based.
+
+ bokeh.push_constant.use_jitter = use_jitter;
bokeh.push_constant.jitter_seed = Math::randf() * 1000.0;
bokeh.push_constant.z_near = p_cam_znear;
bokeh.push_constant.z_far = p_cam_zfar;
bokeh.push_constant.orthogonal = p_cam_orthogonal;
- bokeh.push_constant.blur_size = p_bokeh_size;
+ bokeh.push_constant.blur_size = (dof_near_size < 0.0 && dof_far_size < 0.0) ? 32 : bokeh_size; // Cap with physically-based to keep performance reasonable.
bokeh.push_constant.second_pass = false;
bokeh.push_constant.half_size = false;
@@ -150,9 +169,9 @@ void BokehDOF::bokeh_dof_compute(const BokehBuffers &p_buffers, bool p_dof_far,
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_buffers.base_texture_size.x, p_buffers.base_texture_size.y, 1);
RD::get_singleton()->compute_list_add_barrier(compute_list);
- if (p_bokeh_shape == RS::DOF_BOKEH_BOX || p_bokeh_shape == RS::DOF_BOKEH_HEXAGON) {
+ if (bokeh_shape == RS::DOF_BOKEH_BOX || bokeh_shape == RS::DOF_BOKEH_HEXAGON) {
//second pass
- BokehMode mode = p_bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX : BOKEH_GEN_BOKEH_HEXAGONAL;
+ BokehMode mode = bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX : BOKEH_GEN_BOKEH_HEXAGONAL;
shader = bokeh.compute_shader.version_get_shader(bokeh.shader_version, mode);
ERR_FAIL_COND(shader.is_null());
@@ -160,9 +179,9 @@ void BokehDOF::bokeh_dof_compute(const BokehBuffers &p_buffers, bool p_dof_far,
static const int quality_samples[4] = { 6, 12, 12, 24 };
- bokeh.push_constant.steps = quality_samples[p_quality];
+ bokeh.push_constant.steps = quality_samples[blur_quality];
- if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) {
+ if (blur_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || blur_quality == RS::DOF_BLUR_QUALITY_LOW) {
//box and hexagon are more or less the same, and they can work in either half (very low and low quality) or full (medium and high quality_ sizes)
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_half_image0), 0);
@@ -187,7 +206,7 @@ void BokehDOF::bokeh_dof_compute(const BokehBuffers &p_buffers, bool p_dof_far,
//third pass
bokeh.push_constant.second_pass = true;
- if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) {
+ if (blur_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || blur_quality == RS::DOF_BLUR_QUALITY_LOW) {
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_half_image1), 0);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_half_texture0), 1);
} else {
@@ -200,7 +219,7 @@ void BokehDOF::bokeh_dof_compute(const BokehBuffers &p_buffers, bool p_dof_far,
RD::get_singleton()->compute_list_dispatch_threads(compute_list, bokeh.push_constant.size[0], bokeh.push_constant.size[1], 1);
RD::get_singleton()->compute_list_add_barrier(compute_list);
- if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) {
+ if (blur_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || blur_quality == RS::DOF_BLUR_QUALITY_LOW) {
//forth pass, upscale for low quality
shader = bokeh.compute_shader.version_get_shader(bokeh.shader_version, BOKEH_COMPOSITE);
@@ -232,7 +251,7 @@ void BokehDOF::bokeh_dof_compute(const BokehBuffers &p_buffers, bool p_dof_far,
static const float quality_scale[4] = { 8.0, 4.0, 1.0, 0.5 };
bokeh.push_constant.steps = 0;
- bokeh.push_constant.blur_scale = quality_scale[p_quality];
+ bokeh.push_constant.blur_scale = quality_scale[blur_quality];
//circle always runs in half size, otherwise too expensive
@@ -273,7 +292,7 @@ void BokehDOF::bokeh_dof_compute(const BokehBuffers &p_buffers, bool p_dof_far,
RD::get_singleton()->compute_list_end();
}
-void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_dof_blur_amount, RenderingServer::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal) {
+void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, RID p_camera_attributes, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal) {
ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't blur-based depth of field with the clustered renderer.");
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
@@ -281,6 +300,17 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, f
MaterialStorage *material_storage = MaterialStorage::get_singleton();
ERR_FAIL_NULL(material_storage);
+ bool dof_far = RSG::camera_attributes->camera_attributes_get_dof_far_enabled(p_camera_attributes);
+ float dof_far_begin = RSG::camera_attributes->camera_attributes_get_dof_far_distance(p_camera_attributes);
+ float dof_far_size = RSG::camera_attributes->camera_attributes_get_dof_far_transition(p_camera_attributes);
+ bool dof_near = RSG::camera_attributes->camera_attributes_get_dof_near_enabled(p_camera_attributes);
+ float dof_near_begin = RSG::camera_attributes->camera_attributes_get_dof_near_distance(p_camera_attributes);
+ float dof_near_size = RSG::camera_attributes->camera_attributes_get_dof_near_transition(p_camera_attributes);
+ float bokeh_size = RSG::camera_attributes->camera_attributes_get_dof_blur_amount(p_camera_attributes) * 64; // Base 64 pixel radius.
+
+ RS::DOFBokehShape bokeh_shape = RSG::camera_attributes->camera_attributes_get_dof_blur_bokeh_shape();
+ RS::DOFBlurQuality blur_quality = RSG::camera_attributes->camera_attributes_get_dof_blur_quality();
+
// setup our base push constant
memset(&bokeh.push_constant, 0, sizeof(BokehPushConstant));
@@ -292,7 +322,7 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, f
bokeh.push_constant.second_pass = false;
bokeh.push_constant.half_size = false;
- bokeh.push_constant.blur_size = p_dof_blur_amount;
+ bokeh.push_constant.blur_size = bokeh_size;
// setup our uniforms
RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
@@ -307,17 +337,17 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, f
RD::Uniform u_weight_texture2(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.weight_texture[2] }));
RD::Uniform u_weight_texture3(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.weight_texture[3] }));
- if (p_dof_far || p_dof_near) {
- if (p_dof_far) {
+ if (dof_far || dof_near) {
+ if (dof_far) {
bokeh.push_constant.blur_far_active = true;
- bokeh.push_constant.blur_far_begin = p_dof_far_begin;
- bokeh.push_constant.blur_far_end = p_dof_far_begin + p_dof_far_size;
+ bokeh.push_constant.blur_far_begin = dof_far_begin;
+ bokeh.push_constant.blur_far_end = dof_far_begin + dof_far_size;
}
- if (p_dof_near) {
+ if (dof_near) {
bokeh.push_constant.blur_near_active = true;
- bokeh.push_constant.blur_near_begin = p_dof_near_begin;
- bokeh.push_constant.blur_near_end = p_dof_near_begin - p_dof_near_size;
+ bokeh.push_constant.blur_near_begin = dof_near_begin;
+ bokeh.push_constant.blur_near_end = dof_near_begin - dof_near_size;
}
{
@@ -337,14 +367,14 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, f
RD::get_singleton()->draw_list_end();
}
- if (p_bokeh_shape == RS::DOF_BOKEH_BOX || p_bokeh_shape == RS::DOF_BOKEH_HEXAGON) {
+ if (bokeh_shape == RS::DOF_BOKEH_BOX || bokeh_shape == RS::DOF_BOKEH_HEXAGON) {
// double pass approach
- BokehMode mode = p_bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX : BOKEH_GEN_BOKEH_HEXAGONAL;
+ BokehMode mode = bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX : BOKEH_GEN_BOKEH_HEXAGONAL;
RID shader = bokeh.raster_shader.version_get_shader(bokeh.shader_version, mode);
ERR_FAIL_COND(shader.is_null());
- if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) {
+ if (blur_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || blur_quality == RS::DOF_BLUR_QUALITY_LOW) {
//box and hexagon are more or less the same, and they can work in either half (very low and low quality) or full (medium and high quality_ sizes)
bokeh.push_constant.size[0] = p_buffers.base_texture_size.x >> 1;
bokeh.push_constant.size[1] = p_buffers.base_texture_size.y >> 1;
@@ -354,7 +384,7 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, f
static const int quality_samples[4] = { 6, 12, 12, 24 };
bokeh.push_constant.blur_scale = 0.5;
- bokeh.push_constant.steps = quality_samples[p_quality];
+ bokeh.push_constant.steps = quality_samples[blur_quality];
RID framebuffer = bokeh.push_constant.half_size ? p_buffers.half_fb[0] : p_buffers.secondary_fb;
@@ -373,7 +403,7 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, f
// Pass 2
if (!bokeh.push_constant.half_size) {
// do not output weight, we're writing back into our base buffer
- mode = p_bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX_NOWEIGHT : BOKEH_GEN_BOKEH_HEXAGONAL_NOWEIGHT;
+ mode = bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX_NOWEIGHT : BOKEH_GEN_BOKEH_HEXAGONAL_NOWEIGHT;
shader = bokeh.raster_shader.version_get_shader(bokeh.shader_version, mode);
ERR_FAIL_COND(shader.is_null());
@@ -432,7 +462,7 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, f
}
static const float quality_scale[4] = { 8.0, 4.0, 1.0, 0.5 };
- bokeh.push_constant.blur_scale = quality_scale[p_quality];
+ bokeh.push_constant.blur_scale = quality_scale[blur_quality];
bokeh.push_constant.steps = 0.0;
RID framebuffer = bokeh.push_constant.half_size ? p_buffers.half_fb[0] : p_buffers.secondary_fb;
diff --git a/servers/rendering/renderer_rd/effects/bokeh_dof.h b/servers/rendering/renderer_rd/effects/bokeh_dof.h
index 30b33be168..33dbdfcdc1 100644
--- a/servers/rendering/renderer_rd/effects/bokeh_dof.h
+++ b/servers/rendering/renderer_rd/effects/bokeh_dof.h
@@ -66,6 +66,11 @@ private:
uint32_t use_jitter;
float jitter_seed;
+ uint32_t use_physical_near;
+ uint32_t use_physical_far;
+
+ float blur_size_near;
+ float blur_size_far;
uint32_t pad[2];
};
@@ -111,8 +116,8 @@ public:
BokehDOF(bool p_prefer_raster_effects);
~BokehDOF();
- void bokeh_dof_compute(const BokehBuffers &p_buffers, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_bokeh_size, RS::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, bool p_use_jitter, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal);
- void bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_dof_blur_amount, RenderingServer::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal);
+ void bokeh_dof_compute(const BokehBuffers &p_buffers, RID p_camera_attributes, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal);
+ void bokeh_dof_raster(const BokehBuffers &p_buffers, RID p_camera_attributes, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal);
};
} // namespace RendererRD
diff --git a/servers/rendering/renderer_rd/effects/copy_effects.cpp b/servers/rendering/renderer_rd/effects/copy_effects.cpp
index 5507483cee..9fda54a34d 100644
--- a/servers/rendering/renderer_rd/effects/copy_effects.cpp
+++ b/servers/rendering/renderer_rd/effects/copy_effects.cpp
@@ -56,6 +56,7 @@ CopyEffects::CopyEffects(bool p_prefer_raster_effects) {
blur_modes.push_back("\n#define MODE_GAUSSIAN_GLOW\n"); // BLUR_MODE_GAUSSIAN_GLOW
blur_modes.push_back("\n#define MODE_GAUSSIAN_GLOW\n#define GLOW_USE_AUTO_EXPOSURE\n"); // BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE
blur_modes.push_back("\n#define MODE_COPY\n"); // BLUR_MODE_COPY
+ blur_modes.push_back("\n#define MODE_SET_COLOR\n"); // BLUR_MODE_SET_COLOR
blur_raster.shader.initialize(blur_modes);
memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
@@ -105,6 +106,7 @@ CopyEffects::CopyEffects(bool p_prefer_raster_effects) {
copy_modes.push_back("\n#define MODE_TWO_SOURCES\n"); // COPY_TO_FB_COPY2
copy_modes.push_back("\n#define MULTIVIEW\n"); // COPY_TO_FB_MULTIVIEW
copy_modes.push_back("\n#define MULTIVIEW\n#define MODE_TWO_SOURCES\n"); // COPY_TO_FB_MULTIVIEW_WITH_DEPTH
+ copy_modes.push_back("\n#define MODE_SET_COLOR\n"); // COPY_TO_FB_SET_COLOR
copy_to_fb.shader.initialize(copy_modes);
@@ -357,8 +359,8 @@ void CopyEffects::copy_to_rect(RID p_source_rd_texture, RID p_dest_texture, cons
copy.push_constant.flags |= COPY_FLAG_ALPHA_TO_ONE;
}
- copy.push_constant.section[0] = 0;
- copy.push_constant.section[1] = 0;
+ copy.push_constant.section[0] = p_rect.position.x;
+ copy.push_constant.section[1] = p_rect.position.y;
copy.push_constant.section[2] = p_rect.size.width;
copy.push_constant.section[3] = p_rect.size.height;
copy.push_constant.target[0] = p_rect.position.x;
@@ -508,16 +510,18 @@ void CopyEffects::copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuff
memset(&copy_to_fb.push_constant, 0, sizeof(CopyToFbPushConstant));
- copy_to_fb.push_constant.use_section = true;
+ copy_to_fb.push_constant.flags |= COPY_TO_FB_FLAG_USE_SECTION;
copy_to_fb.push_constant.section[0] = p_uv_rect.position.x;
copy_to_fb.push_constant.section[1] = p_uv_rect.position.y;
copy_to_fb.push_constant.section[2] = p_uv_rect.size.x;
copy_to_fb.push_constant.section[3] = p_uv_rect.size.y;
if (p_flip_y) {
- copy_to_fb.push_constant.flip_y = true;
+ copy_to_fb.push_constant.flags |= COPY_TO_FB_FLAG_FLIP_Y;
}
+ copy_to_fb.push_constant.luminance_multiplier = 1.0;
+
// setup our uniforms
RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
@@ -535,25 +539,35 @@ void CopyEffects::copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuff
RD::get_singleton()->draw_list_draw(draw_list, true);
}
-void CopyEffects::copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y, bool p_force_luminance, bool p_alpha_to_zero, bool p_srgb, RID p_secondary, bool p_multiview) {
+void CopyEffects::copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y, bool p_force_luminance, bool p_alpha_to_zero, bool p_srgb, RID p_secondary, bool p_multiview, bool p_alpha_to_one, bool p_linear) {
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
ERR_FAIL_NULL(uniform_set_cache);
MaterialStorage *material_storage = MaterialStorage::get_singleton();
ERR_FAIL_NULL(material_storage);
memset(&copy_to_fb.push_constant, 0, sizeof(CopyToFbPushConstant));
+ copy_to_fb.push_constant.luminance_multiplier = 1.0;
if (p_flip_y) {
- copy_to_fb.push_constant.flip_y = true;
+ copy_to_fb.push_constant.flags |= COPY_TO_FB_FLAG_FLIP_Y;
}
if (p_force_luminance) {
- copy_to_fb.push_constant.force_luminance = true;
+ copy_to_fb.push_constant.flags |= COPY_TO_FB_FLAG_FORCE_LUMINANCE;
}
if (p_alpha_to_zero) {
- copy_to_fb.push_constant.alpha_to_zero = true;
+ copy_to_fb.push_constant.flags |= COPY_TO_FB_FLAG_ALPHA_TO_ZERO;
}
if (p_srgb) {
- copy_to_fb.push_constant.srgb = true;
+ copy_to_fb.push_constant.flags |= COPY_TO_FB_FLAG_SRGB;
+ }
+ if (p_alpha_to_one) {
+ copy_to_fb.push_constant.flags |= COPY_TO_FB_FLAG_ALPHA_TO_ONE;
+ }
+ if (p_linear) {
+ // Used for copying to a linear buffer. In the mobile renderer we divide the contents of the linear buffer
+ // to allow for a wider effective range.
+ copy_to_fb.push_constant.flags |= COPY_TO_FB_FLAG_LINEAR;
+ copy_to_fb.push_constant.luminance_multiplier = prefer_raster_effects ? 2.0 : 1.0;
}
// setup our uniforms
@@ -608,15 +622,13 @@ void CopyEffects::copy_raster(RID p_source_texture, RID p_dest_framebuffer) {
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[BLUR_MODE_COPY].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_texture), 0);
RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
-
- memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant));
RD::get_singleton()->draw_list_draw(draw_list, true);
RD::get_singleton()->draw_list_end();
}
-void CopyEffects::gaussian_blur(RID p_source_rd_texture, RID p_texture, const Rect2i &p_region, bool p_8bit_dst) {
+void CopyEffects::gaussian_blur(RID p_source_rd_texture, RID p_texture, const Rect2i &p_region, const Size2i &p_size, bool p_8bit_dst) {
ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the gaussian blur with the mobile renderer.");
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
@@ -628,8 +640,10 @@ void CopyEffects::gaussian_blur(RID p_source_rd_texture, RID p_texture, const Re
copy.push_constant.section[0] = p_region.position.x;
copy.push_constant.section[1] = p_region.position.y;
- copy.push_constant.section[2] = p_region.size.width;
- copy.push_constant.section[3] = p_region.size.height;
+ copy.push_constant.target[0] = p_region.position.x;
+ copy.push_constant.target[1] = p_region.position.y;
+ copy.push_constant.section[2] = p_size.width;
+ copy.push_constant.section[3] = p_size.height;
// setup our uniforms
RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
@@ -641,7 +655,6 @@ void CopyEffects::gaussian_blur(RID p_source_rd_texture, RID p_texture, const Re
RID shader = copy.shader.version_get_shader(copy.shader_version, mode);
ERR_FAIL_COND(shader.is_null());
- //HORIZONTAL
RD::DrawListID compute_list = RD::get_singleton()->compute_list_begin();
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode]);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
@@ -654,7 +667,44 @@ void CopyEffects::gaussian_blur(RID p_source_rd_texture, RID p_texture, const Re
RD::get_singleton()->compute_list_end();
}
-void CopyEffects::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_grey) {
+void CopyEffects::gaussian_blur_raster(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_region, const Size2i &p_size) {
+ ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of the gaussian blur with the clustered renderer.");
+
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ RID dest_framebuffer = FramebufferCacheRD::get_singleton()->get_cache(p_dest_texture);
+
+ memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
+
+ BlurRasterMode blur_mode = BLUR_MODE_GAUSSIAN_BLUR;
+
+ blur_raster.push_constant.pixel_size[0] = 1.0 / float(p_size.x);
+ blur_raster.push_constant.pixel_size[1] = 1.0 / float(p_size.y);
+
+ // setup our uniforms
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture }));
+
+ RID shader = blur_raster.shader.version_get_shader(blur_raster.shader_version, blur_mode);
+ ERR_FAIL_COND(shader.is_null());
+
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(dest_framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
+
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
+
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant));
+
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+}
+
+void CopyEffects::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_scale) {
ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the gaussian glow with the mobile renderer.");
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
@@ -678,7 +728,7 @@ void CopyEffects::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, con
copy.push_constant.glow_white = 0; //actually unused
copy.push_constant.glow_luminance_cap = p_luminance_cap;
- copy.push_constant.glow_auto_exposure_grey = p_auto_exposure_grey; //unused also
+ copy.push_constant.glow_auto_exposure_scale = p_auto_exposure_scale; //unused also
// setup our uniforms
RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
@@ -698,14 +748,14 @@ void CopyEffects::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, con
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_auto_exposure), 1);
}
- copy.push_constant.flags = base_flags | (p_first_pass ? COPY_FLAG_GLOW_FIRST_PASS : 0) | (p_high_quality ? COPY_FLAG_HIGH_QUALITY_GLOW : 0);
+ copy.push_constant.flags = base_flags | (p_first_pass ? COPY_FLAG_GLOW_FIRST_PASS : 0);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_size.width, p_size.height, 1);
RD::get_singleton()->compute_list_end();
}
-void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, float p_luminance_multiplier, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Size2i &p_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_grey) {
+void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, RID p_half_texture, RID p_dest_texture, float p_luminance_multiplier, const Size2i &p_size, float p_strength, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_scale) {
ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of the gaussian glow with the clustered renderer.");
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
@@ -713,6 +763,9 @@ void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, float p_luminanc
MaterialStorage *material_storage = MaterialStorage::get_singleton();
ERR_FAIL_NULL(material_storage);
+ RID half_framebuffer = FramebufferCacheRD::get_singleton()->get_cache(p_half_texture);
+ RID dest_framebuffer = FramebufferCacheRD::get_singleton()->get_cache(p_dest_texture);
+
memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
BlurRasterMode blur_mode = p_first_pass && p_auto_exposure.is_valid() ? BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE : BLUR_MODE_GAUSSIAN_GLOW;
@@ -729,7 +782,7 @@ void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, float p_luminanc
blur_raster.push_constant.glow_white = 0; //actually unused
blur_raster.push_constant.glow_luminance_cap = p_luminance_cap;
- blur_raster.push_constant.glow_auto_exposure_grey = p_auto_exposure_grey; //unused also
+ blur_raster.push_constant.glow_auto_exposure_scale = p_auto_exposure_scale; //unused also
blur_raster.push_constant.luminance_multiplier = p_luminance_multiplier;
@@ -737,14 +790,14 @@ void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, float p_luminanc
RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture }));
- RD::Uniform u_rd_texture_half(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_rd_texture_half }));
+ RD::Uniform u_half_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_half_texture }));
RID shader = blur_raster.shader.version_get_shader(blur_raster.shader_version, blur_mode);
ERR_FAIL_COND(shader.is_null());
//HORIZONTAL
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer_half, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer_half)));
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(half_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(half_framebuffer)));
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
if (p_auto_exposure.is_valid() && p_first_pass) {
RD::Uniform u_auto_exposure(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_auto_exposure }));
@@ -764,9 +817,9 @@ void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, float p_luminanc
ERR_FAIL_COND(shader.is_null());
//VERTICAL
- draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_rd_texture_half), 0);
+ draw_list = RD::get_singleton()->draw_list_begin(dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(dest_framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_half_texture), 0);
RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
blur_raster.push_constant.flags = base_flags;
@@ -810,9 +863,11 @@ void CopyEffects::make_mipmap(RID p_source_rd_texture, RID p_dest_texture, const
RD::get_singleton()->compute_list_end();
}
-void CopyEffects::make_mipmap_raster(RID p_source_rd_texture, RID p_dest_framebuffer, const Size2i &p_size) {
+void CopyEffects::make_mipmap_raster(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size) {
ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of mipmap with the clustered renderer.");
+ RID dest_framebuffer = FramebufferCacheRD::get_singleton()->get_cache(p_dest_texture);
+
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
ERR_FAIL_NULL(uniform_set_cache);
MaterialStorage *material_storage = MaterialStorage::get_singleton();
@@ -833,8 +888,8 @@ void CopyEffects::make_mipmap_raster(RID p_source_rd_texture, RID p_dest_framebu
RID shader = blur_raster.shader.version_get_shader(blur_raster.shader_version, mode);
ERR_FAIL_COND(shader.is_null());
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(dest_framebuffer)));
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant));
@@ -877,6 +932,36 @@ void CopyEffects::set_color(RID p_dest_texture, const Color &p_color, const Rect
RD::get_singleton()->compute_list_end();
}
+void CopyEffects::set_color_raster(RID p_dest_texture, const Color &p_color, const Rect2i &p_region) {
+ ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of the set_color shader with the clustered renderer.");
+
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ memset(&copy_to_fb.push_constant, 0, sizeof(CopyToFbPushConstant));
+
+ copy_to_fb.push_constant.set_color[0] = p_color.r;
+ copy_to_fb.push_constant.set_color[1] = p_color.g;
+ copy_to_fb.push_constant.set_color[2] = p_color.b;
+ copy_to_fb.push_constant.set_color[3] = p_color.a;
+
+ RID dest_framebuffer = FramebufferCacheRD::get_singleton()->get_cache(p_dest_texture);
+
+ CopyToFBMode mode = COPY_TO_FB_SET_COLOR;
+
+ RID shader = copy_to_fb.shader.version_get_shader(copy_to_fb.shader_version, mode);
+ ERR_FAIL_COND(shader.is_null());
+
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, p_region);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy_to_fb.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(dest_framebuffer)));
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &copy_to_fb.push_constant, sizeof(CopyToFbPushConstant));
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+}
+
void CopyEffects::copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuffer, const Rect2 &p_rect, const Vector2 &p_dst_size, float p_z_near, float p_z_far, bool p_dp_flip) {
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
ERR_FAIL_NULL(uniform_set_cache);
@@ -1070,7 +1155,8 @@ void CopyEffects::cubemap_roughness(RID p_source_rd_texture, RID p_dest_texture,
memset(&roughness.push_constant, 0, sizeof(CubemapRoughnessPushConstant));
roughness.push_constant.face_id = p_face_id > 9 ? 0 : p_face_id;
- roughness.push_constant.roughness = p_roughness * p_roughness; // Shader expects roughness, not perceptual roughness, so multiply before passing in.
+ // Remap to perceptual-roughness^2 to create more detail in lower mips and match the mapping of cubemap_filter.
+ roughness.push_constant.roughness = p_roughness * p_roughness;
roughness.push_constant.sample_count = p_sample_count;
roughness.push_constant.use_direct_write = p_roughness == 0.0;
roughness.push_constant.face_size = p_size;
@@ -1117,8 +1203,8 @@ void CopyEffects::cubemap_roughness_raster(RID p_source_rd_texture, RID p_dest_f
roughness.push_constant.use_direct_write = p_roughness == 0.0;
roughness.push_constant.face_size = p_size;
- // setup our uniforms
- RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ // Setup our uniforms.
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture }));
diff --git a/servers/rendering/renderer_rd/effects/copy_effects.h b/servers/rendering/renderer_rd/effects/copy_effects.h
index d25555eee5..a0904f0b8e 100644
--- a/servers/rendering/renderer_rd/effects/copy_effects.h
+++ b/servers/rendering/renderer_rd/effects/copy_effects.h
@@ -63,6 +63,8 @@ private:
BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE,
BLUR_MODE_COPY,
+ BLUR_MODE_SET_COLOR,
+
BLUR_MODE_MAX
};
@@ -86,7 +88,7 @@ private:
float glow_exposure;
float glow_white;
float glow_luminance_cap;
- float glow_auto_exposure_grey;
+ float glow_auto_exposure_scale;
float luminance_multiplier;
float res1;
@@ -130,8 +132,7 @@ private:
COPY_FLAG_FLIP_Y = (1 << 5),
COPY_FLAG_FORCE_LUMINANCE = (1 << 6),
COPY_FLAG_ALL_SOURCE = (1 << 7),
- COPY_FLAG_HIGH_QUALITY_GLOW = (1 << 8),
- COPY_FLAG_ALPHA_TO_ONE = (1 << 9),
+ COPY_FLAG_ALPHA_TO_ONE = (1 << 8),
};
struct CopyPushConstant {
@@ -148,7 +149,7 @@ private:
float glow_exposure;
float glow_white;
float glow_luminance_cap;
- float glow_auto_exposure_grey;
+ float glow_auto_exposure_scale;
// DOF.
float camera_z_far;
float camera_z_near;
@@ -174,19 +175,28 @@ private:
COPY_TO_FB_MULTIVIEW,
COPY_TO_FB_MULTIVIEW_WITH_DEPTH,
+
+ COPY_TO_FB_SET_COLOR,
COPY_TO_FB_MAX,
};
+ enum CopyToFBFlags {
+ COPY_TO_FB_FLAG_FLIP_Y = (1 << 0),
+ COPY_TO_FB_FLAG_USE_SECTION = (1 << 1),
+ COPY_TO_FB_FLAG_FORCE_LUMINANCE = (1 << 2),
+ COPY_TO_FB_FLAG_ALPHA_TO_ZERO = (1 << 3),
+ COPY_TO_FB_FLAG_SRGB = (1 << 4),
+ COPY_TO_FB_FLAG_ALPHA_TO_ONE = (1 << 5),
+ COPY_TO_FB_FLAG_LINEAR = (1 << 6),
+ };
+
struct CopyToFbPushConstant {
float section[4];
float pixel_size[2];
- uint32_t flip_y;
- uint32_t use_section;
+ float luminance_multiplier;
+ uint32_t flags;
- uint32_t force_luminance;
- uint32_t alpha_to_zero;
- uint32_t srgb;
- uint32_t pad;
+ float set_color[4];
};
struct CopyToFb {
@@ -316,18 +326,20 @@ public:
void copy_cubemap_to_panorama(RID p_source_cube, RID p_dest_panorama, const Size2i &p_panorama_size, float p_lod, bool p_is_array);
void copy_depth_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false);
void copy_depth_to_rect_and_linearize(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y, float p_z_near, float p_z_far);
- void copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_alpha_to_zero = false, bool p_srgb = false, RID p_secondary = RID(), bool p_multiview = false);
+ void copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_alpha_to_zero = false, bool p_srgb = false, RID p_secondary = RID(), bool p_multiview = false, bool alpha_to_one = false, bool p_linear = false);
void copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_uv_rect, RD::DrawListID p_draw_list, bool p_flip_y = false, bool p_panorama = false);
void copy_raster(RID p_source_texture, RID p_dest_framebuffer);
- void gaussian_blur(RID p_source_rd_texture, RID p_texture, const Rect2i &p_region, bool p_8bit_dst = false);
- void gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0);
- void gaussian_glow_raster(RID p_source_rd_texture, float p_luminance_multiplier, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0);
+ void gaussian_blur(RID p_source_rd_texture, RID p_texture, const Rect2i &p_region, const Size2i &p_size, bool p_8bit_dst = false);
+ void gaussian_blur_raster(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_region, const Size2i &p_size);
+ void gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength = 1.0, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_scale = 1.0);
+ void gaussian_glow_raster(RID p_source_rd_texture, RID p_half_texture, RID p_dest_texture, float p_luminance_multiplier, const Size2i &p_size, float p_strength = 1.0, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_scale = 1.0);
void make_mipmap(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size);
- void make_mipmap_raster(RID p_source_rd_texture, RID p_dest_framebuffer, const Size2i &p_size);
+ void make_mipmap_raster(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size);
void set_color(RID p_dest_texture, const Color &p_color, const Rect2i &p_region, bool p_8bit_dst = false);
+ void set_color_raster(RID p_dest_texture, const Color &p_color, const Rect2i &p_region);
void copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuffer, const Rect2 &p_rect, const Vector2 &p_dst_size, float p_z_near, float p_z_far, bool p_dp_flip);
void cubemap_downsample(RID p_source_cubemap, RID p_dest_cubemap, const Size2i &p_size);
diff --git a/servers/rendering/renderer_rd/effects/fsr.cpp b/servers/rendering/renderer_rd/effects/fsr.cpp
new file mode 100644
index 0000000000..92b34ede0e
--- /dev/null
+++ b/servers/rendering/renderer_rd/effects/fsr.cpp
@@ -0,0 +1,128 @@
+/*************************************************************************/
+/* fsr.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "fsr.h"
+#include "../storage_rd/material_storage.h"
+#include "../uniform_set_cache_rd.h"
+
+using namespace RendererRD;
+
+FSR::FSR() {
+ Vector<String> FSR_upscale_modes;
+
+#if defined(MACOS_ENABLED) || defined(IOS_ENABLED)
+ // MoltenVK does not support some of the operations used by the normal mode of FSR. Fallback works just fine though.
+ FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_FALLBACK\n");
+#else
+ // Everyone else can use normal mode when available.
+ if (RD::get_singleton()->has_feature(RD::SUPPORTS_FSR_HALF_FLOAT)) {
+ FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_NORMAL\n");
+ } else {
+ FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_FALLBACK\n");
+ }
+#endif
+
+ fsr_shader.initialize(FSR_upscale_modes);
+
+ shader_version = fsr_shader.version_create();
+ pipeline = RD::get_singleton()->compute_pipeline_create(fsr_shader.version_get_shader(shader_version, 0));
+}
+
+FSR::~FSR() {
+ fsr_shader.version_free(shader_version);
+}
+
+void FSR::fsr_upscale(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_source_rd_texture, RID p_destination_texture) {
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ Size2i internal_size = p_render_buffers->get_internal_size();
+ Size2i target_size = p_render_buffers->get_target_size();
+ float fsr_upscale_sharpness = p_render_buffers->get_fsr_sharpness();
+
+ if (!p_render_buffers->has_texture(SNAME("FSR"), SNAME("upscale_texture"))) {
+ RD::DataFormat format = p_render_buffers->get_base_data_format();
+ uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
+ uint32_t layers = 1; // we only need one layer, in multiview we're processing one layer at a time.
+
+ p_render_buffers->create_texture(SNAME("FSR"), SNAME("upscale_texture"), format, usage_bits, RD::TEXTURE_SAMPLES_1, target_size, layers);
+ }
+
+ RID upscale_texture = p_render_buffers->get_texture(SNAME("FSR"), SNAME("upscale_texture"));
+
+ FSRUpscalePushConstant push_constant;
+ memset(&push_constant, 0, sizeof(FSRUpscalePushConstant));
+
+ int dispatch_x = (target_size.x + 15) / 16;
+ int dispatch_y = (target_size.y + 15) / 16;
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, pipeline);
+
+ push_constant.resolution_width = internal_size.width;
+ push_constant.resolution_height = internal_size.height;
+ push_constant.upscaled_width = target_size.width;
+ push_constant.upscaled_height = target_size.height;
+ push_constant.sharpness = fsr_upscale_sharpness;
+
+ RID shader = fsr_shader.version_get_shader(shader_version, 0);
+ ERR_FAIL_COND(shader.is_null());
+
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ //FSR Easc
+ RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, { default_sampler, p_source_rd_texture });
+ RD::Uniform u_upscale_texture(RD::UNIFORM_TYPE_IMAGE, 0, { upscale_texture });
+
+ push_constant.pass = FSR_UPSCALE_PASS_EASU;
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_upscale_texture), 1);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(FSRUpscalePushConstant));
+
+ RD::get_singleton()->compute_list_dispatch(compute_list, dispatch_x, dispatch_y, 1);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ //FSR Rcas
+ RD::Uniform u_upscale_texture_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, { default_sampler, upscale_texture });
+ RD::Uniform u_destination_texture(RD::UNIFORM_TYPE_IMAGE, 0, { p_destination_texture });
+
+ push_constant.pass = FSR_UPSCALE_PASS_RCAS;
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_upscale_texture_with_sampler), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_destination_texture), 1);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(FSRUpscalePushConstant));
+
+ RD::get_singleton()->compute_list_dispatch(compute_list, dispatch_x, dispatch_y, 1);
+
+ RD::get_singleton()->compute_list_end(compute_list);
+}
diff --git a/servers/rendering/renderer_rd/effects/fsr.h b/servers/rendering/renderer_rd/effects/fsr.h
new file mode 100644
index 0000000000..69088e526a
--- /dev/null
+++ b/servers/rendering/renderer_rd/effects/fsr.h
@@ -0,0 +1,72 @@
+/*************************************************************************/
+/* fsr.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef FSR_RD_H
+#define FSR_RD_H
+
+#include "../pipeline_cache_rd.h"
+#include "../shaders/effects/fsr_upscale.glsl.gen.h"
+#include "../storage_rd/render_scene_buffers_rd.h"
+#include "servers/rendering/renderer_scene_render.h"
+#include "servers/rendering_server.h"
+
+namespace RendererRD {
+
+class FSR {
+public:
+ FSR();
+ ~FSR();
+
+ void fsr_upscale(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_source_rd_texture, RID p_destination_texture);
+
+private:
+ enum FSRUpscalePass {
+ FSR_UPSCALE_PASS_EASU = 0,
+ FSR_UPSCALE_PASS_RCAS = 1
+ };
+
+ struct FSRUpscalePushConstant {
+ float resolution_width;
+ float resolution_height;
+ float upscaled_width;
+ float upscaled_height;
+ float sharpness;
+ int pass;
+ int _unused0, _unused1;
+ };
+
+ FsrUpscaleShaderRD fsr_shader;
+ RID shader_version;
+ RID pipeline;
+};
+
+} // namespace RendererRD
+
+#endif // FSR_RD_H
diff --git a/servers/rendering/renderer_rd/effects/resolve.h b/servers/rendering/renderer_rd/effects/resolve.h
index 2a4cd06827..49fba921d5 100644
--- a/servers/rendering/renderer_rd/effects/resolve.h
+++ b/servers/rendering/renderer_rd/effects/resolve.h
@@ -65,8 +65,8 @@ public:
Resolve();
~Resolve();
- void resolve_gi(RID p_source_depth, RID p_source_normal_roughness, RID p_source_voxel_gi, RID p_dest_depth, RID p_dest_normal_roughness, RID p_dest_voxel_gi, Vector2i p_screen_size, int p_samples, uint32_t p_barrier = RD::BARRIER_MASK_ALL);
- void resolve_depth(RID p_source_depth, RID p_dest_depth, Vector2i p_screen_size, int p_samples, uint32_t p_barrier = RD::BARRIER_MASK_ALL);
+ void resolve_gi(RID p_source_depth, RID p_source_normal_roughness, RID p_source_voxel_gi, RID p_dest_depth, RID p_dest_normal_roughness, RID p_dest_voxel_gi, Vector2i p_screen_size, int p_samples, uint32_t p_barrier = RD::BARRIER_MASK_ALL_BARRIERS);
+ void resolve_depth(RID p_source_depth, RID p_dest_depth, Vector2i p_screen_size, int p_samples, uint32_t p_barrier = RD::BARRIER_MASK_ALL_BARRIERS);
};
} // namespace RendererRD
diff --git a/servers/rendering/renderer_rd/effects/ss_effects.cpp b/servers/rendering/renderer_rd/effects/ss_effects.cpp
index 0f896a8aa7..8e43869b4d 100644
--- a/servers/rendering/renderer_rd/effects/ss_effects.cpp
+++ b/servers/rendering/renderer_rd/effects/ss_effects.cpp
@@ -30,8 +30,10 @@
#include "ss_effects.h"
+#include "core/config/project_settings.h"
#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h"
#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"
using namespace RendererRD;
@@ -41,7 +43,7 @@ SSEffects *SSEffects::singleton = nullptr;
static _FORCE_INLINE_ void store_camera(const Projection &p_mtx, float *p_array) {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
- p_array[i * 4 + j] = p_mtx.matrix[i][j];
+ p_array[i * 4 + j] = p_mtx.columns[i][j];
}
}
}
@@ -49,8 +51,8 @@ static _FORCE_INLINE_ void store_camera(const Projection &p_mtx, float *p_array)
SSEffects::SSEffects() {
singleton = this;
+ // Initialize depth buffer for screen space effects
{
- // Initialize depth buffer for screen space effects
Vector<String> downsampler_modes;
downsampler_modes.push_back("\n");
downsampler_modes.push_back("\n#define USE_HALF_SIZE\n");
@@ -99,6 +101,7 @@ SSEffects::SSEffects() {
}
// Initialize Screen Space Indirect Lighting (SSIL)
+ ssil_set_quality(RS::EnvironmentSSILQuality(int(GLOBAL_GET("rendering/environment/ssil/quality"))), GLOBAL_GET("rendering/environment/ssil/half_size"), GLOBAL_GET("rendering/environment/ssil/adaptive_target"), GLOBAL_GET("rendering/environment/ssil/blur_passes"), GLOBAL_GET("rendering/environment/ssil/fadeout_from"), GLOBAL_GET("rendering/environment/ssil/fadeout_to"));
{
Vector<String> ssil_modes;
@@ -174,9 +177,10 @@ SSEffects::SSEffects() {
}
}
- {
- // Initialize Screen Space Ambient Occlusion (SSAO)
+ // Initialize Screen Space Ambient Occlusion (SSAO)
+ ssao_set_quality(RS::EnvironmentSSAOQuality(int(GLOBAL_GET("rendering/environment/ssao/quality"))), GLOBAL_GET("rendering/environment/ssao/half_size"), GLOBAL_GET("rendering/environment/ssao/adaptive_target"), GLOBAL_GET("rendering/environment/ssao/blur_passes"), GLOBAL_GET("rendering/environment/ssao/fadeout_from"), GLOBAL_GET("rendering/environment/ssao/fadeout_to"));
+ {
RD::SamplerState sampler;
sampler.mag_filter = RD::SAMPLER_FILTER_NEAREST;
sampler.min_filter = RD::SAMPLER_FILTER_NEAREST;
@@ -275,9 +279,10 @@ SSEffects::SSEffects() {
ss_effects.mirror_sampler = RD::get_singleton()->sampler_create(sampler);
}
- {
- // Screen Space Reflections
+ // Screen Space Reflections
+ ssr_roughness_quality = RS::EnvironmentSSRRoughnessQuality(int(GLOBAL_GET("rendering/environment/screen_space_reflection/roughness_quality")));
+ {
Vector<RD::PipelineSpecializationConstant> specialization_constants;
{
@@ -333,6 +338,26 @@ SSEffects::SSEffects() {
}
}
}
+
+ // Subsurface scattering
+ sss_quality = RS::SubSurfaceScatteringQuality(int(GLOBAL_GET("rendering/environment/subsurface_scattering/subsurface_scattering_quality")));
+ sss_scale = GLOBAL_GET("rendering/environment/subsurface_scattering/subsurface_scattering_scale");
+ sss_depth_scale = GLOBAL_GET("rendering/environment/subsurface_scattering/subsurface_scattering_depth_scale");
+
+ {
+ Vector<String> sss_modes;
+ sss_modes.push_back("\n#define USE_11_SAMPLES\n");
+ sss_modes.push_back("\n#define USE_17_SAMPLES\n");
+ sss_modes.push_back("\n#define USE_25_SAMPLES\n");
+
+ sss.shader.initialize(sss_modes);
+
+ sss.shader_version = sss.shader.version_create();
+
+ for (int i = 0; i < sss_modes.size(); i++) {
+ sss.pipelines[i] = RD::get_singleton()->compute_pipeline_create(sss.shader.version_get_shader(sss.shader_version, i));
+ }
+ }
}
SSEffects::~SSEffects() {
@@ -376,12 +401,17 @@ SSEffects::~SSEffects() {
RD::get_singleton()->free(ssao.importance_map_load_counter);
}
+ {
+ // Cleanup Subsurface scattering
+ sss.shader.version_free(sss.shader_version);
+ }
+
singleton = nullptr;
}
/* SS Downsampler */
-void SSEffects::downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_mipmaps, RS::EnvironmentSSAOQuality p_ssao_quality, RS::EnvironmentSSILQuality p_ssil_quality, bool p_invalidate_uniform_set, bool p_ssao_half_size, bool p_ssil_half_size, Size2i p_full_screen_size, const Projection &p_projection) {
+void SSEffects::downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_mipmaps, bool p_invalidate_uniform_set, Size2i p_full_screen_size, const Projection &p_projection) {
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
ERR_FAIL_NULL(uniform_set_cache);
MaterialStorage *material_storage = MaterialStorage::get_singleton();
@@ -391,9 +421,9 @@ void SSEffects::downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
int downsample_mode = SS_EFFECTS_DOWNSAMPLE;
- bool use_mips = p_ssao_quality > RS::ENV_SSAO_QUALITY_MEDIUM || p_ssil_quality > RS::ENV_SSIL_QUALITY_MEDIUM;
+ bool use_mips = ssao_quality > RS::ENV_SSAO_QUALITY_MEDIUM || ssil_quality > RS::ENV_SSIL_QUALITY_MEDIUM;
- if (p_ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW && p_ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {
+ if (ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW && ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {
downsample_mode = SS_EFFECTS_DOWNSAMPLE_HALF;
} else if (use_mips) {
downsample_mode = SS_EFFECTS_DOWNSAMPLE_MIPMAP;
@@ -402,10 +432,10 @@ void SSEffects::downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_
bool use_half_size = false;
bool use_full_mips = false;
- if (p_ssao_half_size && p_ssil_half_size) {
+ if (ssao_half_size && ssil_half_size) {
downsample_mode++;
use_half_size = true;
- } else if (p_ssao_half_size != p_ssil_half_size) {
+ } else if (ssao_half_size != ssil_half_size) {
if (use_mips) {
downsample_mode = SS_EFFECTS_DOWNSAMPLE_FULL_MIPS;
use_full_mips = true;
@@ -421,6 +451,11 @@ void SSEffects::downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_
RD::get_singleton()->draw_command_begin_label("Downsample Depth");
if (p_invalidate_uniform_set || use_full_mips != ss_effects.used_full_mips_last_frame || use_half_size != ss_effects.used_half_size_last_frame || use_mips != ss_effects.used_mips_last_frame) {
+ if (ss_effects.downsample_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(ss_effects.downsample_uniform_set)) {
+ RD::get_singleton()->free(ss_effects.downsample_uniform_set);
+ ss_effects.downsample_uniform_set = RID();
+ }
+
Vector<RD::Uniform> uniforms;
{
RD::Uniform u;
@@ -453,8 +488,8 @@ void SSEffects::downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_
ss_effects.downsample_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ss_effects.downsample_shader.version_get_shader(ss_effects.downsample_shader_version, use_full_mips ? 6 : 2), 2);
}
- float depth_linearize_mul = -p_projection.matrix[3][2];
- float depth_linearize_add = p_projection.matrix[2][2];
+ float depth_linearize_mul = -p_projection.columns[3][2];
+ float depth_linearize_add = p_projection.columns[2][2];
if (depth_linearize_mul * depth_linearize_add < 0) {
depth_linearize_add = -depth_linearize_add;
}
@@ -494,16 +529,26 @@ void SSEffects::downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_
ss_effects.used_full_mips_last_frame = use_full_mips;
ss_effects.used_half_size_last_frame = use_half_size;
+ ss_effects.used_mips_last_frame = use_mips;
}
/* SSIL */
+void SSEffects::ssil_set_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) {
+ ssil_quality = p_quality;
+ ssil_half_size = p_half_size;
+ ssil_adaptive_target = p_adaptive_target;
+ ssil_blur_passes = p_blur_passes;
+ ssil_fadeout_from = p_fadeout_from;
+ ssil_fadeout_to = p_fadeout_to;
+}
+
void SSEffects::gather_ssil(RD::ComputeListID p_compute_list, const Vector<RID> p_ssil_slices, const Vector<RID> p_edges_slices, const SSILSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set, RID p_projection_uniform_set) {
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
ERR_FAIL_NULL(uniform_set_cache);
RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_gather_uniform_set, 0);
- if ((p_settings.quality == RS::ENV_SSIL_QUALITY_ULTRA) && !p_adaptive_base_pass) {
+ if ((ssil_quality == RS::ENV_SSIL_QUALITY_ULTRA) && !p_adaptive_base_pass) {
RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_importance_map_uniform_set, 1);
}
RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_projection_uniform_set, 3);
@@ -511,7 +556,7 @@ void SSEffects::gather_ssil(RD::ComputeListID p_compute_list, const Vector<RID>
RID shader = ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 0);
for (int i = 0; i < 4; i++) {
- if ((p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) {
+ if ((ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) {
continue;
}
@@ -526,7 +571,7 @@ void SSEffects::gather_ssil(RD::ComputeListID p_compute_list, const Vector<RID>
RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, uniform_set_cache->get_cache(shader, 2, u_ssil_slice, u_edges_slice), 2);
RD::get_singleton()->compute_list_set_push_constant(p_compute_list, &ssil.gather_push_constant, sizeof(SSILGatherPushConstant));
- Size2i size = Size2i(p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1), p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1));
+ Size2i size = Size2i(p_settings.full_screen_size.x >> (ssil_half_size ? 2 : 1), p_settings.full_screen_size.y >> (ssil_half_size ? 2 : 1));
RD::get_singleton()->compute_list_dispatch_threads(p_compute_list, size.x, size.y, 1);
}
@@ -534,11 +579,11 @@ void SSEffects::gather_ssil(RD::ComputeListID p_compute_list, const Vector<RID>
}
void SSEffects::ssil_allocate_buffers(SSILRenderBuffers &p_ssil_buffers, const SSILSettings &p_settings, RID p_linear_depth) {
- if (p_ssil_buffers.half_size != p_settings.half_size) {
+ if (p_ssil_buffers.half_size != ssil_half_size) {
ssil_free(p_ssil_buffers);
}
- if (p_settings.half_size) {
+ if (ssil_half_size) {
p_ssil_buffers.buffer_width = (p_settings.full_screen_size.x + 3) / 4;
p_ssil_buffers.buffer_height = (p_settings.full_screen_size.y + 3) / 4;
p_ssil_buffers.half_buffer_width = (p_settings.full_screen_size.x + 7) / 8;
@@ -552,7 +597,7 @@ void SSEffects::ssil_allocate_buffers(SSILRenderBuffers &p_ssil_buffers, const S
if (p_ssil_buffers.ssil_final.is_null()) {
{
- p_ssil_buffers.depth_texture_view = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_linear_depth, 0, p_settings.half_size ? 1 : 0, 4, RD::TEXTURE_SLICE_2D_ARRAY);
+ p_ssil_buffers.depth_texture_view = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_linear_depth, 0, ssil_half_size ? 1 : 0, 4, RD::TEXTURE_SLICE_2D_ARRAY);
}
{
RD::TextureFormat tf;
@@ -637,7 +682,7 @@ void SSEffects::ssil_allocate_buffers(SSILRenderBuffers &p_ssil_buffers, const S
p_ssil_buffers.importance_map[1] = RD::get_singleton()->texture_create(tf, RD::TextureView());
RD::get_singleton()->set_resource_name(p_ssil_buffers.importance_map[1], "SSIL Importance Map Pong");
}
- p_ssil_buffers.half_size = p_settings.half_size;
+ p_ssil_buffers.half_size = ssil_half_size;
}
}
@@ -668,8 +713,8 @@ void SSEffects::screen_space_indirect_lighting(SSILRenderBuffers &p_ssil_buffers
ssil.gather_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssil_buffers.buffer_width;
ssil.gather_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssil_buffers.buffer_height;
- float tan_half_fov_x = 1.0 / p_projection.matrix[0][0];
- float tan_half_fov_y = 1.0 / p_projection.matrix[1][1];
+ float tan_half_fov_x = 1.0 / p_projection.columns[0][0];
+ float tan_half_fov_y = 1.0 / p_projection.columns[1][1];
ssil.gather_push_constant.NDC_to_view_mul[0] = tan_half_fov_x * 2.0;
ssil.gather_push_constant.NDC_to_view_mul[1] = tan_half_fov_y * -2.0;
ssil.gather_push_constant.NDC_to_view_add[0] = tan_half_fov_x * -1.0;
@@ -683,26 +728,26 @@ void SSEffects::screen_space_indirect_lighting(SSILRenderBuffers &p_ssil_buffers
ssil.gather_push_constant.radius = p_settings.radius;
float radius_near_limit = (p_settings.radius * 1.2f);
- if (p_settings.quality <= RS::ENV_SSIL_QUALITY_LOW) {
+ if (ssil_quality <= RS::ENV_SSIL_QUALITY_LOW) {
radius_near_limit *= 1.50f;
- if (p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {
+ if (ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {
ssil.gather_push_constant.radius *= 0.8f;
}
}
radius_near_limit /= tan_half_fov_y;
ssil.gather_push_constant.intensity = p_settings.intensity * Math_PI;
- ssil.gather_push_constant.fade_out_mul = -1.0 / (p_settings.fadeout_to - p_settings.fadeout_from);
- ssil.gather_push_constant.fade_out_add = p_settings.fadeout_from / (p_settings.fadeout_to - p_settings.fadeout_from) + 1.0;
+ ssil.gather_push_constant.fade_out_mul = -1.0 / (ssil_fadeout_to - ssil_fadeout_from);
+ ssil.gather_push_constant.fade_out_add = ssil_fadeout_from / (ssil_fadeout_to - ssil_fadeout_from) + 1.0;
ssil.gather_push_constant.inv_radius_near_limit = 1.0f / radius_near_limit;
ssil.gather_push_constant.neg_inv_radius = -1.0 / ssil.gather_push_constant.radius;
ssil.gather_push_constant.normal_rejection_amount = p_settings.normal_rejection;
ssil.gather_push_constant.load_counter_avg_div = 9.0 / float((p_ssil_buffers.half_buffer_width) * (p_ssil_buffers.half_buffer_height) * 255);
- ssil.gather_push_constant.adaptive_sample_limit = p_settings.adaptive_target;
+ ssil.gather_push_constant.adaptive_sample_limit = ssil_adaptive_target;
- ssil.gather_push_constant.quality = MAX(0, p_settings.quality - 1);
- ssil.gather_push_constant.size_multiplier = p_settings.half_size ? 2 : 1;
+ ssil.gather_push_constant.quality = MAX(0, ssil_quality - 1);
+ ssil.gather_push_constant.size_multiplier = ssil_half_size ? 2 : 1;
if (p_ssil_buffers.projection_uniform_set.is_null()) {
Vector<RD::Uniform> uniforms;
@@ -778,7 +823,7 @@ void SSEffects::screen_space_indirect_lighting(SSILRenderBuffers &p_ssil_buffers
p_ssil_buffers.importance_map_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 2), 1);
}
- if (p_settings.quality == RS::ENV_SSIL_QUALITY_ULTRA) {
+ if (ssil_quality == RS::ENV_SSIL_QUALITY_ULTRA) {
RD::get_singleton()->draw_command_begin_label("Generate Importance Map");
ssil.importance_map_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssil_buffers.buffer_width;
ssil.importance_map_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssil_buffers.buffer_height;
@@ -837,13 +882,13 @@ void SSEffects::screen_space_indirect_lighting(SSILRenderBuffers &p_ssil_buffers
ssil.blur_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssil_buffers.buffer_width;
ssil.blur_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssil_buffers.buffer_height;
- int blur_passes = p_settings.quality > RS::ENV_SSIL_QUALITY_VERY_LOW ? p_settings.blur_passes : 1;
+ int blur_passes = ssil_quality > RS::ENV_SSIL_QUALITY_VERY_LOW ? ssil_blur_passes : 1;
shader = ssil.blur_shader.version_get_shader(ssil.blur_shader_version, 0);
for (int pass = 0; pass < blur_passes; pass++) {
int blur_pipeline = SSIL_BLUR_PASS;
- if (p_settings.quality > RS::ENV_SSIL_QUALITY_VERY_LOW) {
+ if (ssil_quality > RS::ENV_SSIL_QUALITY_VERY_LOW) {
blur_pipeline = SSIL_BLUR_PASS_SMART;
if (pass < blur_passes - 2) {
blur_pipeline = SSIL_BLUR_PASS_WIDE;
@@ -851,13 +896,13 @@ void SSEffects::screen_space_indirect_lighting(SSILRenderBuffers &p_ssil_buffers
}
for (int i = 0; i < 4; i++) {
- if ((p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) {
+ if ((ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) {
continue;
}
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[blur_pipeline]);
if (pass % 2 == 0) {
- if (p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {
+ if (ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {
RD::Uniform u_ssil_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssil_buffers.deinterleaved_slices[i] }));
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ssil_slice), 0);
} else {
@@ -868,7 +913,7 @@ void SSEffects::screen_space_indirect_lighting(SSILRenderBuffers &p_ssil_buffers
RD::Uniform u_ssil_pong_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_buffers.pong_slices[i] }));
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ssil_pong_slice), 1);
} else {
- if (p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {
+ if (ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {
RD::Uniform u_ssil_pong_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssil_buffers.pong_slices[i] }));
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ssil_pong_slice), 0);
} else {
@@ -885,11 +930,11 @@ void SSEffects::screen_space_indirect_lighting(SSILRenderBuffers &p_ssil_buffers
RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.blur_push_constant, sizeof(SSILBlurPushConstant));
- int x_groups = (p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1));
- int y_groups = (p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1));
+ int x_groups = (p_settings.full_screen_size.x >> (ssil_half_size ? 2 : 1));
+ int y_groups = (p_settings.full_screen_size.y >> (ssil_half_size ? 2 : 1));
RD::get_singleton()->compute_list_dispatch_threads(compute_list, x_groups, y_groups, 1);
- if (p_settings.quality > RS::ENV_SSIL_QUALITY_VERY_LOW) {
+ if (ssil_quality > RS::ENV_SSIL_QUALITY_VERY_LOW) {
RD::get_singleton()->compute_list_add_barrier(compute_list);
}
}
@@ -903,12 +948,12 @@ void SSEffects::screen_space_indirect_lighting(SSILRenderBuffers &p_ssil_buffers
ssil.interleave_push_constant.inv_sharpness = 1.0 - p_settings.sharpness;
ssil.interleave_push_constant.pixel_size[0] = 1.0 / p_settings.full_screen_size.x;
ssil.interleave_push_constant.pixel_size[1] = 1.0 / p_settings.full_screen_size.y;
- ssil.interleave_push_constant.size_modifier = uint32_t(p_settings.half_size ? 4 : 2);
+ ssil.interleave_push_constant.size_modifier = uint32_t(ssil_half_size ? 4 : 2);
int interleave_pipeline = SSIL_INTERLEAVE_HALF;
- if (p_settings.quality == RS::ENV_SSIL_QUALITY_LOW) {
+ if (ssil_quality == RS::ENV_SSIL_QUALITY_LOW) {
interleave_pipeline = SSIL_INTERLEAVE;
- } else if (p_settings.quality >= RS::ENV_SSIL_QUALITY_MEDIUM) {
+ } else if (ssil_quality >= RS::ENV_SSIL_QUALITY_MEDIUM) {
interleave_pipeline = SSIL_INTERLEAVE_SMART;
}
@@ -919,7 +964,7 @@ void SSEffects::screen_space_indirect_lighting(SSILRenderBuffers &p_ssil_buffers
RD::Uniform u_destination(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_buffers.ssil_final }));
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_destination), 0);
- if (p_settings.quality > RS::ENV_SSIL_QUALITY_VERY_LOW && p_settings.blur_passes % 2 == 0) {
+ if (ssil_quality > RS::ENV_SSIL_QUALITY_VERY_LOW && ssil_blur_passes % 2 == 0) {
RD::Uniform u_ssil(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssil_buffers.deinterleaved }));
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ssil), 1);
} else {
@@ -975,19 +1020,28 @@ void SSEffects::ssil_free(SSILRenderBuffers &p_ssil_buffers) {
/* SSAO */
+void SSEffects::ssao_set_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) {
+ ssao_quality = p_quality;
+ ssao_half_size = p_half_size;
+ ssao_adaptive_target = p_adaptive_target;
+ ssao_blur_passes = p_blur_passes;
+ ssao_fadeout_from = p_fadeout_from;
+ ssao_fadeout_to = p_fadeout_to;
+}
+
void SSEffects::gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID> p_ao_slices, const SSAOSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set) {
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
ERR_FAIL_NULL(uniform_set_cache);
RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_gather_uniform_set, 0);
- if ((p_settings.quality == RS::ENV_SSAO_QUALITY_ULTRA) && !p_adaptive_base_pass) {
+ if ((ssao_quality == RS::ENV_SSAO_QUALITY_ULTRA) && !p_adaptive_base_pass) {
RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_importance_map_uniform_set, 0);
}
RID shader = ssao.gather_shader.version_get_shader(ssao.gather_shader_version, 1); //
for (int i = 0; i < 4; i++) {
- if ((p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) {
+ if ((ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) {
continue;
}
@@ -1001,7 +1055,7 @@ void SSEffects::gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID>
RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, uniform_set_cache->get_cache(shader, 2, u_ao_slice), 2);
RD::get_singleton()->compute_list_set_push_constant(p_compute_list, &ssao.gather_push_constant, sizeof(SSAOGatherPushConstant));
- Size2i size = Size2i(p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1), p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1));
+ Size2i size = Size2i(p_settings.full_screen_size.x >> (ssao_half_size ? 2 : 1), p_settings.full_screen_size.y >> (ssao_half_size ? 2 : 1));
RD::get_singleton()->compute_list_dispatch_threads(p_compute_list, size.x, size.y, 1);
}
@@ -1009,11 +1063,11 @@ void SSEffects::gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID>
}
void SSEffects::ssao_allocate_buffers(SSAORenderBuffers &p_ssao_buffers, const SSAOSettings &p_settings, RID p_linear_depth) {
- if (p_ssao_buffers.half_size != p_settings.half_size) {
+ if (p_ssao_buffers.half_size != ssao_half_size) {
ssao_free(p_ssao_buffers);
}
- if (p_settings.half_size) {
+ if (ssao_half_size) {
p_ssao_buffers.buffer_width = (p_settings.full_screen_size.x + 3) / 4;
p_ssao_buffers.buffer_height = (p_settings.full_screen_size.y + 3) / 4;
p_ssao_buffers.half_buffer_width = (p_settings.full_screen_size.x + 7) / 8;
@@ -1027,7 +1081,7 @@ void SSEffects::ssao_allocate_buffers(SSAORenderBuffers &p_ssao_buffers, const S
if (p_ssao_buffers.ao_deinterleaved.is_null()) {
{
- p_ssao_buffers.depth_texture_view = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_linear_depth, 0, p_settings.half_size ? 1 : 0, 4, RD::TEXTURE_SLICE_2D_ARRAY);
+ p_ssao_buffers.depth_texture_view = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_linear_depth, 0, ssao_half_size ? 1 : 0, 4, RD::TEXTURE_SLICE_2D_ARRAY);
}
{
RD::TextureFormat tf;
@@ -1083,7 +1137,7 @@ void SSEffects::ssao_allocate_buffers(SSAORenderBuffers &p_ssao_buffers, const S
p_ssao_buffers.ao_final = RD::get_singleton()->texture_create(tf, RD::TextureView());
RD::get_singleton()->set_resource_name(p_ssao_buffers.ao_final, "SSAO Final");
}
- p_ssao_buffers.half_size = p_settings.half_size;
+ p_ssao_buffers.half_size = ssao_half_size;
}
}
@@ -1110,8 +1164,8 @@ void SSEffects::generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_bu
ssao.gather_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssao_buffers.buffer_width;
ssao.gather_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssao_buffers.buffer_height;
- float tan_half_fov_x = 1.0 / p_projection.matrix[0][0];
- float tan_half_fov_y = 1.0 / p_projection.matrix[1][1];
+ float tan_half_fov_x = 1.0 / p_projection.columns[0][0];
+ float tan_half_fov_y = 1.0 / p_projection.columns[1][1];
ssao.gather_push_constant.NDC_to_view_mul[0] = tan_half_fov_x * 2.0;
ssao.gather_push_constant.NDC_to_view_mul[1] = tan_half_fov_y * -2.0;
ssao.gather_push_constant.NDC_to_view_add[0] = tan_half_fov_x * -1.0;
@@ -1123,10 +1177,10 @@ void SSEffects::generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_bu
ssao.gather_push_constant.radius = p_settings.radius;
float radius_near_limit = (p_settings.radius * 1.2f);
- if (p_settings.quality <= RS::ENV_SSAO_QUALITY_LOW) {
+ if (ssao_quality <= RS::ENV_SSAO_QUALITY_LOW) {
radius_near_limit *= 1.50f;
- if (p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) {
+ if (ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW) {
ssao.gather_push_constant.radius *= 0.8f;
}
}
@@ -1134,18 +1188,18 @@ void SSEffects::generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_bu
ssao.gather_push_constant.intensity = p_settings.intensity;
ssao.gather_push_constant.shadow_power = p_settings.power;
ssao.gather_push_constant.shadow_clamp = 0.98;
- ssao.gather_push_constant.fade_out_mul = -1.0 / (p_settings.fadeout_to - p_settings.fadeout_from);
- ssao.gather_push_constant.fade_out_add = p_settings.fadeout_from / (p_settings.fadeout_to - p_settings.fadeout_from) + 1.0;
+ ssao.gather_push_constant.fade_out_mul = -1.0 / (ssao_fadeout_to - ssao_fadeout_from);
+ ssao.gather_push_constant.fade_out_add = ssao_fadeout_from / (ssao_fadeout_to - ssao_fadeout_from) + 1.0;
ssao.gather_push_constant.horizon_angle_threshold = p_settings.horizon;
ssao.gather_push_constant.inv_radius_near_limit = 1.0f / radius_near_limit;
ssao.gather_push_constant.neg_inv_radius = -1.0 / ssao.gather_push_constant.radius;
ssao.gather_push_constant.load_counter_avg_div = 9.0 / float((p_ssao_buffers.half_buffer_width) * (p_ssao_buffers.half_buffer_height) * 255);
- ssao.gather_push_constant.adaptive_sample_limit = p_settings.adaptive_target;
+ ssao.gather_push_constant.adaptive_sample_limit = ssao_adaptive_target;
ssao.gather_push_constant.detail_intensity = p_settings.detail;
- ssao.gather_push_constant.quality = MAX(0, p_settings.quality - 1);
- ssao.gather_push_constant.size_multiplier = p_settings.half_size ? 2 : 1;
+ ssao.gather_push_constant.quality = MAX(0, ssao_quality - 1);
+ ssao.gather_push_constant.size_multiplier = ssao_half_size ? 2 : 1;
if (p_ssao_buffers.gather_uniform_set.is_null()) {
Vector<RD::Uniform> uniforms;
@@ -1203,7 +1257,7 @@ void SSEffects::generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_bu
RD::get_singleton()->set_resource_name(p_ssao_buffers.importance_map_uniform_set, "SSAO Importance Map Uniform Set");
}
- if (p_settings.quality == RS::ENV_SSAO_QUALITY_ULTRA) {
+ if (ssao_quality == RS::ENV_SSAO_QUALITY_ULTRA) {
RD::get_singleton()->draw_command_begin_label("Generate Importance Map");
ssao.importance_map_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssao_buffers.buffer_width;
ssao.importance_map_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssao_buffers.buffer_height;
@@ -1271,14 +1325,13 @@ void SSEffects::generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_bu
ssao.blur_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssao_buffers.buffer_width;
ssao.blur_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssao_buffers.buffer_height;
- int blur_passes = p_settings.quality > RS::ENV_SSAO_QUALITY_VERY_LOW ? p_settings.blur_passes : 1;
+ int blur_passes = ssao_quality > RS::ENV_SSAO_QUALITY_VERY_LOW ? ssao_blur_passes : 1;
shader = ssao.blur_shader.version_get_shader(ssao.blur_shader_version, 0);
for (int pass = 0; pass < blur_passes; pass++) {
int blur_pipeline = SSAO_BLUR_PASS;
- if (p_settings.quality > RS::ENV_SSAO_QUALITY_VERY_LOW) {
- blur_pipeline = SSAO_BLUR_PASS_SMART;
+ if (ssao_quality > RS::ENV_SSAO_QUALITY_VERY_LOW) {
if (pass < blur_passes - 2) {
blur_pipeline = SSAO_BLUR_PASS_WIDE;
} else {
@@ -1287,13 +1340,13 @@ void SSEffects::generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_bu
}
for (int i = 0; i < 4; i++) {
- if ((p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) {
+ if ((ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) {
continue;
}
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[blur_pipeline]);
if (pass % 2 == 0) {
- if (p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) {
+ if (ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW) {
RD::Uniform u_ao_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssao_buffers.ao_deinterleaved_slices[i] }));
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ao_slices_with_sampler), 0);
} else {
@@ -1304,7 +1357,7 @@ void SSEffects::generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_bu
RD::Uniform u_ao_pong_slices(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssao_buffers.ao_pong_slices[i] }));
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ao_pong_slices), 1);
} else {
- if (p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) {
+ if (ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW) {
RD::Uniform u_ao_pong_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssao_buffers.ao_pong_slices[i] }));
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ao_pong_slices_with_sampler), 0);
} else {
@@ -1317,11 +1370,11 @@ void SSEffects::generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_bu
}
RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.blur_push_constant, sizeof(SSAOBlurPushConstant));
- Size2i size(p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1), p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1));
+ Size2i size(p_settings.full_screen_size.x >> (ssao_half_size ? 2 : 1), p_settings.full_screen_size.y >> (ssao_half_size ? 2 : 1));
RD::get_singleton()->compute_list_dispatch_threads(compute_list, size.x, size.y, 1);
}
- if (p_settings.quality > RS::ENV_SSAO_QUALITY_VERY_LOW) {
+ if (ssao_quality > RS::ENV_SSAO_QUALITY_VERY_LOW) {
RD::get_singleton()->compute_list_add_barrier(compute_list);
}
}
@@ -1336,14 +1389,14 @@ void SSEffects::generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_bu
ssao.interleave_push_constant.inv_sharpness = 1.0 - p_settings.sharpness;
ssao.interleave_push_constant.pixel_size[0] = 1.0 / p_settings.full_screen_size.x;
ssao.interleave_push_constant.pixel_size[1] = 1.0 / p_settings.full_screen_size.y;
- ssao.interleave_push_constant.size_modifier = uint32_t(p_settings.half_size ? 4 : 2);
+ ssao.interleave_push_constant.size_modifier = uint32_t(ssao_half_size ? 4 : 2);
shader = ssao.interleave_shader.version_get_shader(ssao.interleave_shader_version, 0);
int interleave_pipeline = SSAO_INTERLEAVE_HALF;
- if (p_settings.quality == RS::ENV_SSAO_QUALITY_LOW) {
+ if (ssao_quality == RS::ENV_SSAO_QUALITY_LOW) {
interleave_pipeline = SSAO_INTERLEAVE;
- } else if (p_settings.quality >= RS::ENV_SSAO_QUALITY_MEDIUM) {
+ } else if (ssao_quality >= RS::ENV_SSAO_QUALITY_MEDIUM) {
interleave_pipeline = SSAO_INTERLEAVE_SMART;
}
@@ -1352,7 +1405,7 @@ void SSEffects::generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_bu
RD::Uniform u_upscale_buffer(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssao_buffers.ao_final }));
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_upscale_buffer), 0);
- if (p_settings.quality > RS::ENV_SSAO_QUALITY_VERY_LOW && p_settings.blur_passes % 2 == 0) {
+ if (ssao_quality > RS::ENV_SSAO_QUALITY_VERY_LOW && ssao_blur_passes % 2 == 0) {
RD::Uniform u_ao(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssao_buffers.ao_deinterleaved }));
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ao), 1);
} else {
@@ -1397,8 +1450,23 @@ void SSEffects::ssao_free(SSAORenderBuffers &p_ssao_buffers) {
/* Screen Space Reflection */
-void SSEffects::ssr_allocate_buffers(SSRRenderBuffers &p_ssr_buffers, const RenderingDevice::DataFormat p_color_format, RenderingServer::EnvironmentSSRRoughnessQuality p_roughness_quality, const Size2i &p_screen_size, const uint32_t p_view_count) {
+void SSEffects::ssr_set_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) {
+ ssr_roughness_quality = p_quality;
+}
+
+void SSEffects::ssr_allocate_buffers(SSRRenderBuffers &p_ssr_buffers, const RenderingDevice::DataFormat p_color_format, const Size2i &p_screen_size, const uint32_t p_view_count) {
// As we are processing one view at a time, we can reuse buffers, only our output needs to have layers for each view.
+ if (p_ssr_buffers.size != p_screen_size || p_ssr_buffers.roughness_quality != ssr_roughness_quality) {
+ ssr_free(p_ssr_buffers);
+ }
+
+ if (p_ssr_buffers.output.is_valid()) {
+ // already allocated
+ return;
+ }
+
+ p_ssr_buffers.size = p_screen_size;
+ p_ssr_buffers.roughness_quality = ssr_roughness_quality;
if (p_ssr_buffers.depth_scaled.is_null()) {
RD::TextureFormat tf;
@@ -1418,7 +1486,7 @@ void SSEffects::ssr_allocate_buffers(SSRRenderBuffers &p_ssr_buffers, const Rend
RD::get_singleton()->set_resource_name(p_ssr_buffers.normal_scaled, "SSR Normal Scaled");
}
- if (p_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED && !p_ssr_buffers.blur_radius[0].is_valid()) {
+ if (ssr_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED && !p_ssr_buffers.blur_radius[0].is_valid()) {
RD::TextureFormat tf;
tf.format = RD::DATA_FORMAT_R8_UNORM;
tf.width = p_screen_size.x;
@@ -1462,7 +1530,7 @@ void SSEffects::ssr_allocate_buffers(SSRRenderBuffers &p_ssr_buffers, const Rend
}
}
-void SSEffects::screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const RID *p_diffuse_slices, const RID *p_normal_roughness_slices, RenderingServer::EnvironmentSSRRoughnessQuality p_roughness_quality, const RID *p_metallic_slices, const Color &p_metallic_mask, const RID *p_depth_slices, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets) {
+void SSEffects::screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const RID *p_diffuse_slices, const RID *p_normal_roughness_slices, const RID *p_metallic_slices, const RID *p_depth_slices, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets) {
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
ERR_FAIL_NULL(uniform_set_cache);
MaterialStorage *material_storage = MaterialStorage::get_singleton();
@@ -1523,8 +1591,13 @@ void SSEffects::screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const R
RD::Uniform u_normal_roughness(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 1, Vector<RID>({ default_sampler, p_normal_roughness_slices[v] }));
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_depth, u_normal_roughness), 1);
- RD::Uniform u_output_blur(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.output_slices[v] }));
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_output_blur), 2);
+ if (ssr_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) {
+ RD::Uniform u_output(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.output_slices[v] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_output), 2);
+ } else {
+ RD::Uniform u_intermediate(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.intermediate }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_intermediate), 2);
+ }
RD::Uniform u_scale_depth(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.depth_scaled }));
RD::Uniform u_scale_normal(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_ssr_buffers.normal_scaled }));
@@ -1553,16 +1626,12 @@ void SSEffects::screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const R
push_constant.num_steps = p_max_steps;
push_constant.depth_tolerance = p_tolerance;
push_constant.use_half_res = true;
- push_constant.proj_info[0] = -2.0f / (p_screen_size.width * p_projections[v].matrix[0][0]);
- push_constant.proj_info[1] = -2.0f / (p_screen_size.height * p_projections[v].matrix[1][1]);
- push_constant.proj_info[2] = (1.0f - p_projections[v].matrix[0][2]) / p_projections[v].matrix[0][0];
- push_constant.proj_info[3] = (1.0f + p_projections[v].matrix[1][2]) / p_projections[v].matrix[1][1];
- push_constant.metallic_mask[0] = CLAMP(p_metallic_mask.r * 255.0, 0, 255);
- push_constant.metallic_mask[1] = CLAMP(p_metallic_mask.g * 255.0, 0, 255);
- push_constant.metallic_mask[2] = CLAMP(p_metallic_mask.b * 255.0, 0, 255);
- push_constant.metallic_mask[3] = CLAMP(p_metallic_mask.a * 255.0, 0, 255);
-
- ScreenSpaceReflectionMode mode = (p_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) ? SCREEN_SPACE_REFLECTION_ROUGH : SCREEN_SPACE_REFLECTION_NORMAL;
+ push_constant.proj_info[0] = -2.0f / (p_screen_size.width * p_projections[v].columns[0][0]);
+ push_constant.proj_info[1] = -2.0f / (p_screen_size.height * p_projections[v].columns[1][1]);
+ push_constant.proj_info[2] = (1.0f - p_projections[v].columns[0][2]) / p_projections[v].columns[0][0];
+ push_constant.proj_info[3] = (1.0f + p_projections[v].columns[1][2]) / p_projections[v].columns[1][1];
+
+ ScreenSpaceReflectionMode mode = (ssr_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) ? SCREEN_SPACE_REFLECTION_ROUGH : SCREEN_SPACE_REFLECTION_NORMAL;
RID shader = ssr.shader.version_get_shader(ssr.shader_version, mode);
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr.pipelines[pipeline_specialization][mode]);
@@ -1570,17 +1639,25 @@ void SSEffects::screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const R
RD::Uniform u_scene_data(RD::UNIFORM_TYPE_UNIFORM_BUFFER, 0, ssr.ubo);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 4, u_scene_data), 4);
- RD::Uniform u_output_blur(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.output_slices[v] }));
- RD::Uniform u_scale_depth(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_ssr_buffers.depth_scaled }));
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_output_blur, u_scale_depth), 0);
+ if (ssr_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) {
+ // read from output slices (our scale wrote into these)
+ RD::Uniform u_output(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.output_slices[v] }));
+ RD::Uniform u_scale_depth(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_ssr_buffers.depth_scaled }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_output, u_scale_depth), 0);
- if (p_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) {
+ // write to intermediate (our roughness pass will output into output slices)
RD::Uniform u_intermediate(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.intermediate }));
RD::Uniform u_blur_radius(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_ssr_buffers.blur_radius[0] }));
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_intermediate, u_blur_radius), 1);
} else {
+ // read from intermediate (our scale wrote into these)
RD::Uniform u_intermediate(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.intermediate }));
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_intermediate), 1);
+ RD::Uniform u_scale_depth(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_ssr_buffers.depth_scaled }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_intermediate, u_scale_depth), 0);
+
+ // We are not performing our blur so go directly to output.
+ RD::Uniform u_output(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.output_slices[v] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_output), 1);
}
RD::Uniform u_scale_normal(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.normal_scaled }));
@@ -1595,7 +1672,7 @@ void SSEffects::screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const R
RD::get_singleton()->draw_command_end_label();
}
- if (p_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) {
+ if (ssr_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) {
RD::get_singleton()->draw_command_begin_label("SSR filter");
//blur
@@ -1604,16 +1681,16 @@ void SSEffects::screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const R
ScreenSpaceReflectionFilterPushConstant push_constant;
push_constant.view_index = v;
push_constant.orthogonal = p_projections[v].is_orthogonal();
- push_constant.edge_tolerance = Math::sin(Math::deg2rad(15.0));
- push_constant.proj_info[0] = -2.0f / (p_screen_size.width * p_projections[v].matrix[0][0]);
- push_constant.proj_info[1] = -2.0f / (p_screen_size.height * p_projections[v].matrix[1][1]);
- push_constant.proj_info[2] = (1.0f - p_projections[v].matrix[0][2]) / p_projections[v].matrix[0][0];
- push_constant.proj_info[3] = (1.0f + p_projections[v].matrix[1][2]) / p_projections[v].matrix[1][1];
+ push_constant.edge_tolerance = Math::sin(Math::deg_to_rad(15.0));
+ push_constant.proj_info[0] = -2.0f / (p_screen_size.width * p_projections[v].columns[0][0]);
+ push_constant.proj_info[1] = -2.0f / (p_screen_size.height * p_projections[v].columns[1][1]);
+ push_constant.proj_info[2] = (1.0f - p_projections[v].columns[0][2]) / p_projections[v].columns[0][0];
+ push_constant.proj_info[3] = (1.0f + p_projections[v].columns[1][2]) / p_projections[v].columns[1][1];
push_constant.vertical = 0;
- if (p_roughness_quality == RS::ENV_SSR_ROUGHNESS_QUALITY_LOW) {
+ if (ssr_roughness_quality == RS::ENV_SSR_ROUGHNESS_QUALITY_LOW) {
push_constant.steps = p_max_steps / 3;
push_constant.increment = 3;
- } else if (p_roughness_quality == RS::ENV_SSR_ROUGHNESS_QUALITY_MEDIUM) {
+ } else if (ssr_roughness_quality == RS::ENV_SSR_ROUGHNESS_QUALITY_MEDIUM) {
push_constant.steps = p_max_steps / 2;
push_constant.increment = 2;
} else {
@@ -1713,3 +1790,86 @@ void SSEffects::ssr_free(SSRRenderBuffers &p_ssr_buffers) {
p_ssr_buffers.normal_scaled = RID();
}
}
+
+/* Subsurface scattering */
+
+void SSEffects::sss_set_quality(RS::SubSurfaceScatteringQuality p_quality) {
+ sss_quality = p_quality;
+}
+
+RS::SubSurfaceScatteringQuality SSEffects::sss_get_quality() const {
+ return sss_quality;
+}
+
+void SSEffects::sss_set_scale(float p_scale, float p_depth_scale) {
+ sss_scale = p_scale;
+ sss_depth_scale = p_depth_scale;
+}
+
+void SSEffects::sub_surface_scattering(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_diffuse, RID p_depth, const Projection &p_camera, const Size2i &p_screen_size) {
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ // Our intermediate buffer is only created if we haven't created it already.
+ RD::DataFormat format = p_render_buffers->get_base_data_format();
+ uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+ uint32_t layers = 1; // We only need one layer, we're handling one view at a time
+ uint32_t mipmaps = 1; // Image::get_image_required_mipmaps(p_screen_size.x, p_screen_size.y, Image::FORMAT_RGBAH);
+ RID intermediate = p_render_buffers->create_texture(SNAME("SSR"), SNAME("intermediate"), format, usage_bits, RD::TEXTURE_SAMPLES_1, p_screen_size, layers, mipmaps);
+
+ Plane p = p_camera.xform4(Plane(1, 0, -1, 1));
+ p.normal /= p.d;
+ float unit_size = p.normal.x;
+
+ { //scale color and depth to half
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+
+ sss.push_constant.camera_z_far = p_camera.get_z_far();
+ sss.push_constant.camera_z_near = p_camera.get_z_near();
+ sss.push_constant.orthogonal = p_camera.is_orthogonal();
+ sss.push_constant.unit_size = unit_size;
+ sss.push_constant.screen_size[0] = p_screen_size.x;
+ sss.push_constant.screen_size[1] = p_screen_size.y;
+ sss.push_constant.vertical = false;
+ sss.push_constant.scale = sss_scale;
+ sss.push_constant.depth_scale = sss_depth_scale;
+
+ RID shader = sss.shader.version_get_shader(sss.shader_version, sss_quality - 1);
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sss.pipelines[sss_quality - 1]);
+
+ RD::Uniform u_diffuse_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_diffuse }));
+ RD::Uniform u_diffuse(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_diffuse }));
+ RD::Uniform u_intermediate_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, intermediate }));
+ RD::Uniform u_intermediate(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ intermediate }));
+ RD::Uniform u_depth_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_depth }));
+
+ // horizontal
+
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_diffuse_with_sampler), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_intermediate), 1);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_depth_with_sampler), 2);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &sss.push_constant, sizeof(SubSurfaceScatteringPushConstant));
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
+
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ // vertical
+
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_intermediate_with_sampler), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_diffuse), 1);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_depth_with_sampler), 2);
+
+ sss.push_constant.vertical = true;
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &sss.push_constant, sizeof(SubSurfaceScatteringPushConstant));
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
+
+ RD::get_singleton()->compute_list_end();
+ }
+}
diff --git a/servers/rendering/renderer_rd/effects/ss_effects.h b/servers/rendering/renderer_rd/effects/ss_effects.h
index c31271ffd2..a04dfc4a74 100644
--- a/servers/rendering/renderer_rd/effects/ss_effects.h
+++ b/servers/rendering/renderer_rd/effects/ss_effects.h
@@ -44,9 +44,12 @@
#include "servers/rendering/renderer_rd/shaders/effects/ssil_blur.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/effects/ssil_importance_map.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/effects/ssil_interleave.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/effects/subsurface_scattering.glsl.gen.h"
#include "servers/rendering/renderer_scene_render.h"
#include "servers/rendering_server.h"
+class RenderSceneBuffersRD;
+
namespace RendererRD {
class SSEffects {
@@ -61,9 +64,10 @@ public:
/* SS Downsampler */
- void downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_mipmaps, RS::EnvironmentSSAOQuality p_ssao_quality, RS::EnvironmentSSILQuality p_ssil_quality, bool p_invalidate_uniform_set, bool p_ssao_half_size, bool p_ssil_half_size, Size2i p_full_screen_size, const Projection &p_projection);
+ void downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_mipmaps, bool p_invalidate_uniform_set, Size2i p_full_screen_size, const Projection &p_projection);
/* SSIL */
+ void ssil_set_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to);
struct SSILRenderBuffers {
bool half_size = false;
@@ -96,14 +100,7 @@ public:
float sharpness = 0.98;
float normal_rejection = 1.0;
- RS::EnvironmentSSILQuality quality = RS::ENV_SSIL_QUALITY_MEDIUM;
- bool half_size = true;
- float adaptive_target = 0.5;
- int blur_passes = 4;
- float fadeout_from = 50.0;
- float fadeout_to = 300.0;
-
- Size2i full_screen_size = Size2i();
+ Size2i full_screen_size;
};
void ssil_allocate_buffers(SSILRenderBuffers &p_ssil_buffers, const SSILSettings &p_settings, RID p_linear_depth);
@@ -111,6 +108,7 @@ public:
void ssil_free(SSILRenderBuffers &p_ssil_buffers);
/* SSAO */
+ void ssao_set_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to);
struct SSAORenderBuffers {
bool half_size = false;
@@ -139,14 +137,7 @@ public:
float horizon = 0.06;
float sharpness = 0.98;
- RS::EnvironmentSSAOQuality quality = RS::ENV_SSAO_QUALITY_MEDIUM;
- bool half_size = false;
- float adaptive_target = 0.5;
- int blur_passes = 2;
- float fadeout_from = 50.0;
- float fadeout_to = 300.0;
-
- Size2i full_screen_size = Size2i();
+ Size2i full_screen_size;
};
void ssao_allocate_buffers(SSAORenderBuffers &p_ssao_buffers, const SSAOSettings &p_settings, RID p_linear_depth);
@@ -154,8 +145,12 @@ public:
void ssao_free(SSAORenderBuffers &p_ssao_buffers);
/* Screen Space Reflection */
+ void ssr_set_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality);
struct SSRRenderBuffers {
+ Size2i size;
+ RenderingServer::EnvironmentSSRRoughnessQuality roughness_quality = RenderingServer::ENV_SSR_ROUGHNESS_QUALITY_DISABLED;
+
RID normal_scaled;
RID depth_scaled;
RID blur_radius[2];
@@ -164,11 +159,40 @@ public:
RID output_slices[RendererSceneRender::MAX_RENDER_VIEWS];
};
- void ssr_allocate_buffers(SSRRenderBuffers &p_ssr_buffers, const RenderingDevice::DataFormat p_color_format, RenderingServer::EnvironmentSSRRoughnessQuality p_roughness_quality, const Size2i &p_screen_size, const uint32_t p_view_count);
- void screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const RID *p_diffuse_slices, const RID *p_normal_roughness_slices, RS::EnvironmentSSRRoughnessQuality p_roughness_quality, const RID *p_metallic_slices, const Color &p_metallic_mask, const RID *p_depth_slices, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets);
+ void ssr_allocate_buffers(SSRRenderBuffers &p_ssr_buffers, const RenderingDevice::DataFormat p_color_format, const Size2i &p_screen_size, const uint32_t p_view_count);
+ void screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const RID *p_diffuse_slices, const RID *p_normal_roughness_slices, const RID *p_metallic_slices, const RID *p_depth_slices, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets);
void ssr_free(SSRRenderBuffers &p_ssr_buffers);
+ /* subsurface scattering */
+ void sss_set_quality(RS::SubSurfaceScatteringQuality p_quality);
+ RS::SubSurfaceScatteringQuality sss_get_quality() const;
+ void sss_set_scale(float p_scale, float p_depth_scale);
+
+ void sub_surface_scattering(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_diffuse, RID p_depth, const Projection &p_camera, const Size2i &p_screen_size);
+
private:
+ /* Settings */
+
+ RS::EnvironmentSSAOQuality ssao_quality = RS::ENV_SSAO_QUALITY_MEDIUM;
+ bool ssao_half_size = false;
+ float ssao_adaptive_target = 0.5;
+ int ssao_blur_passes = 2;
+ float ssao_fadeout_from = 50.0;
+ float ssao_fadeout_to = 300.0;
+
+ RS::EnvironmentSSILQuality ssil_quality = RS::ENV_SSIL_QUALITY_MEDIUM;
+ bool ssil_half_size = false;
+ float ssil_adaptive_target = 0.5;
+ int ssil_blur_passes = 4;
+ float ssil_fadeout_from = 50.0;
+ float ssil_fadeout_to = 300.0;
+
+ RS::EnvironmentSSRRoughnessQuality ssr_roughness_quality = RS::ENV_SSR_ROUGHNESS_QUALITY_LOW;
+
+ RS::SubSurfaceScatteringQuality sss_quality = RS::SUB_SURFACE_SCATTERING_QUALITY_MEDIUM;
+ float sss_scale = 0.05;
+ float sss_depth_scale = 0.01;
+
/* SS Downsampler */
struct SSEffectsDownsamplePushConstant {
@@ -459,10 +483,7 @@ private:
uint32_t orthogonal; // 4 - 52
float filter_mipmap_levels; // 4 - 56
uint32_t use_half_res; // 4 - 60
- uint8_t metallic_mask[4]; // 4 - 64
-
- uint32_t view_index; // 4 - 68
- uint32_t pad[3]; // 12 - 80
+ uint32_t view_index; // 4 - 64
// float projection[16]; // this is in our ScreenSpaceReflectionSceneData now
};
@@ -501,6 +522,29 @@ private:
RID shader_version;
RID pipelines[SSR_VARIATIONS][SCREEN_SPACE_REFLECTION_FILTER_MAX];
} ssr_filter;
+
+ /* Subsurface scattering */
+
+ struct SubSurfaceScatteringPushConstant {
+ int32_t screen_size[2];
+ float camera_z_far;
+ float camera_z_near;
+
+ uint32_t vertical;
+ uint32_t orthogonal;
+ float unit_size;
+ float scale;
+
+ float depth_scale;
+ uint32_t pad[3];
+ };
+
+ struct SubSurfaceScattering {
+ SubSurfaceScatteringPushConstant push_constant;
+ SubsurfaceScatteringShaderRD shader;
+ RID shader_version;
+ RID pipelines[3]; //3 quality levels
+ } sss;
};
} // namespace RendererRD
diff --git a/servers/rendering/renderer_rd/effects/taa.cpp b/servers/rendering/renderer_rd/effects/taa.cpp
new file mode 100644
index 0000000000..657385a509
--- /dev/null
+++ b/servers/rendering/renderer_rd/effects/taa.cpp
@@ -0,0 +1,138 @@
+/*************************************************************************/
+/* taa.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "taa.h"
+#include "servers/rendering/renderer_rd/effects/copy_effects.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
+#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"
+
+using namespace RendererRD;
+
+TAA::TAA() {
+ Vector<String> taa_modes;
+ taa_modes.push_back("\n#define MODE_TAA_RESOLVE");
+ taa_shader.initialize(taa_modes);
+ shader_version = taa_shader.version_create();
+ pipeline = RD::get_singleton()->compute_pipeline_create(taa_shader.version_get_shader(shader_version, 0));
+}
+
+TAA::~TAA() {
+ taa_shader.version_free(shader_version);
+}
+
+void TAA::msaa_resolve(Ref<RenderSceneBuffersRD> p_render_buffers) {
+ if (!p_render_buffers->has_velocity_buffer(true)) {
+ // nothing to resolve
+ return;
+ }
+
+ for (uint32_t v = 0; v < p_render_buffers->get_view_count(); v++) {
+ RID velocity_buffer_msaa = p_render_buffers->get_velocity_buffer(true, v);
+ RID velocity_buffer = p_render_buffers->get_velocity_buffer(false, v);
+
+ RD::get_singleton()->texture_resolve_multisample(velocity_buffer_msaa, velocity_buffer);
+ }
+}
+
+void TAA::resolve(RID p_frame, RID p_temp, RID p_depth, RID p_velocity, RID p_prev_velocity, RID p_history, Size2 p_resolution, float p_z_near, float p_z_far) {
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ RID shader = taa_shader.version_get_shader(shader_version, 0);
+ ERR_FAIL_COND(shader.is_null());
+
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ TAAResolvePushConstant push_constant;
+ memset(&push_constant, 0, sizeof(TAAResolvePushConstant));
+ push_constant.resolution_width = p_resolution.width;
+ push_constant.resolution_height = p_resolution.height;
+ push_constant.disocclusion_threshold = 0.025f;
+ push_constant.disocclusion_scale = 10.0f;
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, pipeline);
+
+ RD::Uniform u_frame_source(RD::UNIFORM_TYPE_IMAGE, 0, { p_frame });
+ RD::Uniform u_depth(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 1, { default_sampler, p_depth });
+ RD::Uniform u_velocity(RD::UNIFORM_TYPE_IMAGE, 2, { p_velocity });
+ RD::Uniform u_prev_velocity(RD::UNIFORM_TYPE_IMAGE, 3, { p_prev_velocity });
+ RD::Uniform u_history(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 4, { default_sampler, p_history });
+ RD::Uniform u_frame_dest(RD::UNIFORM_TYPE_IMAGE, 5, { p_temp });
+
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_frame_source, u_depth, u_velocity, u_prev_velocity, u_history, u_frame_dest), 0);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(TAAResolvePushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_resolution.width, p_resolution.height, 1);
+ RD::get_singleton()->compute_list_end();
+}
+
+void TAA::process(Ref<RenderSceneBuffersRD> p_render_buffers, RD::DataFormat p_format, float p_z_near, float p_z_far) {
+ CopyEffects *copy_effects = CopyEffects::get_singleton();
+
+ uint32_t view_count = p_render_buffers->get_view_count();
+ Size2i internal_size = p_render_buffers->get_internal_size();
+ Size2i target_size = p_render_buffers->get_target_size();
+
+ bool just_allocated = false;
+ if (!p_render_buffers->has_texture(SNAME("taa"), SNAME("history"))) {
+ uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+
+ p_render_buffers->create_texture(SNAME("taa"), SNAME("history"), p_format, usage_bits);
+ p_render_buffers->create_texture(SNAME("taa"), SNAME("temp"), p_format, usage_bits);
+
+ p_render_buffers->create_texture(SNAME("taa"), SNAME("prev_velocity"), RD::DATA_FORMAT_R16G16_SFLOAT, usage_bits);
+
+ just_allocated = true;
+ }
+
+ RD::get_singleton()->draw_command_begin_label("TAA");
+
+ for (uint32_t v = 0; v < view_count; v++) {
+ // Get our (cached) slices
+ RID internal_texture = p_render_buffers->get_internal_texture(v);
+ RID velocity_buffer = p_render_buffers->get_velocity_buffer(false, v);
+ RID taa_history = p_render_buffers->get_texture_slice(SNAME("taa"), SNAME("history"), v, 0);
+ RID taa_prev_velocity = p_render_buffers->get_texture_slice(SNAME("taa"), SNAME("prev_velocity"), v, 0);
+
+ if (!just_allocated) {
+ RID depth_texture = p_render_buffers->get_depth_texture(v);
+ RID taa_temp = p_render_buffers->get_texture_slice(SNAME("taa"), SNAME("temp"), v, 0);
+ resolve(internal_texture, taa_temp, depth_texture, velocity_buffer, taa_prev_velocity, taa_history, Size2(internal_size.x, internal_size.y), p_z_near, p_z_far);
+ copy_effects->copy_to_rect(taa_temp, internal_texture, Rect2(0, 0, internal_size.x, internal_size.y));
+ }
+
+ copy_effects->copy_to_rect(internal_texture, taa_history, Rect2(0, 0, internal_size.x, internal_size.y));
+ copy_effects->copy_to_rect(velocity_buffer, taa_prev_velocity, Rect2(0, 0, target_size.x, target_size.y));
+ }
+
+ RD::get_singleton()->draw_command_end_label();
+}
diff --git a/servers/rendering/renderer_rd/effects/taa.h b/servers/rendering/renderer_rd/effects/taa.h
new file mode 100644
index 0000000000..ce4af18866
--- /dev/null
+++ b/servers/rendering/renderer_rd/effects/taa.h
@@ -0,0 +1,68 @@
+/*************************************************************************/
+/* taa.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef TAA_RD_H
+#define TAA_RD_H
+
+#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
+#include "servers/rendering/renderer_rd/shaders/effects/taa_resolve.glsl.gen.h"
+#include "servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h"
+#include "servers/rendering/renderer_scene_render.h"
+
+#include "servers/rendering_server.h"
+
+namespace RendererRD {
+
+class TAA {
+public:
+ TAA();
+ ~TAA();
+
+ void msaa_resolve(Ref<RenderSceneBuffersRD> p_render_buffers);
+ void process(Ref<RenderSceneBuffersRD> p_render_buffers, RD::DataFormat p_format, float p_z_near, float p_z_far);
+
+private:
+ struct TAAResolvePushConstant {
+ float resolution_width;
+ float resolution_height;
+ float disocclusion_threshold;
+ float disocclusion_scale;
+ };
+
+ TaaResolveShaderRD taa_shader;
+ RID shader_version;
+ RID pipeline;
+
+ void resolve(RID p_frame, RID p_temp, RID p_depth, RID p_velocity, RID p_prev_velocity, RID p_history, Size2 p_resolution, float p_z_near, float p_z_far);
+};
+
+} // namespace RendererRD
+
+#endif // TAA_RD_H
diff --git a/servers/rendering/renderer_rd/effects/tone_mapper.cpp b/servers/rendering/renderer_rd/effects/tone_mapper.cpp
index 38a4a37b8a..3a47b1420b 100644
--- a/servers/rendering/renderer_rd/effects/tone_mapper.cpp
+++ b/servers/rendering/renderer_rd/effects/tone_mapper.cpp
@@ -117,7 +117,7 @@ void ToneMapper::tonemapper(RID p_source_color, RID p_dst_framebuffer, const Ton
tonemap.push_constant.use_auto_exposure = p_settings.use_auto_exposure;
tonemap.push_constant.exposure = p_settings.exposure;
tonemap.push_constant.white = p_settings.white;
- tonemap.push_constant.auto_exposure_grey = p_settings.auto_exposure_grey;
+ tonemap.push_constant.auto_exposure_scale = p_settings.auto_exposure_scale;
tonemap.push_constant.luminance_multiplier = p_settings.luminance_multiplier;
tonemap.push_constant.use_color_correction = p_settings.use_color_correction;
@@ -203,7 +203,7 @@ void ToneMapper::tonemapper(RD::DrawListID p_subpass_draw_list, RID p_source_col
tonemap.push_constant.use_auto_exposure = p_settings.use_auto_exposure;
tonemap.push_constant.exposure = p_settings.exposure;
tonemap.push_constant.white = p_settings.white;
- tonemap.push_constant.auto_exposure_grey = p_settings.auto_exposure_grey;
+ tonemap.push_constant.auto_exposure_scale = p_settings.auto_exposure_scale;
tonemap.push_constant.use_color_correction = p_settings.use_color_correction;
diff --git a/servers/rendering/renderer_rd/effects/tone_mapper.h b/servers/rendering/renderer_rd/effects/tone_mapper.h
index 05db4a0cbe..e91118e241 100644
--- a/servers/rendering/renderer_rd/effects/tone_mapper.h
+++ b/servers/rendering/renderer_rd/effects/tone_mapper.h
@@ -77,7 +77,7 @@ private:
float exposure; // 4 - 84
float white; // 4 - 88
- float auto_exposure_grey; // 4 - 92
+ float auto_exposure_scale; // 4 - 92
float luminance_multiplier; // 4 - 96
float pixel_size[2]; // 8 - 104
@@ -124,7 +124,7 @@ public:
float white = 1.0;
bool use_auto_exposure = false;
- float auto_exposure_grey = 0.5;
+ float auto_exposure_scale = 0.5;
RID exposure_texture;
float luminance_multiplier = 1.0;
diff --git a/servers/rendering/renderer_rd/effects/vrs.cpp b/servers/rendering/renderer_rd/effects/vrs.cpp
index fa0b99fef9..701d53b41d 100644
--- a/servers/rendering/renderer_rd/effects/vrs.cpp
+++ b/servers/rendering/renderer_rd/effects/vrs.cpp
@@ -91,47 +91,19 @@ void VRS::copy_vrs(RID p_source_rd_texture, RID p_dest_framebuffer, bool p_multi
RD::get_singleton()->draw_list_end();
}
-void VRS::create_vrs_texture(const int p_base_width, const int p_base_height, const uint32_t p_view_count, RID &p_vrs_texture, RID &p_vrs_fb) {
- // TODO find a way to skip this if VRS is not supported, but we don't have access to VulkanContext here, even though we're in vulkan.. hmmm
-
- // TODO we should find some way to store this properly, we're assuming 16x16 as this seems to be the standard but in our vrs_capacities we
- // obtain a minimum and maximum size, and we should choose something within this range and then make sure that is consistently set when creating
- // our frame buffer. Also it is important that we make the resulting size we calculate down below available to the end user so they know the size
- // of the VRS buffer to supply.
- Size2i texel_size = Size2i(16, 16);
-
- RD::TextureFormat tf;
- if (p_view_count > 1) {
- tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
- } else {
- tf.texture_type = RD::TEXTURE_TYPE_2D;
- }
- tf.format = RD::DATA_FORMAT_R8_UINT;
- tf.width = p_base_width / texel_size.x;
- if (p_base_width % texel_size.x != 0) {
- tf.width++;
+Size2i VRS::get_vrs_texture_size(const Size2i p_base_size) const {
+ int32_t texel_width = RD::get_singleton()->limit_get(RD::LIMIT_VRS_TEXEL_WIDTH);
+ int32_t texel_height = RD::get_singleton()->limit_get(RD::LIMIT_VRS_TEXEL_HEIGHT);
+
+ int width = p_base_size.x / texel_width;
+ if (p_base_size.x % texel_width != 0) {
+ width++;
}
- tf.height = p_base_height / texel_size.y;
- if (p_base_height % texel_size.y != 0) {
- tf.height++;
+ int height = p_base_size.y / texel_height;
+ if (p_base_size.y % texel_height != 0) {
+ height++;
}
- tf.array_layers = p_view_count; // create a layer for every view
- tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_VRS_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
- tf.samples = RD::TEXTURE_SAMPLES_1;
-
- p_vrs_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
-
- // by default VRS is assumed to be our VRS attachment, but if we need to write into it, we need a bit more control
- Vector<RID> fb;
- fb.push_back(p_vrs_texture);
-
- RD::FramebufferPass pass;
- pass.color_attachments.push_back(0);
-
- Vector<RD::FramebufferPass> passes;
- passes.push_back(pass);
-
- p_vrs_fb = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, p_view_count);
+ return Size2i(width, height);
}
void VRS::update_vrs_texture(RID p_vrs_fb, RID p_render_target) {
@@ -146,10 +118,11 @@ void VRS::update_vrs_texture(RID p_vrs_fb, RID p_render_target) {
if (vrs_mode == RS::VIEWPORT_VRS_TEXTURE) {
RID vrs_texture = texture_storage->render_target_get_vrs_texture(p_render_target);
if (vrs_texture.is_valid()) {
- Texture *texture = texture_storage->get_texture(vrs_texture);
- if (texture) {
+ RID rd_texture = texture_storage->texture_get_rd_texture(vrs_texture);
+ int layers = texture_storage->texture_get_layers(vrs_texture);
+ if (rd_texture.is_valid()) {
// Copy into our density buffer
- copy_vrs(texture->rd_texture, p_vrs_fb, texture->layers > 1);
+ copy_vrs(rd_texture, p_vrs_fb, layers > 1);
}
}
} else if (vrs_mode == RS::VIEWPORT_VRS_XR) {
@@ -157,10 +130,12 @@ void VRS::update_vrs_texture(RID p_vrs_fb, RID p_render_target) {
if (interface.is_valid()) {
RID vrs_texture = interface->get_vrs_texture();
if (vrs_texture.is_valid()) {
- Texture *texture = texture_storage->get_texture(vrs_texture);
- if (texture) {
+ RID rd_texture = texture_storage->texture_get_rd_texture(vrs_texture);
+ int layers = texture_storage->texture_get_layers(vrs_texture);
+
+ if (rd_texture.is_valid()) {
// Copy into our density buffer
- copy_vrs(texture->rd_texture, p_vrs_fb, texture->layers > 1);
+ copy_vrs(rd_texture, p_vrs_fb, layers > 1);
}
}
}
diff --git a/servers/rendering/renderer_rd/effects/vrs.h b/servers/rendering/renderer_rd/effects/vrs.h
index dd15df615e..7125c6455d 100644
--- a/servers/rendering/renderer_rd/effects/vrs.h
+++ b/servers/rendering/renderer_rd/effects/vrs.h
@@ -66,7 +66,7 @@ public:
void copy_vrs(RID p_source_rd_texture, RID p_dest_framebuffer, bool p_multiview = false);
- void create_vrs_texture(const int p_base_width, const int p_base_height, const uint32_t p_view_count, RID &p_vrs_texture, RID &p_vrs_fb);
+ Size2i get_vrs_texture_size(const Size2i p_base_size) const;
void update_vrs_texture(RID p_vrs_fb, RID p_render_target);
};