Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brecht@blender.org>2022-03-15 17:59:07 +0300
committerPhilipp Oeser <info@graphics-engineer.com>2022-03-21 15:24:38 +0300
commiteb605ba78808f2bba73267548f4949001391538e (patch)
tree93fd457612d47532445408f56c25acd600142721
parent233004789ea2bb199e604aa1bd6c2838d414ffa9 (diff)
Fix T96417: Cycles issue with multiscatter GGX and self intersection avoidance
When the light direction is not pointing away from the geometric normal and there is a shadow terminator offset, self intersection is supposed to occur.
-rw-r--r--intern/cycles/kernel/integrator/shade_surface.h8
-rw-r--r--intern/cycles/kernel/light/sample.h44
2 files changed, 30 insertions, 22 deletions
diff --git a/intern/cycles/kernel/integrator/shade_surface.h b/intern/cycles/kernel/integrator/shade_surface.h
index d3edfb0e05e..cc3f114b64b 100644
--- a/intern/cycles/kernel/integrator/shade_surface.h
+++ b/intern/cycles/kernel/integrator/shade_surface.h
@@ -365,13 +365,15 @@ ccl_device_forceinline void integrate_surface_ao(KernelGlobals kg,
float ao_pdf;
sample_cos_hemisphere(ao_N, bsdf_u, bsdf_v, &ao_D, &ao_pdf);
+ bool skip_self = true;
+
Ray ray ccl_optional_struct_init;
- ray.P = shadow_ray_offset(kg, sd, ao_D);
+ ray.P = shadow_ray_offset(kg, sd, ao_D, &skip_self);
ray.D = ao_D;
ray.t = kernel_data.integrator.ao_bounces_distance;
ray.time = sd->time;
- ray.self.object = sd->object;
- ray.self.prim = sd->prim;
+ ray.self.object = (skip_self) ? sd->object : OBJECT_NONE;
+ ray.self.prim = (skip_self) ? sd->prim : PRIM_NONE;
ray.self.light_object = OBJECT_NONE;
ray.self.light_prim = PRIM_NONE;
ray.dP = differential_zero_compact();
diff --git a/intern/cycles/kernel/light/sample.h b/intern/cycles/kernel/light/sample.h
index 521ad2f7066..4b2f7235c4b 100644
--- a/intern/cycles/kernel/light/sample.h
+++ b/intern/cycles/kernel/light/sample.h
@@ -193,11 +193,9 @@ ccl_device_inline float3 shadow_ray_smooth_surface_offset(
ccl_device_inline float3 shadow_ray_offset(KernelGlobals kg,
ccl_private const ShaderData *ccl_restrict sd,
- float3 L)
+ float3 L,
+ bool *r_skip_self)
{
- float NL = dot(sd->N, L);
- bool transmit = (NL < 0.0f);
- float3 Ng = (transmit ? -sd->Ng : sd->Ng);
float3 P = sd->P;
if ((sd->type & PRIMITIVE_TRIANGLE) && (sd->shader & SHADER_SMOOTH_NORMAL)) {
@@ -207,19 +205,25 @@ ccl_device_inline float3 shadow_ray_offset(KernelGlobals kg,
* offset_cutoff = 0.1f means that 10-20% of rays will be affected. Also
* make a smooth transition near the threshold. */
if (offset_cutoff > 0.0f) {
- float NgL = dot(Ng, L);
- float offset_amount = 0.0f;
+ float NL = dot(sd->N, L);
+ const bool transmit = (NL < 0.0f);
if (NL < 0) {
NL = -NL;
}
- if (NL < offset_cutoff) {
- offset_amount = clamp(2.0f - (NgL + NL) / offset_cutoff, 0.0f, 1.0f);
- }
- else {
- offset_amount = clamp(1.0f - NgL / offset_cutoff, 0.0f, 1.0f);
- }
+
+ const float3 Ng = (transmit ? -sd->Ng : sd->Ng);
+ const float NgL = dot(Ng, L);
+
+ const float offset_amount = (NL < offset_cutoff) ?
+ clamp(2.0f - (NgL + NL) / offset_cutoff, 0.0f, 1.0f) :
+ clamp(1.0f - NgL / offset_cutoff, 0.0f, 1.0f);
+
if (offset_amount > 0.0f) {
P += shadow_ray_smooth_surface_offset(kg, sd, Ng) * offset_amount;
+
+ /* Only skip self intersections if light direction and geometric normal point in the same
+ * direction, otherwise we're meant to hit this surface. */
+ *r_skip_self = (NgL > 0.0f);
}
}
}
@@ -230,7 +234,8 @@ ccl_device_inline float3 shadow_ray_offset(KernelGlobals kg,
ccl_device_inline void shadow_ray_setup(ccl_private const ShaderData *ccl_restrict sd,
ccl_private const LightSample *ccl_restrict ls,
const float3 P,
- ccl_private Ray *ray)
+ ccl_private Ray *ray,
+ const bool skip_self)
{
if (ls->shader & SHADER_CAST_SHADOW) {
/* setup ray */
@@ -259,10 +264,10 @@ ccl_device_inline void shadow_ray_setup(ccl_private const ShaderData *ccl_restri
ray->time = sd->time;
/* Fill in intersection surface and light details. */
- ray->self.prim = sd->prim;
- ray->self.object = sd->object;
- ray->self.light_prim = ls->prim;
+ ray->self.object = (skip_self) ? sd->object : OBJECT_NONE;
+ ray->self.prim = (skip_self) ? sd->prim : PRIM_NONE;
ray->self.light_object = ls->object;
+ ray->self.light_prim = ls->prim;
}
/* Create shadow ray towards light sample. */
@@ -272,8 +277,9 @@ ccl_device_inline void light_sample_to_surface_shadow_ray(
ccl_private const LightSample *ccl_restrict ls,
ccl_private Ray *ray)
{
- const float3 P = shadow_ray_offset(kg, sd, ls->D);
- shadow_ray_setup(sd, ls, P, ray);
+ bool skip_self = true;
+ const float3 P = shadow_ray_offset(kg, sd, ls->D, &skip_self);
+ shadow_ray_setup(sd, ls, P, ray, skip_self);
}
/* Create shadow ray towards light sample. */
@@ -284,7 +290,7 @@ ccl_device_inline void light_sample_to_volume_shadow_ray(
const float3 P,
ccl_private Ray *ray)
{
- shadow_ray_setup(sd, ls, P, ray);
+ shadow_ray_setup(sd, ls, P, ray, false);
}
ccl_device_inline float light_sample_mis_weight_forward(KernelGlobals kg,