diff options
author | William Leeson <leesonw> | 2022-01-13 19:20:50 +0300 |
---|---|---|
committer | Brecht Van Lommel <brecht@blender.org> | 2022-01-26 19:51:05 +0300 |
commit | ae440703411486c9219fa0ff54e471eea64afb58 (patch) | |
tree | 285443f953e6e89de24dad6ad5012ed2d488e182 /intern/cycles/kernel/integrator | |
parent | a9bb4607660a2f68a78732fd7f5d5280d8075dcb (diff) |
Cycles: explicitly skip self-intersection
Remember the last intersected primitive and skip any intersections with the
same primitive.
Ref D12954
Diffstat (limited to 'intern/cycles/kernel/integrator')
10 files changed, 61 insertions, 5 deletions
diff --git a/intern/cycles/kernel/integrator/intersect_closest.h b/intern/cycles/kernel/integrator/intersect_closest.h index df710dc1d82..4c5265189fa 100644 --- a/intern/cycles/kernel/integrator/intersect_closest.h +++ b/intern/cycles/kernel/integrator/intersect_closest.h @@ -328,6 +328,12 @@ ccl_device void integrator_intersect_closest(KernelGlobals kg, /* Scene Intersection. */ Intersection isect ccl_optional_struct_init; + isect.object = OBJECT_NONE; + isect.prim = PRIM_NONE; + ray.self.object = last_isect_object; + ray.self.prim = last_isect_prim; + ray.self.light_object = OBJECT_NONE; + ray.self.light_prim = PRIM_NONE; bool hit = scene_intersect(kg, &ray, visibility, &isect); /* TODO: remove this and do it in the various intersection functions instead. */ diff --git a/intern/cycles/kernel/integrator/intersect_shadow.h b/intern/cycles/kernel/integrator/intersect_shadow.h index 90422445fad..1ba8724826b 100644 --- a/intern/cycles/kernel/integrator/intersect_shadow.h +++ b/intern/cycles/kernel/integrator/intersect_shadow.h @@ -156,7 +156,10 @@ ccl_device void integrator_intersect_shadow(KernelGlobals kg, IntegratorShadowSt /* Read ray from integrator state into local memory. */ Ray ray ccl_optional_struct_init; integrator_state_read_shadow_ray(kg, state, &ray); - + ray.self.object = INTEGRATOR_STATE_ARRAY(state, shadow_isect, 0, object); + ray.self.prim = INTEGRATOR_STATE_ARRAY(state, shadow_isect, 0, prim); + ray.self.light_object = INTEGRATOR_STATE_ARRAY(state, shadow_isect, 1, object); + ray.self.light_prim = INTEGRATOR_STATE_ARRAY(state, shadow_isect, 1, prim); /* Compute visibility. */ const uint visibility = integrate_intersect_shadow_visibility(kg, state); diff --git a/intern/cycles/kernel/integrator/intersect_volume_stack.h b/intern/cycles/kernel/integrator/intersect_volume_stack.h index 9fa5ff63ad2..aa7be879995 100644 --- a/intern/cycles/kernel/integrator/intersect_volume_stack.h +++ b/intern/cycles/kernel/integrator/intersect_volume_stack.h @@ -38,7 +38,10 @@ ccl_device void integrator_volume_stack_update_for_subsurface(KernelGlobals kg, Ray volume_ray ccl_optional_struct_init; volume_ray.P = from_P; volume_ray.D = normalize_len(to_P - from_P, &volume_ray.t); - + volume_ray.self.object = INTEGRATOR_STATE(state, isect, object); + volume_ray.self.prim = INTEGRATOR_STATE(state, isect, prim); + volume_ray.self.light_object = OBJECT_NONE; + volume_ray.self.light_prim = PRIM_NONE; /* Store to avoid global fetches on every intersection step. */ const uint volume_stack_size = kernel_data.volume_stack_size; @@ -91,6 +94,10 @@ ccl_device void integrator_volume_stack_init(KernelGlobals kg, IntegratorState s * fewest hits. */ volume_ray.D = make_float3(0.0f, 0.0f, 1.0f); volume_ray.t = FLT_MAX; + volume_ray.self.object = OBJECT_NONE; + volume_ray.self.prim = PRIM_NONE; + volume_ray.self.light_object = OBJECT_NONE; + volume_ray.self.light_prim = PRIM_NONE; int stack_index = 0, enclosed_index = 0; diff --git a/intern/cycles/kernel/integrator/shade_shadow.h b/intern/cycles/kernel/integrator/shade_shadow.h index a68fcaa7a64..10ec48c8637 100644 --- a/intern/cycles/kernel/integrator/shade_shadow.h +++ b/intern/cycles/kernel/integrator/shade_shadow.h @@ -83,7 +83,10 @@ ccl_device_inline void integrate_transparent_volume_shadow(KernelGlobals kg, /* Setup shader data. */ Ray ray ccl_optional_struct_init; integrator_state_read_shadow_ray(kg, state, &ray); - + ray.self.object = OBJECT_NONE; + ray.self.prim = PRIM_NONE; + ray.self.light_object = OBJECT_NONE; + ray.self.light_prim = PRIM_NONE; /* Modify ray position and length to match current segment. */ const float start_t = (hit == 0) ? 0.0f : INTEGRATOR_STATE_ARRAY(state, shadow_isect, hit - 1, t); diff --git a/intern/cycles/kernel/integrator/shade_surface.h b/intern/cycles/kernel/integrator/shade_surface.h index 9f6077e5d66..3ca9e773591 100644 --- a/intern/cycles/kernel/integrator/shade_surface.h +++ b/intern/cycles/kernel/integrator/shade_surface.h @@ -182,6 +182,11 @@ ccl_device_forceinline void integrate_surface_direct_light(KernelGlobals kg, /* Write shadow ray and associated state to global memory. */ integrator_state_write_shadow_ray(kg, shadow_state, &ray); + // Save memory by storing the light and object indices in the shadow_isect + INTEGRATOR_STATE_ARRAY_WRITE(shadow_state, shadow_isect, 0, object) = ray.self.object; + INTEGRATOR_STATE_ARRAY_WRITE(shadow_state, shadow_isect, 0, prim) = ray.self.prim; + INTEGRATOR_STATE_ARRAY_WRITE(shadow_state, shadow_isect, 1, object) = ray.self.light_object; + INTEGRATOR_STATE_ARRAY_WRITE(shadow_state, shadow_isect, 1, prim) = ray.self.light_prim; /* Copy state from main path to shadow path. */ const uint16_t bounce = INTEGRATOR_STATE(state, path, bounce); @@ -364,6 +369,10 @@ ccl_device_forceinline void integrate_surface_ao(KernelGlobals kg, 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.light_object = OBJECT_NONE; + ray.self.light_prim = PRIM_NONE; ray.dP = differential_zero_compact(); ray.dD = differential_zero_compact(); @@ -375,6 +384,10 @@ ccl_device_forceinline void integrate_surface_ao(KernelGlobals kg, /* Write shadow ray and associated state to global memory. */ integrator_state_write_shadow_ray(kg, shadow_state, &ray); + INTEGRATOR_STATE_ARRAY_WRITE(shadow_state, shadow_isect, 0, object) = ray.self.object; + INTEGRATOR_STATE_ARRAY_WRITE(shadow_state, shadow_isect, 0, prim) = ray.self.prim; + INTEGRATOR_STATE_ARRAY_WRITE(shadow_state, shadow_isect, 1, object) = ray.self.light_object; + INTEGRATOR_STATE_ARRAY_WRITE(shadow_state, shadow_isect, 1, prim) = ray.self.light_prim; /* Copy state from main path to shadow path. */ const uint16_t bounce = INTEGRATOR_STATE(state, path, bounce); diff --git a/intern/cycles/kernel/integrator/shade_volume.h b/intern/cycles/kernel/integrator/shade_volume.h index 00fa256d894..107d5ec1795 100644 --- a/intern/cycles/kernel/integrator/shade_volume.h +++ b/intern/cycles/kernel/integrator/shade_volume.h @@ -791,6 +791,10 @@ ccl_device_forceinline void integrate_volume_direct_light( /* Write shadow ray and associated state to global memory. */ integrator_state_write_shadow_ray(kg, shadow_state, &ray); + INTEGRATOR_STATE_ARRAY_WRITE(shadow_state, shadow_isect, 0, object) = ray.self.object; + INTEGRATOR_STATE_ARRAY_WRITE(shadow_state, shadow_isect, 0, prim) = ray.self.prim; + INTEGRATOR_STATE_ARRAY_WRITE(shadow_state, shadow_isect, 1, object) = ray.self.light_object; + INTEGRATOR_STATE_ARRAY_WRITE(shadow_state, shadow_isect, 1, prim) = ray.self.light_prim; /* Copy state from main path to shadow path. */ const uint16_t bounce = INTEGRATOR_STATE(state, path, bounce); @@ -878,6 +882,9 @@ ccl_device_forceinline bool integrate_volume_phase_scatter( INTEGRATOR_STATE_WRITE(state, ray, dP) = differential_make_compact(sd->dP); INTEGRATOR_STATE_WRITE(state, ray, dD) = differential_make_compact(phase_domega_in); # endif + // Save memory by storing last hit prim and object in isect + INTEGRATOR_STATE_WRITE(state, isect, prim) = sd->prim; + INTEGRATOR_STATE_WRITE(state, isect, object) = sd->object; /* Update throughput. */ const float3 throughput = INTEGRATOR_STATE(state, path, throughput); diff --git a/intern/cycles/kernel/integrator/shadow_state_template.h b/intern/cycles/kernel/integrator/shadow_state_template.h index 625a429d3db..86fcabdcd82 100644 --- a/intern/cycles/kernel/integrator/shadow_state_template.h +++ b/intern/cycles/kernel/integrator/shadow_state_template.h @@ -61,6 +61,7 @@ KERNEL_STRUCT_MEMBER(shadow_ray, packed_float3, D, KERNEL_FEATURE_PATH_TRACING) KERNEL_STRUCT_MEMBER(shadow_ray, float, t, KERNEL_FEATURE_PATH_TRACING) KERNEL_STRUCT_MEMBER(shadow_ray, float, time, KERNEL_FEATURE_PATH_TRACING) KERNEL_STRUCT_MEMBER(shadow_ray, float, dP, KERNEL_FEATURE_PATH_TRACING) +KERNEL_STRUCT_MEMBER(shadow_ray, int, object, KERNEL_FEATURE_PATH_TRACING) KERNEL_STRUCT_END(shadow_ray) /*********************** Shadow Intersection result **************************/ diff --git a/intern/cycles/kernel/integrator/subsurface.h b/intern/cycles/kernel/integrator/subsurface.h index 59b0cd2596c..5a09fc51d75 100644 --- a/intern/cycles/kernel/integrator/subsurface.h +++ b/intern/cycles/kernel/integrator/subsurface.h @@ -57,7 +57,6 @@ ccl_device int subsurface_bounce(KernelGlobals kg, /* Pass along object info, reusing isect to save memory. */ INTEGRATOR_STATE_WRITE(state, subsurface, Ng) = sd->Ng; - INTEGRATOR_STATE_WRITE(state, isect, object) = sd->object; uint32_t path_flag = (INTEGRATOR_STATE(state, path, flag) & ~PATH_RAY_CAMERA) | ((sc->type == CLOSURE_BSSRDF_BURLEY_ID) ? PATH_RAY_SUBSURFACE_DISK : diff --git a/intern/cycles/kernel/integrator/subsurface_disk.h b/intern/cycles/kernel/integrator/subsurface_disk.h index cc6f5048cda..f5641d1fa5e 100644 --- a/intern/cycles/kernel/integrator/subsurface_disk.h +++ b/intern/cycles/kernel/integrator/subsurface_disk.h @@ -99,6 +99,10 @@ ccl_device_inline bool subsurface_disk(KernelGlobals kg, ray.dP = ray_dP; ray.dD = differential_zero_compact(); ray.time = time; + ray.self.object = OBJECT_NONE; + ray.self.prim = PRIM_NONE; + ray.self.light_object = OBJECT_NONE; + ray.self.light_prim = OBJECT_NONE; /* Intersect with the same object. if multiple intersections are found it * will use at most BSSRDF_MAX_HITS hits, a random subset of all hits. */ diff --git a/intern/cycles/kernel/integrator/subsurface_random_walk.h b/intern/cycles/kernel/integrator/subsurface_random_walk.h index 7a8b467e199..43676fccfe5 100644 --- a/intern/cycles/kernel/integrator/subsurface_random_walk.h +++ b/intern/cycles/kernel/integrator/subsurface_random_walk.h @@ -195,6 +195,7 @@ ccl_device_inline bool subsurface_random_walk(KernelGlobals kg, const float time = INTEGRATOR_STATE(state, ray, time); const float3 Ng = INTEGRATOR_STATE(state, subsurface, Ng); const int object = INTEGRATOR_STATE(state, isect, object); + const int prim = INTEGRATOR_STATE(state, isect, prim); /* Sample diffuse surface scatter into the object. */ float3 D; @@ -211,6 +212,10 @@ ccl_device_inline bool subsurface_random_walk(KernelGlobals kg, ray.time = time; ray.dP = ray_dP; ray.dD = differential_zero_compact(); + ray.self.object = object; + ray.self.prim = prim; + ray.self.light_object = OBJECT_NONE; + ray.self.light_prim = PRIM_NONE; #ifndef __KERNEL_GPU_RAYTRACING__ /* Compute or fetch object transforms. */ @@ -377,7 +382,15 @@ ccl_device_inline bool subsurface_random_walk(KernelGlobals kg, * If yes, we will later use backwards guided sampling in order to have a decent * chance of connecting to it. * TODO: Maybe use less than 10 times the mean free path? */ - ray.t = (bounce == 0) ? max(t, 10.0f / (min3(sigma_t))) : t; + if (bounce == 0) { + ray.t = max(t, 10.0f / (min3(sigma_t))); + } + else { + ray.t = t; + /* After the first bounce the object can intersect the same surface again */ + ray.self.object = OBJECT_NONE; + ray.self.prim = PRIM_NONE; + } scene_intersect_local(kg, &ray, &ss_isect, object, NULL, 1); hit = (ss_isect.num_hits > 0); |