diff options
Diffstat (limited to 'servers/rendering/renderer_rd/effects')
-rw-r--r-- | servers/rendering/renderer_rd/effects/bokeh_dof.cpp | 94 | ||||
-rw-r--r-- | servers/rendering/renderer_rd/effects/bokeh_dof.h | 9 | ||||
-rw-r--r-- | servers/rendering/renderer_rd/effects/copy_effects.cpp | 31 | ||||
-rw-r--r-- | servers/rendering/renderer_rd/effects/copy_effects.h | 10 | ||||
-rw-r--r-- | servers/rendering/renderer_rd/effects/fsr.cpp | 127 | ||||
-rw-r--r-- | servers/rendering/renderer_rd/effects/fsr.h | 73 | ||||
-rw-r--r-- | servers/rendering/renderer_rd/effects/ss_effects.cpp | 92 | ||||
-rw-r--r-- | servers/rendering/renderer_rd/effects/ss_effects.h | 29 | ||||
-rw-r--r-- | servers/rendering/renderer_rd/effects/taa.cpp | 138 | ||||
-rw-r--r-- | servers/rendering/renderer_rd/effects/taa.h | 68 | ||||
-rw-r--r-- | servers/rendering/renderer_rd/effects/tone_mapper.cpp | 4 | ||||
-rw-r--r-- | servers/rendering/renderer_rd/effects/tone_mapper.h | 4 | ||||
-rw-r--r-- | servers/rendering/renderer_rd/effects/vrs.cpp | 41 | ||||
-rw-r--r-- | servers/rendering/renderer_rd/effects/vrs.h | 2 |
14 files changed, 632 insertions, 90 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..53237c1dfb 100644 --- a/servers/rendering/renderer_rd/effects/copy_effects.cpp +++ b/servers/rendering/renderer_rd/effects/copy_effects.cpp @@ -654,7 +654,7 @@ 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_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_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 +678,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); @@ -705,7 +705,7 @@ void CopyEffects::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, con 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_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_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 +713,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 +732,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 +740,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 +767,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 +813,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 +838,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)); diff --git a/servers/rendering/renderer_rd/effects/copy_effects.h b/servers/rendering/renderer_rd/effects/copy_effects.h index d25555eee5..0ddb60ebef 100644 --- a/servers/rendering/renderer_rd/effects/copy_effects.h +++ b/servers/rendering/renderer_rd/effects/copy_effects.h @@ -86,7 +86,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; @@ -148,7 +148,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; @@ -321,11 +321,11 @@ public: 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_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_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_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_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); diff --git a/servers/rendering/renderer_rd/effects/fsr.cpp b/servers/rendering/renderer_rd/effects/fsr.cpp new file mode 100644 index 0000000000..5fde24a926 --- /dev/null +++ b/servers/rendering/renderer_rd/effects/fsr.cpp @@ -0,0 +1,127 @@ +/*************************************************************************/ +/* 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 "servers/rendering/renderer_rd/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..1adfba527a --- /dev/null +++ b/servers/rendering/renderer_rd/effects/fsr.h @@ -0,0 +1,73 @@ +/*************************************************************************/ +/* 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 "servers/rendering/renderer_rd/pipeline_cache_rd.h" +#include "servers/rendering/renderer_rd/shaders/effects/fsr_upscale.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 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/ss_effects.cpp b/servers/rendering/renderer_rd/effects/ss_effects.cpp index 874409b885..315bea2e67 100644 --- a/servers/rendering/renderer_rd/effects/ss_effects.cpp +++ b/servers/rendering/renderer_rd/effects/ss_effects.cpp @@ -32,6 +32,7 @@ #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; @@ -333,6 +334,22 @@ SSEffects::SSEffects() { } } } + + // Subsurface scattering + { + 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,6 +393,11 @@ SSEffects::~SSEffects() { RD::get_singleton()->free(ssao.importance_map_load_counter); } + { + // Cleanup Subsurface scattering + sss.shader.version_free(sss.shader_version); + } + singleton = nullptr; } @@ -1713,3 +1735,73 @@ void SSEffects::ssr_free(SSRRenderBuffers &p_ssr_buffers) { p_ssr_buffers.normal_scaled = RID(); } } + +/* Subsurface scattering */ + +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, float p_scale, float p_depth_scale, RenderingServer::SubSurfaceScatteringQuality p_quality) { + 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 = p_scale; + sss.push_constant.depth_scale = p_depth_scale; + + RID shader = sss.shader.version_get_shader(sss.shader_version, p_quality - 1); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sss.pipelines[p_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..a60f3a48ab 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 { @@ -168,6 +171,9 @@ public: 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_free(SSRRenderBuffers &p_ssr_buffers); + /* subsurface scattering */ + void sub_surface_scattering(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_diffuse, RID p_depth, const Projection &p_camera, const Size2i &p_screen_size, float p_scale, float p_depth_scale, RS::SubSurfaceScatteringQuality p_quality); + private: /* SS Downsampler */ @@ -501,6 +507,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 68cfd43d90..5ff00aa94c 100644 --- a/servers/rendering/renderer_rd/effects/vrs.cpp +++ b/servers/rendering/renderer_rd/effects/vrs.cpp @@ -91,47 +91,22 @@ 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 - +Size2i VRS::get_vrs_texture_size(const Size2i p_base_size) const { // 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++; + int width = p_base_size.x / texel_size.x; + if (p_base_size.x % texel_size.x != 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_size.y; + if (p_base_size.y % texel_size.y != 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) { 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); }; |