|
@@ -46,7 +46,7 @@ layout(set = 1, binding = 2) uniform texture2D environment;
|
|
#ifdef MODE_UNOCCLUDE
|
|
#ifdef MODE_UNOCCLUDE
|
|
|
|
|
|
layout(rgba32f, set = 1, binding = 0) uniform restrict image2DArray position;
|
|
layout(rgba32f, set = 1, binding = 0) uniform restrict image2DArray position;
|
|
-layout(rgba32f, set = 1, binding = 1) uniform restrict readonly image2DArray unocclude;
|
|
|
|
|
|
+layout(rgba32f, set = 1, binding = 1) uniform restrict image2DArray unocclude;
|
|
|
|
|
|
#endif
|
|
#endif
|
|
|
|
|
|
@@ -73,7 +73,8 @@ layout(set = 1, binding = 1) uniform texture2DArray source_light;
|
|
|
|
|
|
#ifdef MODE_DENOISE
|
|
#ifdef MODE_DENOISE
|
|
layout(set = 1, binding = 2) uniform texture2DArray source_normal;
|
|
layout(set = 1, binding = 2) uniform texture2DArray source_normal;
|
|
-layout(set = 1, binding = 3) uniform DenoiseParams {
|
|
|
|
|
|
+layout(set = 1, binding = 3) uniform texture2DArray unocclude_mask;
|
|
|
|
+layout(set = 1, binding = 4) uniform DenoiseParams {
|
|
float spatial_bandwidth;
|
|
float spatial_bandwidth;
|
|
float light_bandwidth;
|
|
float light_bandwidth;
|
|
float albedo_bandwidth;
|
|
float albedo_bandwidth;
|
|
@@ -93,6 +94,7 @@ layout(push_constant, std430) uniform Params {
|
|
|
|
|
|
ivec2 region_ofs;
|
|
ivec2 region_ofs;
|
|
uint probe_count;
|
|
uint probe_count;
|
|
|
|
+ uint denoiser_range;
|
|
}
|
|
}
|
|
params;
|
|
params;
|
|
|
|
|
|
@@ -1011,13 +1013,16 @@ void main() {
|
|
|
|
|
|
vec3 rays[4] = vec3[](tangent, bitangent, -tangent, -bitangent);
|
|
vec3 rays[4] = vec3[](tangent, bitangent, -tangent, -bitangent);
|
|
float min_d = 1e20;
|
|
float min_d = 1e20;
|
|
|
|
+ float unocclude_mask = 0.0;
|
|
|
|
+
|
|
for (int i = 0; i < 4; i++) {
|
|
for (int i = 0; i < 4; i++) {
|
|
- vec3 ray_to = base_pos + rays[i] * texel_size;
|
|
|
|
|
|
+ vec3 ray_to = base_pos + rays[i] * texel_size * params.denoiser_range;
|
|
float d;
|
|
float d;
|
|
vec3 norm;
|
|
vec3 norm;
|
|
|
|
|
|
if (trace_ray_closest_hit_distance(base_pos, ray_to, d, norm) == RAY_BACK) {
|
|
if (trace_ray_closest_hit_distance(base_pos, ray_to, d, norm) == RAY_BACK) {
|
|
- if (d < min_d) {
|
|
|
|
|
|
+ unocclude_mask = 1.0;
|
|
|
|
+ if (d <= texel_size && d < min_d) {
|
|
// This bias needs to be greater than the regular bias, because otherwise later, rays will go the other side when pointing back.
|
|
// This bias needs to be greater than the regular bias, because otherwise later, rays will go the other side when pointing back.
|
|
vertex_pos = base_pos + rays[i] * d + norm * bake_params.bias * 10.0;
|
|
vertex_pos = base_pos + rays[i] * d + norm * bake_params.bias * 10.0;
|
|
min_d = d;
|
|
min_d = d;
|
|
@@ -1028,6 +1033,7 @@ void main() {
|
|
position_alpha.xyz = vertex_pos;
|
|
position_alpha.xyz = vertex_pos;
|
|
|
|
|
|
imageStore(position, ivec3(atlas_pos, params.atlas_slice), position_alpha);
|
|
imageStore(position, ivec3(atlas_pos, params.atlas_slice), position_alpha);
|
|
|
|
+ imageStore(unocclude, ivec3(atlas_pos, params.atlas_slice), vec4(unocclude_mask, 0, 0, 0));
|
|
|
|
|
|
#endif
|
|
#endif
|
|
|
|
|
|
@@ -1211,6 +1217,7 @@ void main() {
|
|
vec3 search_rgb = texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(search_pos, lightmap_slice), 0).rgb;
|
|
vec3 search_rgb = texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(search_pos, lightmap_slice), 0).rgb;
|
|
vec3 search_albedo = texelFetch(sampler2DArray(albedo_tex, linear_sampler), ivec3(search_pos, params.atlas_slice), 0).rgb;
|
|
vec3 search_albedo = texelFetch(sampler2DArray(albedo_tex, linear_sampler), ivec3(search_pos, params.atlas_slice), 0).rgb;
|
|
vec3 search_normal = texelFetch(sampler2DArray(source_normal, linear_sampler), ivec3(search_pos, params.atlas_slice), 0).xyz;
|
|
vec3 search_normal = texelFetch(sampler2DArray(source_normal, linear_sampler), ivec3(search_pos, params.atlas_slice), 0).xyz;
|
|
|
|
+ float search_occlusion = texelFetch(sampler2DArray(unocclude_mask, linear_sampler), ivec3(search_pos, params.atlas_slice), 0).r;
|
|
float patch_square_dist = 0.0f;
|
|
float patch_square_dist = 0.0f;
|
|
for (int offset_y = -HALF_PATCH_WINDOW; offset_y <= HALF_PATCH_WINDOW; offset_y++) {
|
|
for (int offset_y = -HALF_PATCH_WINDOW; offset_y <= HALF_PATCH_WINDOW; offset_y++) {
|
|
for (int offset_x = -HALF_PATCH_WINDOW; offset_x <= HALF_PATCH_WINDOW; offset_x++) {
|
|
for (int offset_x = -HALF_PATCH_WINDOW; offset_x <= HALF_PATCH_WINDOW; offset_x++) {
|
|
@@ -1252,12 +1259,16 @@ void main() {
|
|
float normal_square_dist = dot(normal_delta, normal_delta);
|
|
float normal_square_dist = dot(normal_delta, normal_delta);
|
|
weight *= exp(-normal_square_dist / TWO_SIGMA_NORMAL_SQUARE);
|
|
weight *= exp(-normal_square_dist / TWO_SIGMA_NORMAL_SQUARE);
|
|
|
|
|
|
|
|
+ // Weight with occlusion.
|
|
|
|
+ weight *= 1.0 - search_occlusion;
|
|
|
|
+
|
|
denoised_rgb += weight * search_rgb;
|
|
denoised_rgb += weight * search_rgb;
|
|
sum_weights += weight;
|
|
sum_weights += weight;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- denoised_rgb /= sum_weights;
|
|
|
|
|
|
+ // Avoid division by zero if no weights were accumulated.
|
|
|
|
+ denoised_rgb = sum_weights > EPSILON ? denoised_rgb / sum_weights : input_rgb;
|
|
} else {
|
|
} else {
|
|
// Ignore pixels where the normal is empty, just copy the light color.
|
|
// Ignore pixels where the normal is empty, just copy the light color.
|
|
denoised_rgb = input_light.rgb;
|
|
denoised_rgb = input_light.rgb;
|