Blender V5.0
shadow_all.h
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2009-2010 NVIDIA Corporation
2 * SPDX-FileCopyrightText: 2009-2012 Intel Corporation
3 * SPDX-FileCopyrightText: 2011-2022 Blender Foundation
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Adapted code from NVIDIA Corporation. */
8
9#if BVH_FEATURE(BVH_HAIR)
10# define NODE_INTERSECT bvh_node_intersect
11#else
12# define NODE_INTERSECT bvh_aligned_node_intersect
13#endif
14
15/* This is a template BVH traversal function, where various features can be
16 * enabled/disabled. This way we can compile optimized versions for each case
17 * without new features slowing things down.
18 *
19 * BVH_HAIR: hair curve rendering
20 * BVH_POINTCLOUD: point cloud rendering
21 * BVH_MOTION: motion blur rendering
22 */
23
24#ifndef __KERNEL_GPU__
26#else
28#endif
29 bool
31 const ccl_private Ray *ray,
33 const uint visibility,
34 const uint max_transparent_hits,
35 ccl_private uint *r_num_recorded_hits,
36 ccl_private float *r_throughput)
37{
38 /* todo:
39 * - likely and unlikely for if() statements
40 * - test restrict attribute for pointers
41 */
42
43 /* traversal stack in CUDA thread-local memory */
44 int traversal_stack[BVH_STACK_SIZE];
45 traversal_stack[0] = ENTRYPOINT_SENTINEL;
46
47 /* traversal variables in registers */
48 int stack_ptr = 0;
49 int node_addr = kernel_data.bvh.root;
50
51 /* ray parameters in registers */
52 float3 P = ray->P;
53 float3 dir = bvh_clamp_direction(ray->D);
54 float3 idir = bvh_inverse_direction(dir);
55 float tmin = ray->tmin;
56 int object = OBJECT_NONE;
57 uint num_transparent_hits = 0;
58
59 /* Max distance in world space. May be dynamically reduced when max number of
60 * recorded hits is exceeded and we no longer need to find hits beyond the max
61 * distance found. */
62 const float tmax = ray->tmax;
63 float tmax_hits = tmax;
64
65 uint isect_index = 0;
66
67 *r_num_recorded_hits = 0;
68 *r_throughput = 1.0f;
69
70 /* traversal loop */
71 do {
72 do {
73 /* traverse internal nodes */
74 while (node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) {
75 int node_addr_child1, traverse_mask;
76 float dist[2];
77 float4 cnodes = kernel_data_fetch(bvh_nodes, node_addr + 0);
78
79 traverse_mask = NODE_INTERSECT(kg,
80 P,
82 dir,
83#endif
84 idir,
85 tmin,
86 tmax,
87 node_addr,
88 visibility,
89 dist);
90
91 node_addr = __float_as_int(cnodes.z);
92 node_addr_child1 = __float_as_int(cnodes.w);
93
94 if (traverse_mask == 3) {
95 /* Both children were intersected, push the farther one. */
96 bool is_closest_child1 = (dist[1] < dist[0]);
97 if (is_closest_child1) {
98 int tmp = node_addr;
99 node_addr = node_addr_child1;
100 node_addr_child1 = tmp;
101 }
102
103 ++stack_ptr;
104 kernel_assert(stack_ptr < BVH_STACK_SIZE);
105 traversal_stack[stack_ptr] = node_addr_child1;
106 }
107 else {
108 /* One child was intersected. */
109 if (traverse_mask == 2) {
110 node_addr = node_addr_child1;
111 }
112 else if (traverse_mask == 0) {
113 /* Neither child was intersected. */
114 node_addr = traversal_stack[stack_ptr];
115 --stack_ptr;
116 }
117 }
118 }
119
120 /* if node is leaf, fetch triangle list */
121 if (node_addr < 0) {
122 float4 leaf = kernel_data_fetch(bvh_leaf_nodes, (-node_addr - 1));
123 int prim_addr = __float_as_int(leaf.x);
124
125 if (prim_addr >= 0) {
126 const int prim_addr2 = __float_as_int(leaf.y);
127 const uint type = __float_as_int(leaf.w);
128
129 /* pop */
130 node_addr = traversal_stack[stack_ptr];
131 --stack_ptr;
132
133 /* primitive intersection */
134 for (; prim_addr < prim_addr2; prim_addr++) {
135 kernel_assert((kernel_data_fetch(prim_type, prim_addr) & PRIMITIVE_ALL) ==
136 (type & PRIMITIVE_ALL));
137 bool hit;
138
139 /* todo: specialized intersect functions which don't fill in
140 * isect unless needed and check SD_HAS_TRANSPARENT_SHADOW?
141 * might give a few % performance improvement */
143
144 const int prim_object = (object == OBJECT_NONE) ?
145 kernel_data_fetch(prim_object, prim_addr) :
146 object;
147 const int prim = kernel_data_fetch(prim_index, prim_addr);
148 if (intersection_skip_self_shadow(ray->self, prim_object, prim)) {
149 continue;
150 }
151
152#ifdef __SHADOW_LINKING__
153 if (intersection_skip_shadow_link(kg, ray->self, prim_object)) {
154 continue;
155 }
156#endif
157
158 switch (type & PRIMITIVE_ALL) {
159 case PRIMITIVE_TRIANGLE: {
160 hit = triangle_intersect(
161 kg, &isect, P, dir, tmin, tmax, visibility, prim_object, prim, prim_addr);
162 break;
163 }
164#if BVH_FEATURE(BVH_MOTION)
167 &isect,
168 P,
169 dir,
170 tmin,
171 tmax,
172 ray->time,
173 visibility,
174 prim_object,
175 prim,
176 prim_addr);
177 break;
178 }
179#endif
180#if BVH_FEATURE(BVH_HAIR) && defined(__HAIR__)
187 if ((type & PRIMITIVE_MOTION) && kernel_data.bvh.use_bvh_steps) {
188 const float2 prim_time = kernel_data_fetch(prim_time, prim_addr);
189 if (ray->time < prim_time.x || ray->time > prim_time.y) {
190 hit = false;
191 break;
192 }
193 }
194
195 const int curve_type = kernel_data_fetch(prim_type, prim_addr);
196 hit = curve_intersect(
197 kg, &isect, P, dir, tmin, tmax, prim_object, prim, ray->time, curve_type);
198
199 break;
200 }
201#endif
202#if BVH_FEATURE(BVH_POINTCLOUD) && defined(__POINTCLOUD__)
203 case PRIMITIVE_POINT:
205 if ((type & PRIMITIVE_MOTION) && kernel_data.bvh.use_bvh_steps) {
206 const float2 prim_time = kernel_data_fetch(prim_time, prim_addr);
207 if (ray->time < prim_time.x || ray->time > prim_time.y) {
208 hit = false;
209 break;
210 }
211 }
212
213 const int point_type = kernel_data_fetch(prim_type, prim_addr);
214 hit = point_intersect(
215 kg, &isect, P, dir, tmin, tmax, prim_object, prim, ray->time, point_type);
216 break;
217 }
218#endif /* BVH_FEATURE(BVH_POINTCLOUD) */
219 default: {
220 hit = false;
221 break;
222 }
223 }
224
225 /* shadow ray early termination */
226 if (hit) {
227 /* Detect if this surface has a shader with transparent shadows. */
228 /* TODO: optimize so primitive visibility flag indicates if the primitive has a
229 * transparent shadow shader? */
230 const int flags = intersection_get_shader_flags(kg, isect.prim, isect.type);
231 if ((flags & SD_HAS_TRANSPARENT_SHADOW) == 0) {
232 /* If no transparent shadows, all light is blocked and we can stop immediately. */
233 return true;
234 }
235
236 /* If the intersection is already recoded ignore it completely: don't update
237 * throughput as it has been already updated. But also don't count it for num_hits
238 * as that could result in situation when the same ray will be considered transparent
239 * when spatial split is off, and be opaque when spatial split is on. */
241 state, isect.object, isect.prim, *r_num_recorded_hits))
242 {
243 continue;
244 }
245
246 /* Only count transparent bounces, volume bounds bounces are counted when shading. */
247 num_transparent_hits += !(flags & SD_HAS_ONLY_VOLUME);
248 if (num_transparent_hits > max_transparent_hits) {
249 return true;
250 }
251
252 bool record_intersection = true;
253
254 /* Always use baked shadow transparency for curves. */
255 if (isect.type & PRIMITIVE_CURVE) {
257 kg, isect.object, isect.prim, isect.type, isect.u);
258
259 if (*r_throughput < CURVE_SHADOW_TRANSPARENCY_CUTOFF) {
260 return true;
261 }
262 else {
263 record_intersection = false;
264 }
265 }
266
267 if (record_intersection) {
268 /* Test if we need to record this transparent intersection. */
269
270 /* Always increase the number of recorded hits, even beyond the maximum,
271 * so that we can detect this and trace another ray if needed. */
272 ++(*r_num_recorded_hits);
273
274 const uint max_record_hits = (uint)INTEGRATOR_SHADOW_ISECT_SIZE;
275 if (*r_num_recorded_hits <= max_record_hits || isect.t < tmax_hits) {
276 integrator_state_write_shadow_isect(state, &isect, isect_index);
277
278 if (*r_num_recorded_hits >= max_record_hits) {
279 /* If the maximum number of hits is reached, find the furthest intersection to
280 replace it with the next closer one. We want N closest intersections. */
281 isect_index = 0;
282 tmax_hits = INTEGRATOR_STATE_ARRAY(state, shadow_isect, 0, t);
283 for (uint i = 1; i < max_record_hits; ++i) {
284 const float isect_t = INTEGRATOR_STATE_ARRAY(state, shadow_isect, i, t);
285 if (isect_t > tmax_hits) {
286 isect_index = i;
287 tmax_hits = isect_t;
288 }
289 }
290 }
291 else {
292 isect_index = *r_num_recorded_hits;
293 }
294 }
295 }
296 }
297 }
298 }
299 else {
300 /* instance push */
301 object = kernel_data_fetch(prim_object, -prim_addr - 1);
302
303#if BVH_FEATURE(BVH_MOTION)
304 bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir);
305#else
306 bvh_instance_push(kg, object, ray, &P, &dir, &idir);
307#endif
308
309 ++stack_ptr;
310 kernel_assert(stack_ptr < BVH_STACK_SIZE);
311 traversal_stack[stack_ptr] = ENTRYPOINT_SENTINEL;
312
313 node_addr = kernel_data_fetch(object_node, object);
314 }
315 }
316 } while (node_addr != ENTRYPOINT_SENTINEL);
317
318 if (stack_ptr >= 0) {
319 kernel_assert(object != OBJECT_NONE);
320
321 /* Instance pop. */
322 bvh_instance_pop(ray, &P, &dir, &idir);
323
324 object = OBJECT_NONE;
325 node_addr = traversal_stack[stack_ptr];
326 --stack_ptr;
327 }
328 } while (node_addr != ENTRYPOINT_SENTINEL);
329
330 return false;
331}
332
334 const ccl_private Ray *ray,
336 const uint visibility,
337 const uint max_transparent_hits,
338 ccl_private uint *num_recorded_hits,
339 ccl_private float *throughput)
340{
342 kg, ray, state, visibility, max_transparent_hits, num_recorded_hits, throughput);
343}
344
345#undef BVH_FUNCTION_NAME
346#undef BVH_FUNCTION_FEATURES
347#undef NODE_INTERSECT
unsigned int uint
Definition bvh/bvh.h:67
ccl_device_forceinline int intersection_get_shader_flags(KernelGlobals kg, const int prim, const int type)
ccl_device_forceinline bool intersection_skip_shadow_already_recoded(IntegratorShadowState state, const int object, const int prim, const int num_hits)
ccl_device_inline bool intersection_skip_shadow_link(KernelGlobals kg, const ccl_ray_data RaySelfPrimitives &self, const int isect_object)
ccl_device_inline bool intersection_skip_self_shadow(const ccl_ray_data RaySelfPrimitives &self, const int object, const int prim)
#define CURVE_SHADOW_TRANSPARENCY_CUTOFF
ccl_device_inline float intersection_curve_shadow_transparency(KernelGlobals kg, const int object, const int prim, const int type, const float u)
#define kernel_assert(cond)
#define kernel_data
#define ccl_optional_struct_init
#define kernel_data_fetch(name, index)
#define INTEGRATOR_SHADOW_ISECT_SIZE
#define OBJECT_NONE
#define ccl_private
const ThreadKernelGlobalsCPU * KernelGlobals
#define ccl_device_inline
#define __float_as_int(x)
#define BVH_FUNCTION_NAME
#define BVH_STACK_SIZE
#define BVH_FEATURE(f)
#define ENTRYPOINT_SENTINEL
#define BVH_HAIR
#define BVH_FUNCTION_FULL_NAME(prefix)
ccl_device_inline void bvh_instance_push(KernelGlobals kg, const int object, const ccl_private Ray *ray, ccl_private float3 *P, ccl_private float3 *dir, ccl_private float3 *idir)
ccl_device_inline float3 bvh_inverse_direction(const float3 dir)
ccl_device_inline float3 bvh_clamp_direction(const float3 dir)
ccl_device_inline void bvh_instance_pop(const ccl_private Ray *ray, ccl_private float3 *P, ccl_private float3 *dir, ccl_private float3 *idir)
@ SD_HAS_TRANSPARENT_SHADOW
@ SD_HAS_ONLY_VOLUME
@ PRIMITIVE_MOTION_CURVE_RIBBON
@ PRIMITIVE_CURVE_THICK_LINEAR
@ PRIMITIVE_ALL
@ PRIMITIVE_MOTION
@ PRIMITIVE_MOTION_TRIANGLE
@ PRIMITIVE_CURVE_RIBBON
@ PRIMITIVE_MOTION_CURVE_THICK
@ PRIMITIVE_CURVE
@ PRIMITIVE_CURVE_THICK
@ PRIMITIVE_TRIANGLE
@ PRIMITIVE_MOTION_CURVE_THICK_LINEAR
@ PRIMITIVE_MOTION_POINT
@ PRIMITIVE_POINT
static ulong state[N]
ccl_device_inline bool motion_triangle_intersect(KernelGlobals kg, ccl_private Intersection *isect, const float3 P, const float3 dir, const float tmin, const float tmax, const float time, const uint visibility, const int object, const int prim, const int prim_addr)
#define ccl_device
#define NODE_INTERSECT
Definition shadow_all.h:12
IntegratorShadowStateCPU * IntegratorShadowState
Definition state.h:230
#define INTEGRATOR_STATE_ARRAY(state, nested_struct, array_index, member)
Definition state.h:238
ccl_device_forceinline void integrator_state_write_shadow_isect(IntegratorShadowState state, const ccl_private Intersection *ccl_restrict isect, const int index)
Definition state_util.h:284
float x
float y
float y
Definition sky_math.h:225
float z
Definition sky_math.h:225
float x
Definition sky_math.h:225
float w
Definition sky_math.h:225
i
Definition text_draw.cc:230
CCL_NAMESPACE_BEGIN ccl_device_inline bool triangle_intersect(KernelGlobals kg, ccl_private Intersection *isect, const float3 P, const float3 dir, const float tmin, const float tmax, const uint visibility, const int object, const int prim, const int prim_addr)