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:
authorSergey Sharybin <sergey@blender.org>2022-03-08 16:43:48 +0300
committerSergey Sharybin <sergey@blender.org>2022-03-09 12:37:19 +0300
commit04e89c5b06739a9a507942e2a9c67fb59b975600 (patch)
tree97e5723d9616f364b706b8d7e8353d9d190e8255 /intern/cycles/kernel/bvh
parent801d7b4921dce55d1fb0d2989935408db1e1691e (diff)
Fix T96165: Incorrect render of barcelone scene with BVH2
Fix T95462: Partly transparent objects appear to glow in the dark The issue was caused by incorrect check for exceeded number of transparent bounces: the same maximum distance was used for picking up N closest intersections and counting overall intersections count. Now made it so intersection count is using ray distance which matches the way how Embree and OptiX implementation works. Benchmark result: {F12907888} There is no big time difference in the pabellon scene. The Victor scene timing doesn't seem to be very reliable as the variance in time across different benchmark runs is quite high. Differential Revision: https://developer.blender.org/D14280
Diffstat (limited to 'intern/cycles/kernel/bvh')
-rw-r--r--intern/cycles/kernel/bvh/shadow_all.h73
1 files changed, 39 insertions, 34 deletions
diff --git a/intern/cycles/kernel/bvh/shadow_all.h b/intern/cycles/kernel/bvh/shadow_all.h
index a5769e91a28..2f58929c1e5 100644
--- a/intern/cycles/kernel/bvh/shadow_all.h
+++ b/intern/cycles/kernel/bvh/shadow_all.h
@@ -29,8 +29,8 @@ ccl_device_inline
IntegratorShadowState state,
const uint visibility,
const uint max_hits,
- ccl_private uint *num_recorded_hits,
- ccl_private float *throughput)
+ ccl_private uint *r_num_recorded_hits,
+ ccl_private float *r_throughput)
{
/* todo:
* - likely and unlikely for if() statements
@@ -60,15 +60,18 @@ ccl_device_inline
* recorded hits is exceeded and we no longer need to find hits beyond the max
* distance found. */
float t_max_world = ray->t;
- /* Equal to t_max_world when traversing top level BVH, transformed into local
- * space when entering instances. */
- float t_max_current = t_max_world;
+
+ /* Current maximum distance to the intersection.
+ * Is calculated as a ray length, transformed to an object space when entering
+ * instance node. */
+ float t_max_current = ray->t;
+
/* Conversion from world to local space for the current instance if any, 1.0
* otherwise. */
float t_world_to_instance = 1.0f;
- *num_recorded_hits = 0;
- *throughput = 1.0f;
+ *r_num_recorded_hits = 0;
+ *r_throughput = 1.0f;
/* traversal loop */
do {
@@ -237,10 +240,10 @@ ccl_device_inline
/* Always use baked shadow transparency for curves. */
if (isect.type & PRIMITIVE_CURVE) {
- *throughput *= intersection_curve_shadow_transparency(
+ *r_throughput *= intersection_curve_shadow_transparency(
kg, isect.object, isect.prim, isect.u);
- if (*throughput < CURVE_SHADOW_TRANSPARENCY_CUTOFF) {
+ if (*r_throughput < CURVE_SHADOW_TRANSPARENCY_CUTOFF) {
return true;
}
else {
@@ -249,37 +252,39 @@ ccl_device_inline
}
if (record_intersection) {
- /* Increase the number of hits, possibly beyond max_hits, we will
- * simply not record those and only keep the max_hits closest. */
- uint record_index = (*num_recorded_hits)++;
-
+ /* Test if we need to record this transparent intersection. */
const uint max_record_hits = min(max_hits, INTEGRATOR_SHADOW_ISECT_SIZE);
- if (record_index >= max_record_hits - 1) {
- /* If maximum number of hits reached, find the intersection with
- * the largest distance to potentially replace when another hit
- * is found. */
- const int num_recorded_hits = min(max_record_hits, record_index);
- float max_recorded_t = INTEGRATOR_STATE_ARRAY(state, shadow_isect, 0, t);
- int max_recorded_hit = 0;
-
- for (int i = 1; i < num_recorded_hits; i++) {
- const float isect_t = INTEGRATOR_STATE_ARRAY(state, shadow_isect, i, t);
- if (isect_t > max_recorded_t) {
- max_recorded_t = isect_t;
- max_recorded_hit = i;
+ if (*r_num_recorded_hits < max_record_hits || isect.t < t_max_world) {
+ /* If maximum number of hits was reached, replace the intersection with the
+ * highest distance. We want to find the N closest intersections. */
+ const uint num_recorded_hits = min(*r_num_recorded_hits, max_record_hits);
+ uint isect_index = num_recorded_hits;
+ if (num_recorded_hits + 1 >= max_record_hits) {
+ float max_t = INTEGRATOR_STATE_ARRAY(state, shadow_isect, 0, t);
+ uint max_recorded_hit = 0;
+
+ for (uint i = 1; i < num_recorded_hits; ++i) {
+ const float isect_t = INTEGRATOR_STATE_ARRAY(state, shadow_isect, i, t);
+ if (isect_t > max_t) {
+ max_recorded_hit = i;
+ max_t = isect_t;
+ }
+ }
+
+ if (num_recorded_hits >= max_record_hits) {
+ isect_index = max_recorded_hit;
}
- }
- if (record_index >= max_record_hits) {
- record_index = max_recorded_hit;
+ /* Limit the ray distance and stop counting hits beyond this. */
+ t_max_world = max(isect.t, max_t);
}
- /* Limit the ray distance and stop counting hits beyond this. */
- t_max_world = max(max_recorded_t, isect.t);
- t_max_current = t_max_world * t_world_to_instance;
+ integrator_state_write_shadow_isect(state, &isect, isect_index);
}
- integrator_state_write_shadow_isect(state, &isect, record_index);
+ /* Always increase the number of recorded hits, even beyond the maximum,
+ * so that we can detect this and trace another ray if needed. */
+ ++(*r_num_recorded_hits);
}
}
}
@@ -318,7 +323,7 @@ ccl_device_inline
#endif
/* Restore world space ray length. */
- t_max_current = t_max_world;
+ t_max_current = ray->t;
object = OBJECT_NONE;
t_world_to_instance = 1.0f;