Re-implement subsurface scattering.
The size settings are more "just works", with default scale and depth scale values that don't need much tweaking. Additionally, a "skin" mode was added so skin looks better. EDIT: Cleaned up SSR filter shader a bit.
This commit is contained in:
parent
aeb95ef006
commit
c54f80d35c
|
@ -369,6 +369,11 @@ void EditorNode::_notification(int p_what) {
|
|||
RS::get_singleton()->environment_glow_set_use_bicubic_upscale(glow_bicubic);
|
||||
RS::EnvironmentSSRRoughnessQuality ssr_roughness_quality = RS::EnvironmentSSRRoughnessQuality(int(GLOBAL_GET("rendering/quality/screen_space_reflection/roughness_quality")));
|
||||
RS::get_singleton()->environment_set_ssr_roughness_quality(ssr_roughness_quality);
|
||||
RS::SubSurfaceScatteringQuality sss_quality = RS::SubSurfaceScatteringQuality(int(GLOBAL_GET("rendering/quality/subsurface_scattering/subsurface_scattering_quality")));
|
||||
RS::get_singleton()->sub_surface_scattering_set_quality(sss_quality);
|
||||
float sss_scale = GLOBAL_GET("rendering/quality/subsurface_scattering/subsurface_scattering_scale");
|
||||
float sss_depth_scale = GLOBAL_GET("rendering/quality/subsurface_scattering/subsurface_scattering_depth_scale");
|
||||
RS::get_singleton()->sub_surface_scattering_set_scale(sss_scale, sss_depth_scale);
|
||||
}
|
||||
|
||||
ResourceImporterTexture::get_singleton()->update_imports();
|
||||
|
|
|
@ -444,6 +444,9 @@ void BaseMaterial3D::_update_shader() {
|
|||
case DEPTH_DRAW_DISABLED: code += ",depth_draw_never"; break;
|
||||
}
|
||||
|
||||
if (features[FEATURE_SUBSURACE_SCATTERING] && flags[FLAG_SUBSURFACE_MODE_SKIN]) {
|
||||
code += ",sss_mode_skin";
|
||||
}
|
||||
if (transparency == TRANSPARENCY_ALPHA_DEPTH_PRE_PASS) {
|
||||
code += ",depth_prepass_alpha";
|
||||
}
|
||||
|
@ -2284,6 +2287,7 @@ void BaseMaterial3D::_bind_methods() {
|
|||
ADD_GROUP("Subsurf Scatter", "subsurf_scatter_");
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "subsurf_scatter_enabled"), "set_feature", "get_feature", FEATURE_SUBSURACE_SCATTERING);
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "subsurf_scatter_strength", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_subsurface_scattering_strength", "get_subsurface_scattering_strength");
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "subsurf_scatter_skin_mode"), "set_flag", "get_flag", FLAG_SUBSURFACE_MODE_SKIN);
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "subsurf_scatter_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_SUBSURFACE_SCATTERING);
|
||||
|
||||
ADD_GROUP("Transmission", "transmission_");
|
||||
|
@ -2436,6 +2440,7 @@ void BaseMaterial3D::_bind_methods() {
|
|||
BIND_ENUM_CONSTANT(FLAG_USE_SHADOW_TO_OPACITY);
|
||||
BIND_ENUM_CONSTANT(FLAG_USE_TEXTURE_REPEAT);
|
||||
BIND_ENUM_CONSTANT(FLAG_INVERT_HEIGHTMAP);
|
||||
BIND_ENUM_CONSTANT(FLAG_SUBSURFACE_MODE_SKIN);
|
||||
BIND_ENUM_CONSTANT(FLAG_MAX);
|
||||
|
||||
BIND_ENUM_CONSTANT(DIFFUSE_BURLEY);
|
||||
|
|
|
@ -218,6 +218,7 @@ public:
|
|||
FLAG_USE_SHADOW_TO_OPACITY,
|
||||
FLAG_USE_TEXTURE_REPEAT,
|
||||
FLAG_INVERT_HEIGHTMAP,
|
||||
FLAG_SUBSURFACE_MODE_SKIN,
|
||||
FLAG_MAX
|
||||
};
|
||||
|
||||
|
|
|
@ -266,6 +266,9 @@ public:
|
|||
virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_curve) = 0;
|
||||
virtual bool screen_space_roughness_limiter_is_active() const = 0;
|
||||
|
||||
virtual void sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality) = 0;
|
||||
virtual void sub_surface_scattering_set_scale(float p_scale, float p_depth_scale) = 0;
|
||||
|
||||
virtual bool free(RID p_rid) = 0;
|
||||
|
||||
virtual void update() = 0;
|
||||
|
|
|
@ -461,6 +461,53 @@ void RasterizerEffectsRD::screen_space_reflection(RID p_diffuse, RID p_normal, R
|
|||
RD::get_singleton()->compute_list_end();
|
||||
}
|
||||
|
||||
void RasterizerEffectsRD::sub_surface_scattering(RID p_diffuse, RID p_diffuse2, RID p_depth, const CameraMatrix &p_camera, const Size2i &p_screen_size, float p_scale, float p_depth_scale, RenderingServer::SubSurfaceScatteringQuality p_quality) {
|
||||
|
||||
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
|
||||
|
||||
int32_t x_groups = (p_screen_size.width - 1) / 8 + 1;
|
||||
int32_t y_groups = (p_screen_size.height - 1) / 8 + 1;
|
||||
|
||||
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
|
||||
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;
|
||||
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sss.pipelines[p_quality - 1]);
|
||||
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_diffuse), 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_diffuse2), 1);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth), 2);
|
||||
|
||||
RD::get_singleton()->compute_list_set_push_constant(compute_list, &sss.push_constant, sizeof(SubSurfaceScatteringPushConstant));
|
||||
|
||||
RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
|
||||
|
||||
RD::get_singleton()->compute_list_add_barrier(compute_list);
|
||||
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_diffuse2), 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_diffuse), 1);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth), 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(compute_list, x_groups, y_groups, 1);
|
||||
|
||||
RD::get_singleton()->compute_list_end();
|
||||
}
|
||||
}
|
||||
|
||||
void RasterizerEffectsRD::merge_specular(RID p_dest_framebuffer, RID p_specular, RID p_base, RID p_reflection) {
|
||||
|
||||
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, Vector<Color>());
|
||||
|
@ -1063,8 +1110,7 @@ void RasterizerEffectsRD::render_sky(RD::DrawListID p_list, float p_time, RID p_
|
|||
|
||||
RasterizerEffectsRD::RasterizerEffectsRD() {
|
||||
|
||||
{
|
||||
// Initialize blur
|
||||
{ // Initialize blur
|
||||
Vector<String> blur_modes;
|
||||
blur_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n");
|
||||
blur_modes.push_back("\n#define MODE_GAUSSIAN_GLOW\n");
|
||||
|
@ -1356,6 +1402,21 @@ RasterizerEffectsRD::RasterizerEffectsRD() {
|
|||
ssr_scale.pipeline = RD::get_singleton()->compute_pipeline_create(ssr_scale.shader.version_get_shader(ssr_scale.shader_version, 0));
|
||||
}
|
||||
|
||||
{
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
RD::SamplerState sampler;
|
||||
sampler.mag_filter = RD::SAMPLER_FILTER_LINEAR;
|
||||
sampler.min_filter = RD::SAMPLER_FILTER_LINEAR;
|
||||
|
@ -1412,4 +1473,8 @@ RasterizerEffectsRD::~RasterizerEffectsRD() {
|
|||
roughness_limiter.shader.version_free(roughness_limiter.shader_version);
|
||||
cubemap_downsampler.shader.version_free(cubemap_downsampler.shader_version);
|
||||
filter.shader.version_free(filter.shader_version);
|
||||
ssr.shader.version_free(ssr.shader_version);
|
||||
ssr_scale.shader.version_free(ssr_scale.shader_version);
|
||||
ssr_filter.shader.version_free(ssr_filter.shader_version);
|
||||
sss.shader.version_free(sss.shader_version);
|
||||
}
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#include "servers/rendering/rasterizer_rd/shaders/ssao.glsl.gen.h"
|
||||
#include "servers/rendering/rasterizer_rd/shaders/ssao_blur.glsl.gen.h"
|
||||
#include "servers/rendering/rasterizer_rd/shaders/ssao_minify.glsl.gen.h"
|
||||
#include "servers/rendering/rasterizer_rd/shaders/subsurface_scattering.glsl.gen.h"
|
||||
#include "servers/rendering/rasterizer_rd/shaders/tonemap.glsl.gen.h"
|
||||
|
||||
#include "servers/rendering_server.h"
|
||||
|
@ -480,6 +481,29 @@ class RasterizerEffectsRD {
|
|||
RID pipeline;
|
||||
} ssr_scale;
|
||||
|
||||
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;
|
||||
|
||||
RID default_sampler;
|
||||
RID default_mipmap_sampler;
|
||||
RID index_buffer;
|
||||
|
@ -571,6 +595,7 @@ public:
|
|||
|
||||
void screen_space_reflection(RID p_diffuse, RID p_normal, RS::EnvironmentSSRRoughnessQuality p_roughness_quality, RID p_roughness, RID p_blur_radius, RID p_blur_radius2, RID p_metallic, const Color &p_metallic_mask, RID p_depth, RID p_scale_depth, RID p_scale_normal, RID p_output, RID p_output_blur, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const CameraMatrix &p_camera);
|
||||
void merge_specular(RID p_dest_framebuffer, RID p_specular, RID p_base, RID p_reflection);
|
||||
void sub_surface_scattering(RID p_diffuse, RID p_diffuse2, RID p_depth, const CameraMatrix &p_camera, const Size2i &p_screen_size, float p_scale, float p_depth_scale, RS::SubSurfaceScatteringQuality p_quality);
|
||||
|
||||
RasterizerEffectsRD();
|
||||
~RasterizerEffectsRD();
|
||||
|
|
|
@ -1795,6 +1795,14 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor
|
|||
render_list.clear();
|
||||
_fill_render_list(p_cull_result, p_cull_count, PASS_MODE_COLOR, render_buffer == nullptr);
|
||||
|
||||
bool using_sss = render_buffer && scene_state.used_sss && sub_surface_scattering_get_quality() != RS::SUB_SURFACE_SCATTERING_QUALITY_DISABLED;
|
||||
|
||||
if (using_sss) {
|
||||
using_separate_specular = true;
|
||||
render_buffer->ensure_specular();
|
||||
using_separate_specular = true;
|
||||
opaque_specular_framebuffer = render_buffer->color_specular_fb;
|
||||
}
|
||||
RID radiance_uniform_set;
|
||||
bool draw_sky = false;
|
||||
|
||||
|
@ -1894,8 +1902,8 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor
|
|||
|
||||
RENDER_TIMESTAMP("Render Opaque Pass");
|
||||
|
||||
bool can_continue_color = !scene_state.used_screen_texture && !using_ssr && !scene_state.used_sss;
|
||||
bool can_continue_depth = !scene_state.used_depth_texture && !using_ssr;
|
||||
bool can_continue_color = !scene_state.used_screen_texture && !using_ssr && !using_sss;
|
||||
bool can_continue_depth = !scene_state.used_depth_texture && !using_ssr && !using_sss;
|
||||
|
||||
{
|
||||
|
||||
|
@ -1904,10 +1912,15 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor
|
|||
|
||||
//regular forward for now
|
||||
Vector<Color> c;
|
||||
c.push_back(clear_color.to_linear());
|
||||
if (using_separate_specular) {
|
||||
Color cc = clear_color.to_linear();
|
||||
cc.a = 0; //subsurf scatter must be 0
|
||||
c.push_back(cc);
|
||||
c.push_back(Color(0, 0, 0, 0));
|
||||
} else {
|
||||
c.push_back(clear_color.to_linear());
|
||||
}
|
||||
|
||||
RID framebuffer = using_separate_specular ? opaque_specular_framebuffer : opaque_framebuffer;
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, depth_pre_pass ? (using_ssao ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CONTINUE) : RD::INITIAL_ACTION_CLEAR, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0);
|
||||
_render_list(draw_list, RD::get_singleton()->framebuffer_get_format(framebuffer), render_list.elements, render_list.element_count, false, using_separate_specular ? PASS_MODE_COLOR_SPECULAR : PASS_MODE_COLOR, render_buffer == nullptr, radiance_uniform_set, render_buffers_uniform_set);
|
||||
|
@ -1950,10 +1963,9 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor
|
|||
|
||||
if (using_separate_specular) {
|
||||
|
||||
if (scene_state.used_sss) {
|
||||
if (using_sss) {
|
||||
RENDER_TIMESTAMP("Sub Surface Scattering");
|
||||
|
||||
//_process_sss()
|
||||
_process_sss(p_render_buffer, p_cam_projection);
|
||||
}
|
||||
|
||||
if (using_ssr) {
|
||||
|
@ -2620,6 +2632,8 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag
|
|||
actions.render_mode_defines["diffuse_lambert_wrap"] = "#define DIFFUSE_LAMBERT_WRAP\n";
|
||||
actions.render_mode_defines["diffuse_toon"] = "#define DIFFUSE_TOON\n";
|
||||
|
||||
actions.render_mode_defines["sss_mode_skin"] = "#define SSS_MODE_SKIN\n";
|
||||
|
||||
bool force_blinn = GLOBAL_GET("rendering/quality/shading/force_blinn_over_ggx");
|
||||
|
||||
if (!force_blinn) {
|
||||
|
|
|
@ -3203,6 +3203,26 @@ void RasterizerSceneRD::_free_render_buffer_data(RenderBuffers *rb) {
|
|||
}
|
||||
}
|
||||
|
||||
void RasterizerSceneRD::_process_sss(RID p_render_buffers, const CameraMatrix &p_camera) {
|
||||
|
||||
RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
|
||||
ERR_FAIL_COND(!rb);
|
||||
|
||||
bool can_use_effects = rb->width >= 8 && rb->height >= 8;
|
||||
|
||||
if (!can_use_effects) {
|
||||
//just copy
|
||||
return;
|
||||
}
|
||||
|
||||
if (rb->blur[0].texture.is_null()) {
|
||||
_allocate_blur_textures(rb);
|
||||
_render_buffers_uniform_set_changed(p_render_buffers);
|
||||
}
|
||||
|
||||
storage->get_effects()->sub_surface_scattering(rb->texture, rb->blur[0].mipmaps[0].texture, rb->depth_texture, p_camera, Size2i(rb->width, rb->height), sss_scale, sss_depth_scale, sss_quality);
|
||||
}
|
||||
|
||||
void RasterizerSceneRD::_process_ssr(RID p_render_buffers, RID p_dest_framebuffer, RID p_normal_buffer, RID p_roughness_buffer, RID p_specular_buffer, RID p_metallic, const Color &p_metallic_mask, RID p_environment, const CameraMatrix &p_projection, bool p_use_additive) {
|
||||
|
||||
RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
|
||||
|
@ -3547,6 +3567,19 @@ void RasterizerSceneRD::render_buffers_configure(RID p_render_buffers, RID p_ren
|
|||
_render_buffers_uniform_set_changed(p_render_buffers);
|
||||
}
|
||||
|
||||
void RasterizerSceneRD::sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality) {
|
||||
sss_quality = p_quality;
|
||||
}
|
||||
|
||||
RS::SubSurfaceScatteringQuality RasterizerSceneRD::sub_surface_scattering_get_quality() const {
|
||||
return sss_quality;
|
||||
}
|
||||
|
||||
void RasterizerSceneRD::sub_surface_scattering_set_scale(float p_scale, float p_depth_scale) {
|
||||
sss_scale = p_scale;
|
||||
sss_depth_scale = p_depth_scale;
|
||||
}
|
||||
|
||||
int RasterizerSceneRD::get_roughness_layers() const {
|
||||
return roughness_layers;
|
||||
}
|
||||
|
@ -4101,6 +4134,9 @@ RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) {
|
|||
screen_space_roughness_limiter_curve = GLOBAL_GET("rendering/quality/filters/screen_space_roughness_limiter_curve");
|
||||
glow_bicubic_upscale = int(GLOBAL_GET("rendering/quality/glow/upscale_mode")) > 0;
|
||||
ssr_roughness_quality = RS::EnvironmentSSRRoughnessQuality(int(GLOBAL_GET("rendering/quality/screen_space_reflection/roughness_quality")));
|
||||
sss_quality = RS::SubSurfaceScatteringQuality(int(GLOBAL_GET("rendering/quality/subsurface_scattering/subsurface_scattering_quality")));
|
||||
sss_scale = GLOBAL_GET("rendering/quality/subsurface_scattering/subsurface_scattering_scale");
|
||||
sss_depth_scale = GLOBAL_GET("rendering/quality/subsurface_scattering/subsurface_scattering_depth_scale");
|
||||
}
|
||||
|
||||
RasterizerSceneRD::~RasterizerSceneRD() {
|
||||
|
|
|
@ -93,6 +93,7 @@ protected:
|
|||
|
||||
void _process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection);
|
||||
void _process_ssr(RID p_render_buffers, RID p_dest_framebuffer, RID p_normal_buffer, RID p_roughness_buffer, RID p_specular_buffer, RID p_metallic, const Color &p_metallic_mask, RID p_environment, const CameraMatrix &p_projection, bool p_use_additive);
|
||||
void _process_sss(RID p_render_buffers, const CameraMatrix &p_camera);
|
||||
|
||||
void _setup_sky(RID p_environment, const Vector3 &p_position, const Size2i p_screen_size);
|
||||
void _update_sky(RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform);
|
||||
|
@ -698,6 +699,9 @@ private:
|
|||
RS::DOFBlurQuality dof_blur_quality = RS::DOF_BLUR_QUALITY_MEDIUM;
|
||||
RS::DOFBokehShape dof_blur_bokeh_shape = RS::DOF_BOKEH_HEXAGON;
|
||||
bool dof_blur_use_jitter = false;
|
||||
RS::SubSurfaceScatteringQuality sss_quality = RS::SUB_SURFACE_SCATTERING_QUALITY_MEDIUM;
|
||||
float sss_scale = 0.05;
|
||||
float sss_depth_scale = 0.01;
|
||||
|
||||
mutable RID_Owner<CameraEffects> camera_effects_owner;
|
||||
|
||||
|
@ -1110,6 +1114,10 @@ public:
|
|||
virtual bool screen_space_roughness_limiter_is_active() const;
|
||||
virtual float screen_space_roughness_limiter_get_curve() const;
|
||||
|
||||
virtual void sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality);
|
||||
RS::SubSurfaceScatteringQuality sub_surface_scattering_get_quality() const;
|
||||
virtual void sub_surface_scattering_set_scale(float p_scale, float p_depth_scale);
|
||||
|
||||
int get_roughness_layers() const;
|
||||
bool is_using_radiance_cubemap_array() const;
|
||||
|
||||
|
|
|
@ -25,4 +25,5 @@ if "RD_GLSL" in env["BUILDERS"]:
|
|||
env.RD_GLSL("screen_space_reflection.glsl")
|
||||
env.RD_GLSL("screen_space_reflection_filter.glsl")
|
||||
env.RD_GLSL("screen_space_reflection_scale.glsl")
|
||||
env.RD_GLSL("subsurface_scattering.glsl")
|
||||
env.RD_GLSL("specular_merge.glsl")
|
||||
|
|
|
@ -1697,6 +1697,9 @@ FRAGMENT_SHADER_CODE
|
|||
|
||||
#else
|
||||
|
||||
#ifdef SSS_MODE_SKIN
|
||||
sss_strength = -sss_strength;
|
||||
#endif
|
||||
diffuse_buffer = vec4(emission + diffuse_light + ambient_light, sss_strength);
|
||||
specular_buffer = vec4(specular_light, metallic);
|
||||
|
||||
|
|
|
@ -69,8 +69,6 @@ float gauss_weight(float p_val) {
|
|||
return mix(gauss_table[idx], gauss_table[idx + 1], c);
|
||||
}
|
||||
|
||||
#define GAUSS_WEIGHT(m_val) gauss_table[clamp(int(m_val * float(GAUSS_TABLE_SIZE - 1)), 0, GAUSS_TABLE_SIZE - 1)]
|
||||
|
||||
#define M_PI 3.14159265359
|
||||
|
||||
vec3 reconstructCSPosition(vec2 S, float z) {
|
||||
|
@ -105,17 +103,14 @@ void do_filter(inout vec4 accum, inout float accum_radius, inout float divisor,
|
|||
break;
|
||||
}
|
||||
|
||||
float contrib = 0.0;
|
||||
if (d < radius) {
|
||||
contrib += gauss_weight(d / radius);
|
||||
}
|
||||
|
||||
if (contrib > 0.0) {
|
||||
accum += imageLoad(source_ssr, tc) * contrib;
|
||||
float w = gauss_weight(d / radius);
|
||||
accum += imageLoad(source_ssr, tc) * w;
|
||||
#ifndef VERTICAL_PASS
|
||||
accum_radius += r * contrib;
|
||||
accum_radius += r * w;
|
||||
#endif
|
||||
divisor += contrib;
|
||||
divisor += w;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,198 @@
|
|||
/* clang-format off */
|
||||
[compute]
|
||||
|
||||
#version 450
|
||||
|
||||
VERSION_DEFINES
|
||||
|
||||
|
||||
|
||||
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
|
||||
|
||||
/* clang-format on */
|
||||
|
||||
#ifdef USE_25_SAMPLES
|
||||
const int kernel_size = 13;
|
||||
|
||||
const vec2 kernel[kernel_size] = vec2[](
|
||||
vec2(0.530605, 0.0),
|
||||
vec2(0.0211412, 0.0208333),
|
||||
vec2(0.0402784, 0.0833333),
|
||||
vec2(0.0493588, 0.1875),
|
||||
vec2(0.0410172, 0.333333),
|
||||
vec2(0.0263642, 0.520833),
|
||||
vec2(0.017924, 0.75),
|
||||
vec2(0.0128496, 1.02083),
|
||||
vec2(0.0094389, 1.33333),
|
||||
vec2(0.00700976, 1.6875),
|
||||
vec2(0.00500364, 2.08333),
|
||||
vec2(0.00333804, 2.52083),
|
||||
vec2(0.000973794, 3.0));
|
||||
|
||||
const vec4 skin_kernel[kernel_size] = vec4[](
|
||||
vec4(0.530605, 0.613514, 0.739601, 0),
|
||||
vec4(0.0211412, 0.0459286, 0.0378196, 0.0208333),
|
||||
vec4(0.0402784, 0.0657244, 0.04631, 0.0833333),
|
||||
vec4(0.0493588, 0.0367726, 0.0219485, 0.1875),
|
||||
vec4(0.0410172, 0.0199899, 0.0118481, 0.333333),
|
||||
vec4(0.0263642, 0.0119715, 0.00684598, 0.520833),
|
||||
vec4(0.017924, 0.00711691, 0.00347194, 0.75),
|
||||
vec4(0.0128496, 0.00356329, 0.00132016, 1.02083),
|
||||
vec4(0.0094389, 0.00139119, 0.000416598, 1.33333),
|
||||
vec4(0.00700976, 0.00049366, 0.000151938, 1.6875),
|
||||
vec4(0.00500364, 0.00020094, 5.28848e-005, 2.08333),
|
||||
vec4(0.00333804, 7.85443e-005, 1.2945e-005, 2.52083),
|
||||
vec4(0.000973794, 1.11862e-005, 9.43437e-007, 3));
|
||||
|
||||
#endif //USE_25_SAMPLES
|
||||
|
||||
#ifdef USE_17_SAMPLES
|
||||
const int kernel_size = 9;
|
||||
const vec2 kernel[kernel_size] = vec2[](
|
||||
vec2(0.536343, 0.0),
|
||||
vec2(0.0324462, 0.03125),
|
||||
vec2(0.0582416, 0.125),
|
||||
vec2(0.0571056, 0.28125),
|
||||
vec2(0.0347317, 0.5),
|
||||
vec2(0.0216301, 0.78125),
|
||||
vec2(0.0144609, 1.125),
|
||||
vec2(0.0100386, 1.53125),
|
||||
vec2(0.00317394, 2.0));
|
||||
|
||||
const vec4 skin_kernel[kernel_size] = vec4[](
|
||||
vec4(0.536343, 0.624624, 0.748867, 0),
|
||||
vec4(0.0324462, 0.0656718, 0.0532821, 0.03125),
|
||||
vec4(0.0582416, 0.0659959, 0.0411329, 0.125),
|
||||
vec4(0.0571056, 0.0287432, 0.0172844, 0.28125),
|
||||
vec4(0.0347317, 0.0151085, 0.00871983, 0.5),
|
||||
vec4(0.0216301, 0.00794618, 0.00376991, 0.78125),
|
||||
vec4(0.0144609, 0.00317269, 0.00106399, 1.125),
|
||||
vec4(0.0100386, 0.000914679, 0.000275702, 1.53125),
|
||||
vec4(0.00317394, 0.000134823, 3.77269e-005, 2));
|
||||
#endif //USE_17_SAMPLES
|
||||
|
||||
#ifdef USE_11_SAMPLES
|
||||
const int kernel_size = 6;
|
||||
const vec2 kernel[kernel_size] = vec2[](
|
||||
vec2(0.560479, 0.0),
|
||||
vec2(0.0771802, 0.08),
|
||||
vec2(0.0821904, 0.32),
|
||||
vec2(0.03639, 0.72),
|
||||
vec2(0.0192831, 1.28),
|
||||
vec2(0.00471691, 2.0));
|
||||
|
||||
const vec4 skin_kernel[kernel_size] = vec4[](
|
||||
|
||||
vec4(0.560479, 0.669086, 0.784728, 0),
|
||||
vec4(0.0771802, 0.113491, 0.0793803, 0.08),
|
||||
vec4(0.0821904, 0.0358608, 0.0209261, 0.32),
|
||||
vec4(0.03639, 0.0130999, 0.00643685, 0.72),
|
||||
vec4(0.0192831, 0.00282018, 0.00084214, 1.28),
|
||||
vec4(0.00471691, 0.000184771, 5.07565e-005, 2));
|
||||
|
||||
#endif //USE_11_SAMPLES
|
||||
|
||||
layout(push_constant, binding = 1, std430) uniform Params {
|
||||
|
||||
ivec2 screen_size;
|
||||
float camera_z_far;
|
||||
float camera_z_near;
|
||||
|
||||
bool vertical;
|
||||
bool orthogonal;
|
||||
float unit_size;
|
||||
float scale;
|
||||
|
||||
float depth_scale;
|
||||
uint pad[3];
|
||||
}
|
||||
params;
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2D source_image;
|
||||
layout(rgba16f, set = 1, binding = 0) uniform restrict writeonly image2D dest_image;
|
||||
layout(set = 2, binding = 0) uniform sampler2D source_depth;
|
||||
|
||||
void do_filter(inout vec3 color_accum, inout vec3 divisor, vec2 uv, vec2 step, bool p_skin) {
|
||||
|
||||
// Accumulate the other samples:
|
||||
for (int i = 1; i < kernel_size; i++) {
|
||||
// Fetch color and depth for current sample:
|
||||
vec2 offset = uv + kernel[i].y * step;
|
||||
vec4 color = texture(source_image, offset);
|
||||
|
||||
if (abs(color.a) < 0.001) {
|
||||
break; //mix no more
|
||||
}
|
||||
|
||||
vec3 w;
|
||||
if (p_skin) {
|
||||
//skin
|
||||
w = skin_kernel[i].rgb;
|
||||
} else {
|
||||
w = vec3(kernel[i].x);
|
||||
}
|
||||
|
||||
color_accum += color.rgb * w;
|
||||
divisor += w;
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
|
||||
// Pixel being shaded
|
||||
ivec2 ssC = ivec2(gl_GlobalInvocationID.xy);
|
||||
|
||||
if (any(greaterThan(ssC, params.screen_size))) { //too large, do nothing
|
||||
return;
|
||||
}
|
||||
|
||||
vec2 uv = (vec2(ssC) + 0.5) / vec2(params.screen_size);
|
||||
|
||||
// Fetch color of current pixel:
|
||||
vec4 base_color = texture(source_image, uv);
|
||||
float strength = abs(base_color.a);
|
||||
|
||||
if (strength > 0.0) {
|
||||
|
||||
vec2 dir = params.vertical ? vec2(0.0, 1.0) : vec2(1.0, 0.0);
|
||||
|
||||
// Fetch linear depth of current pixel:
|
||||
float depth = texture(source_depth, uv).r * 2.0 - 1.0;
|
||||
float depth_scale;
|
||||
|
||||
if (params.orthogonal) {
|
||||
depth = ((depth + (params.camera_z_far + params.camera_z_near) / (params.camera_z_far - params.camera_z_near)) * (params.camera_z_far - params.camera_z_near)) / 2.0;
|
||||
depth_scale = params.unit_size; //remember depth is negative by default in OpenGL
|
||||
} else {
|
||||
depth = 2.0 * params.camera_z_near * params.camera_z_far / (params.camera_z_far + params.camera_z_near - depth * (params.camera_z_far - params.camera_z_near));
|
||||
depth_scale = params.unit_size / depth; //remember depth is negative by default in OpenGL
|
||||
}
|
||||
|
||||
float scale = mix(params.scale, depth_scale, params.depth_scale);
|
||||
|
||||
// Calculate the final step to fetch the surrounding pixels:
|
||||
vec2 step = scale * dir;
|
||||
step *= strength;
|
||||
step /= 3.0;
|
||||
// Accumulate the center sample:
|
||||
|
||||
vec3 divisor;
|
||||
bool skin = bool(base_color.a < 0.0);
|
||||
|
||||
if (skin) {
|
||||
//skin
|
||||
divisor = skin_kernel[0].rgb;
|
||||
} else {
|
||||
divisor = vec3(kernel[0].x);
|
||||
}
|
||||
|
||||
vec3 color = base_color.rgb * divisor;
|
||||
|
||||
do_filter(color, divisor, uv, step, skin);
|
||||
do_filter(color, divisor, uv, -step, skin);
|
||||
|
||||
base_color.rgb = color / divisor;
|
||||
}
|
||||
|
||||
imageStore(dest_image, ssC, base_color);
|
||||
}
|
|
@ -541,6 +541,8 @@ public:
|
|||
BIND5(environment_set_fog_height, RID, bool, float, float, float)
|
||||
|
||||
BIND2(screen_space_roughness_limiter_set_active, bool, float)
|
||||
BIND1(sub_surface_scattering_set_quality, SubSurfaceScatteringQuality)
|
||||
BIND2(sub_surface_scattering_set_scale, float, float)
|
||||
|
||||
/* CAMERA EFFECTS */
|
||||
|
||||
|
|
|
@ -456,6 +456,8 @@ public:
|
|||
FUNC5(environment_set_fog_height, RID, bool, float, float, float)
|
||||
|
||||
FUNC2(screen_space_roughness_limiter_set_active, bool, float)
|
||||
FUNC1(sub_surface_scattering_set_quality, SubSurfaceScatteringQuality)
|
||||
FUNC2(sub_surface_scattering_set_scale, float, float)
|
||||
|
||||
FUNCRID(camera_effects)
|
||||
|
||||
|
|
|
@ -168,6 +168,8 @@ ShaderTypes::ShaderTypes() {
|
|||
|
||||
shader_modes[RS::SHADER_SPATIAL].modes.push_back("depth_test_disabled");
|
||||
|
||||
shader_modes[RS::SHADER_SPATIAL].modes.push_back("sss_mode_skin");
|
||||
|
||||
shader_modes[RS::SHADER_SPATIAL].modes.push_back("cull_back");
|
||||
shader_modes[RS::SHADER_SPATIAL].modes.push_back("cull_front");
|
||||
shader_modes[RS::SHADER_SPATIAL].modes.push_back("cull_disabled");
|
||||
|
|
|
@ -2362,6 +2362,13 @@ RenderingServer::RenderingServer() {
|
|||
|
||||
GLOBAL_DEF("rendering/quality/screen_space_reflection/roughness_quality", 1);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/screen_space_reflection/roughness_quality", PropertyInfo(Variant::INT, "rendering/quality/screen_space_reflection/roughness_quality", PROPERTY_HINT_ENUM, "Disabled (Fastest),Low, Medium, High (Slowest)"));
|
||||
|
||||
GLOBAL_DEF("rendering/quality/subsurface_scattering/subsurface_scattering_quality", 1);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/subsurface_scattering/subsurface_scattering_quality", PropertyInfo(Variant::INT, "rendering/quality/subsurface_scattering/subsurface_scattering_quality", PROPERTY_HINT_ENUM, "Disabled, Low (Fastest),Medium, High (Slowest)"));
|
||||
GLOBAL_DEF("rendering/quality/subsurface_scattering/subsurface_scattering_scale", 0.05);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/subsurface_scattering/subsurface_scattering_scale", PropertyInfo(Variant::FLOAT, "rendering/quality/subsurface_scattering/subsurface_scattering_scale", PROPERTY_HINT_RANGE, "0.001,1,0.001"));
|
||||
GLOBAL_DEF("rendering/quality/subsurface_scattering/subsurface_scattering_depth_scale", 0.01);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/subsurface_scattering/subsurface_scattering_depth_scale", PropertyInfo(Variant::FLOAT, "rendering/quality/subsurface_scattering/subsurface_scattering_depth_scale", PROPERTY_HINT_RANGE, "0.001,1,0.001"));
|
||||
}
|
||||
|
||||
RenderingServer::~RenderingServer() {
|
||||
|
|
|
@ -782,6 +782,16 @@ public:
|
|||
|
||||
virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_curve) = 0;
|
||||
|
||||
enum SubSurfaceScatteringQuality {
|
||||
SUB_SURFACE_SCATTERING_QUALITY_DISABLED,
|
||||
SUB_SURFACE_SCATTERING_QUALITY_LOW,
|
||||
SUB_SURFACE_SCATTERING_QUALITY_MEDIUM,
|
||||
SUB_SURFACE_SCATTERING_QUALITY_HIGH,
|
||||
};
|
||||
|
||||
virtual void sub_surface_scattering_set_quality(SubSurfaceScatteringQuality p_quality) = 0;
|
||||
virtual void sub_surface_scattering_set_scale(float p_scale, float p_depth_scale) = 0;
|
||||
|
||||
/* CAMERA EFFECTS */
|
||||
|
||||
virtual RID camera_effects_create() = 0;
|
||||
|
|
Loading…
Reference in New Issue