Improve SDFGI indirect light feedback loop

-Use occlusion for feedback, further reduces light leaking.
-More control on feedback, now its a slider.
This commit is contained in:
reduz 2021-02-07 21:08:59 -03:00
parent 57e2822a05
commit 3e2281a347
11 changed files with 71 additions and 44 deletions

View File

@ -520,13 +520,12 @@ bool Environment::is_sdfgi_using_occlusion() const {
return sdfgi_use_occlusion;
}
void Environment::set_sdfgi_use_multi_bounce(bool p_enabled) {
sdfgi_use_multibounce = p_enabled;
void Environment::set_sdfgi_bounce_feedback(float p_amount) {
sdfgi_bounce_feedback = p_amount;
_update_sdfgi();
}
bool Environment::is_sdfgi_using_multi_bounce() const {
return sdfgi_use_multibounce;
float Environment::get_sdfgi_bounce_feedback() const {
return sdfgi_bounce_feedback;
}
void Environment::set_sdfgi_read_sky_light(bool p_enabled) {
@ -573,7 +572,7 @@ void Environment::_update_sdfgi() {
sdfgi_min_cell_size,
RS::EnvironmentSDFGIYScale(sdfgi_y_scale),
sdfgi_use_occlusion,
sdfgi_use_multibounce,
sdfgi_bounce_feedback,
sdfgi_read_sky_light,
sdfgi_energy,
sdfgi_normal_bias,
@ -1207,8 +1206,8 @@ void Environment::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_sdfgi_y_scale"), &Environment::get_sdfgi_y_scale);
ClassDB::bind_method(D_METHOD("set_sdfgi_use_occlusion", "enable"), &Environment::set_sdfgi_use_occlusion);
ClassDB::bind_method(D_METHOD("is_sdfgi_using_occlusion"), &Environment::is_sdfgi_using_occlusion);
ClassDB::bind_method(D_METHOD("set_sdfgi_use_multi_bounce", "enable"), &Environment::set_sdfgi_use_multi_bounce);
ClassDB::bind_method(D_METHOD("is_sdfgi_using_multi_bounce"), &Environment::is_sdfgi_using_multi_bounce);
ClassDB::bind_method(D_METHOD("set_sdfgi_bounce_feedback", "amount"), &Environment::set_sdfgi_bounce_feedback);
ClassDB::bind_method(D_METHOD("get_sdfgi_bounce_feedback"), &Environment::get_sdfgi_bounce_feedback);
ClassDB::bind_method(D_METHOD("set_sdfgi_read_sky_light", "enable"), &Environment::set_sdfgi_read_sky_light);
ClassDB::bind_method(D_METHOD("is_sdfgi_reading_sky_light"), &Environment::is_sdfgi_reading_sky_light);
ClassDB::bind_method(D_METHOD("set_sdfgi_energy", "amount"), &Environment::set_sdfgi_energy);
@ -1220,9 +1219,9 @@ void Environment::_bind_methods() {
ADD_GROUP("SDFGI", "sdfgi_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sdfgi_enabled"), "set_sdfgi_enabled", "is_sdfgi_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sdfgi_use_multi_bounce"), "set_sdfgi_use_multi_bounce", "is_sdfgi_using_multi_bounce");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sdfgi_use_occlusion"), "set_sdfgi_use_occlusion", "is_sdfgi_using_occlusion");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sdfgi_read_sky_light"), "set_sdfgi_read_sky_light", "is_sdfgi_reading_sky_light");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sdfgi_bounce_feedback", PROPERTY_HINT_RANGE, "0,1.99,0.01"), "set_sdfgi_bounce_feedback", "get_sdfgi_bounce_feedback");
ADD_PROPERTY(PropertyInfo(Variant::INT, "sdfgi_cascades", PROPERTY_HINT_ENUM, "4 Cascades,6 Cascades,8 Cascades"), "set_sdfgi_cascades", "get_sdfgi_cascades");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sdfgi_min_cell_size", PROPERTY_HINT_RANGE, "0.01,64,0.01"), "set_sdfgi_min_cell_size", "get_sdfgi_min_cell_size");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sdfgi_cascade0_distance", PROPERTY_HINT_RANGE, "0.1,16384,0.1,or_greater"), "set_sdfgi_cascade0_distance", "get_sdfgi_cascade0_distance");

View File

@ -156,7 +156,7 @@ private:
float sdfgi_min_cell_size = 0.2;
SDFGIYScale sdfgi_y_scale = SDFGI_Y_SCALE_DISABLED;
bool sdfgi_use_occlusion = false;
bool sdfgi_use_multibounce = false;
float sdfgi_bounce_feedback = 0.0;
bool sdfgi_read_sky_light = false;
float sdfgi_energy = 1.0;
float sdfgi_normal_bias = 1.1;
@ -318,8 +318,8 @@ public:
SDFGIYScale get_sdfgi_y_scale() const;
void set_sdfgi_use_occlusion(bool p_enabled);
bool is_sdfgi_using_occlusion() const;
void set_sdfgi_use_multi_bounce(bool p_enabled);
bool is_sdfgi_using_multi_bounce() const;
void set_sdfgi_bounce_feedback(float p_amount);
float get_sdfgi_bounce_feedback() const;
void set_sdfgi_read_sky_light(bool p_enabled);
bool is_sdfgi_reading_sky_light() const;
void set_sdfgi_energy(float p_energy);

View File

@ -667,6 +667,13 @@ void RendererSceneRenderRD::sdfgi_update(RID p_render_buffers, RID p_environment
u.ids.push_back(rb->sdfgi->lightprobe_texture);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.binding = 11;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.ids.push_back(rb->sdfgi->occlusion_texture);
uniforms.push_back(u);
}
cascade.sdf_direct_light_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sdfgi_shader.direct_light.version_get_shader(sdfgi_shader.direct_light_shader, 0), 0);
}
@ -949,7 +956,7 @@ void RendererSceneRenderRD::sdfgi_update(RID p_render_buffers, RID p_environment
sdfgi->cascades[i].integrate_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sdfgi_shader.integrate.version_get_shader(sdfgi_shader.integrate_shader, 0), 0);
}
sdfgi->uses_multibounce = env->sdfgi_use_multibounce;
sdfgi->bounce_feedback = env->sdfgi_bounce_feedback;
sdfgi->energy = env->sdfgi_energy;
sdfgi->normal_bias = env->sdfgi_normal_bias;
sdfgi->probe_bias = env->sdfgi_probe_bias;
@ -962,7 +969,7 @@ void RendererSceneRenderRD::sdfgi_update(RID p_render_buffers, RID p_environment
//check for updates
sdfgi->uses_multibounce = env->sdfgi_use_multibounce;
sdfgi->bounce_feedback = env->sdfgi_bounce_feedback;
sdfgi->energy = env->sdfgi_energy;
sdfgi->normal_bias = env->sdfgi_normal_bias;
sdfgi->probe_bias = env->sdfgi_probe_bias;
@ -1172,8 +1179,9 @@ void RendererSceneRenderRD::_sdfgi_update_light(RID p_render_buffers, RID p_envi
push_constant.grid_size[2] = rb->sdfgi->cascade_size;
push_constant.max_cascades = rb->sdfgi->cascades.size();
push_constant.probe_axis_size = rb->sdfgi->probe_axis_count;
push_constant.multibounce = rb->sdfgi->uses_multibounce;
push_constant.bounce_feedback = rb->sdfgi->bounce_feedback;
push_constant.y_mult = rb->sdfgi->y_mult;
push_constant.use_occlusion = rb->sdfgi->uses_occlusion;
for (uint32_t i = 0; i < rb->sdfgi->cascades.size(); i++) {
SDFGI::Cascade &cascade = rb->sdfgi->cascades[i];
@ -3073,7 +3081,7 @@ void RendererSceneRenderRD::environment_glow_set_use_high_quality(bool p_enable)
glow_high_quality = p_enable;
}
void RendererSceneRenderRD::environment_set_sdfgi(RID p_env, bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, bool p_use_multibounce, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) {
void RendererSceneRenderRD::environment_set_sdfgi(RID p_env, bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) {
Environment *env = environment_owner.getornull(p_env);
ERR_FAIL_COND(!env);
@ -3085,7 +3093,7 @@ void RendererSceneRenderRD::environment_set_sdfgi(RID p_env, bool p_enable, RS::
env->sdfgi_cascades = p_cascades;
env->sdfgi_min_cell_size = p_min_cell_size;
env->sdfgi_use_occlusion = p_use_occlusion;
env->sdfgi_use_multibounce = p_use_multibounce;
env->sdfgi_bounce_feedback = p_bounce_feedback;
env->sdfgi_read_sky_light = p_read_sky;
env->sdfgi_energy = p_energy;
env->sdfgi_normal_bias = p_normal_bias;
@ -7782,7 +7790,7 @@ void RendererSceneRenderRD::_render_sdfgi_region(RID p_render_buffers, int p_reg
RD::get_singleton()->compute_list_add_barrier(compute_list);
if (rb->sdfgi->uses_multibounce) {
if (rb->sdfgi->bounce_feedback > 0.0) {
//multibounce requires this to be stored so direct light can read from it
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sdfgi_shader.integrate_pipeline[SDGIShader::INTEGRATE_MODE_STORE]);
@ -8120,8 +8128,9 @@ void RendererSceneRenderRD::_render_sdfgi_static_lights(RID p_render_buffers, ui
dl_push_constant.grid_size[2] = rb->sdfgi->cascade_size;
dl_push_constant.max_cascades = rb->sdfgi->cascades.size();
dl_push_constant.probe_axis_size = rb->sdfgi->probe_axis_count;
dl_push_constant.multibounce = false; // this is static light, do not multibounce yet
dl_push_constant.bounce_feedback = 0.0; // this is static light, do not multibounce yet
dl_push_constant.y_mult = rb->sdfgi->y_mult;
dl_push_constant.use_occlusion = rb->sdfgi->uses_occlusion;
//all must be processed
dl_push_constant.process_offset = 0;

View File

@ -778,7 +778,7 @@ private:
RS::EnvironmentSDFGICascades sdfgi_cascades;
float sdfgi_min_cell_size = 0.2;
bool sdfgi_use_occlusion = false;
bool sdfgi_use_multibounce = false;
float sdfgi_bounce_feedback = 0.0;
bool sdfgi_read_sky_light = false;
float sdfgi_energy = 1.0;
float sdfgi_normal_bias = 1.1;
@ -1028,7 +1028,7 @@ private:
RID cascades_ubo;
bool uses_occlusion = false;
bool uses_multibounce = false;
float bounce_feedback = 0.0;
bool reads_sky = false;
float energy = 1.0;
float normal_bias = 1.1;
@ -1163,9 +1163,9 @@ private:
uint32_t process_increment;
int32_t probe_axis_size;
uint32_t multibounce;
float bounce_feedback;
float y_mult;
uint32_t pad;
uint32_t use_occlusion;
};
enum {
@ -1721,7 +1721,7 @@ public:
bool environment_is_ssr_enabled(RID p_env) const;
bool environment_is_sdfgi_enabled(RID p_env) const;
virtual void environment_set_sdfgi(RID p_env, bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, bool p_use_multibounce, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias);
virtual void environment_set_sdfgi(RID p_env, bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias);
virtual void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count);
virtual void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames);
virtual void environment_set_sdfgi_frames_to_update_light(RS::EnvironmentSDFGIFramesToUpdateLight p_update);

View File

@ -80,6 +80,7 @@ layout(set = 0, binding = 9, std140) buffer restrict readonly Lights {
lights;
layout(set = 0, binding = 10) uniform texture2DArray lightprobe_texture;
layout(set = 0, binding = 11) uniform texture3D occlusion_texture;
layout(push_constant, binding = 0, std430) uniform Params {
vec3 grid_size;
@ -91,9 +92,9 @@ layout(push_constant, binding = 0, std430) uniform Params {
uint process_increment;
int probe_axis_size;
bool multibounce;
float bounce_feedback;
float y_mult;
uint pad;
bool use_occlusion;
}
params;
@ -159,7 +160,8 @@ void main() {
// Add indirect light first, in order to save computation resources
#ifdef MODE_PROCESS_DYNAMIC
if (params.multibounce) {
if (params.bounce_feedback > 0.001) {
vec3 feedback = (params.bounce_feedback < 1.0) ? (albedo * params.bounce_feedback) : mix(albedo, vec3(1.0), params.bounce_feedback - 1.0);
vec3 pos = (vec3(positioni) + vec3(0.5)) * float(params.probe_axis_size - 1) / params.grid_size;
ivec3 probe_base_pos = ivec3(pos);
@ -172,7 +174,7 @@ void main() {
vec3 base_tex_posf = vec3(tex_pos);
vec2 tex_pixel_size = 1.0 / vec2(ivec2((OCT_SIZE + 2) * params.probe_axis_size * params.probe_axis_size, (OCT_SIZE + 2) * params.probe_axis_size));
vec3 probe_uv_offset = (ivec3(OCT_SIZE + 2, OCT_SIZE + 2, (OCT_SIZE + 2) * params.probe_axis_size)) * tex_pixel_size.xyx;
vec3 probe_uv_offset = vec3(ivec3(OCT_SIZE + 2, OCT_SIZE + 2, (OCT_SIZE + 2) * params.probe_axis_size)) * tex_pixel_size.xyx;
for (uint j = 0; j < 8; j++) {
ivec3 offset = (ivec3(j) >> ivec3(0, 1, 2)) & ivec3(1, 1, 1);
@ -192,18 +194,35 @@ void main() {
for (uint k = 0; k < 6; k++) {
if (bool(valid_aniso & (1 << k))) {
vec3 n = aniso_dir[k];
float weight = trilinear.x * trilinear.y * trilinear.z * max(0.005, dot(n, probe_dir));
float weight = trilinear.x * trilinear.y * trilinear.z * max(0, dot(n, probe_dir));
vec3 tex_posf = base_tex_posf + vec3(octahedron_encode(n) * float(OCT_SIZE), 0.0);
tex_posf.xy *= tex_pixel_size;
if (weight > 0.0 && params.use_occlusion) {
ivec3 occ_indexv = abs((cascades.data[params.cascade].probe_world_offset + probe_posi) & ivec3(1, 1, 1)) * ivec3(1, 2, 4);
vec4 occ_mask = mix(vec4(0.0), vec4(1.0), equal(ivec4(occ_indexv.x | occ_indexv.y), ivec4(0, 1, 2, 3)));
vec3 pos_uvw = tex_posf;
pos_uvw.xy += vec2(offset.xy) * probe_uv_offset.xy;
pos_uvw.x += float(offset.z) * probe_uv_offset.z;
vec3 indirect_light = textureLod(sampler2DArray(lightprobe_texture, linear_sampler), pos_uvw, 0.0).rgb;
vec3 occ_pos = (vec3(positioni) + aniso_dir[k] + vec3(0.5)) / params.grid_size;
occ_pos.z += float(params.cascade);
if (occ_indexv.z != 0) { //z bit is on, means index is >=4, so make it switch to the other half of textures
occ_pos.x += 1.0;
}
occ_pos *= vec3(0.5, 1.0, 1.0 / float(params.max_cascades)); //renormalize
float occlusion = dot(textureLod(sampler3D(occlusion_texture, linear_sampler), occ_pos, 0.0), occ_mask);
light_accum[k] += indirect_light * weight;
weight_accum[k] += weight;
weight *= occlusion;
}
if (weight > 0.0) {
vec3 tex_posf = base_tex_posf + vec3(octahedron_encode(n) * float(OCT_SIZE), 0.0);
tex_posf.xy *= tex_pixel_size;
vec3 pos_uvw = tex_posf;
pos_uvw.xy += vec2(offset.xy) * probe_uv_offset.xy;
pos_uvw.x += float(offset.z) * probe_uv_offset.z;
vec3 indirect_light = textureLod(sampler2DArray(lightprobe_texture, linear_sampler), pos_uvw, 0.0).rgb;
light_accum[k] += indirect_light * weight;
weight_accum[k] += weight;
}
}
}
}
@ -211,7 +230,7 @@ void main() {
for (uint k = 0; k < 6; k++) {
if (weight_accum[k] > 0.0) {
light_accum[k] /= weight_accum[k];
light_accum[k] *= albedo;
light_accum[k] *= feedback;
}
}
}

View File

@ -134,7 +134,7 @@ public:
virtual void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) = 0;
virtual void environment_set_sdfgi(RID p_env, bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, bool p_use_multibounce, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) = 0;
virtual void environment_set_sdfgi(RID p_env, bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) = 0;
virtual void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) = 0;
virtual void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) = 0;

View File

@ -996,7 +996,7 @@ public:
PASS2(environment_set_volumetric_fog_volume_size, int, int)
PASS1(environment_set_volumetric_fog_filter_active, bool)
PASS11(environment_set_sdfgi, RID, bool, RS::EnvironmentSDFGICascades, float, RS::EnvironmentSDFGIYScale, bool, bool, bool, float, float, float)
PASS11(environment_set_sdfgi, RID, bool, RS::EnvironmentSDFGICascades, float, RS::EnvironmentSDFGIYScale, bool, float, bool, float, float, float)
PASS1(environment_set_sdfgi_ray_count, RS::EnvironmentSDFGIRayCount)
PASS1(environment_set_sdfgi_frames_to_converge, RS::EnvironmentSDFGIFramesToConverge)
PASS1(environment_set_sdfgi_frames_to_update_light, RS::EnvironmentSDFGIFramesToUpdateLight)

View File

@ -128,7 +128,7 @@ public:
virtual void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) = 0;
virtual void environment_set_sdfgi(RID p_env, bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, bool p_use_multibounce, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) = 0;
virtual void environment_set_sdfgi(RID p_env, bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) = 0;
virtual void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) = 0;
virtual void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) = 0;

View File

@ -620,7 +620,7 @@ public:
BIND2(environment_set_volumetric_fog_volume_size, int, int)
BIND1(environment_set_volumetric_fog_filter_active, bool)
BIND11(environment_set_sdfgi, RID, bool, EnvironmentSDFGICascades, float, EnvironmentSDFGIYScale, bool, bool, bool, float, float, float)
BIND11(environment_set_sdfgi, RID, bool, EnvironmentSDFGICascades, float, EnvironmentSDFGIYScale, bool, float, bool, float, float, float)
BIND1(environment_set_sdfgi_ray_count, EnvironmentSDFGIRayCount)
BIND1(environment_set_sdfgi_frames_to_converge, EnvironmentSDFGIFramesToConverge)
BIND1(environment_set_sdfgi_frames_to_update_light, EnvironmentSDFGIFramesToUpdateLight)

View File

@ -505,7 +505,7 @@ public:
FUNC6(environment_set_ssao_quality, EnvironmentSSAOQuality, bool, float, int, float, float)
FUNC11(environment_set_sdfgi, RID, bool, EnvironmentSDFGICascades, float, EnvironmentSDFGIYScale, bool, bool, bool, float, float, float)
FUNC11(environment_set_sdfgi, RID, bool, EnvironmentSDFGICascades, float, EnvironmentSDFGIYScale, bool, float, bool, float, float, float)
FUNC1(environment_set_sdfgi_ray_count, EnvironmentSDFGIRayCount)
FUNC1(environment_set_sdfgi_frames_to_converge, EnvironmentSDFGIFramesToConverge)
FUNC1(environment_set_sdfgi_frames_to_update_light, EnvironmentSDFGIFramesToUpdateLight)

View File

@ -985,7 +985,7 @@ public:
ENV_SDFGI_Y_SCALE_50_PERCENT
};
virtual void environment_set_sdfgi(RID p_env, bool p_enable, EnvironmentSDFGICascades p_cascades, float p_min_cell_size, EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, bool p_use_multibounce, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) = 0;
virtual void environment_set_sdfgi(RID p_env, bool p_enable, EnvironmentSDFGICascades p_cascades, float p_min_cell_size, EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) = 0;
enum EnvironmentSDFGIRayCount {
ENV_SDFGI_RAY_COUNT_4,