Blender V4.3
cycles/kernel/bvh/util.h
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#pragma once
6
8
10{
11 /* NOTE: Due to some vectorization code non-finite origin point might
12 * cause lots of false-positive intersections which will overflow traversal
13 * stack.
14 * This code is a quick way to perform early output, to avoid crashes in
15 * such cases.
16 * From production scenes so far it seems it's enough to test first element
17 * only.
18 * Scene intersection may also called with empty rays for conditional trace
19 * calls that evaluate to false, so filter those out.
20 */
21 return isfinite_safe(ray->P.x) && isfinite_safe(ray->D.x) && len_squared(ray->D) != 0.0f;
22}
23
24/* Offset intersection distance by the smallest possible amount, to skip
25 * intersections at this distance. This works in cases where the ray start
26 * position is unchanged and only tmin is updated, since for self
27 * intersection we'll be comparing against the exact same distances.
28 *
29 * Always returns normalized floating point value. */
31{
32 /* This is a simplified version of `nextafterf(t, FLT_MAX)`, only dealing with
33 * non-negative and finite t. */
34 kernel_assert(t >= 0.0f && isfinite_safe(t));
35
36 /* Special handling of zero, which also includes handling of denormal values:
37 * always return smallest normalized value. If a denormalized zero is returned
38 * it will cause false-positive intersection detection with a distance of 0.
39 *
40 * The check relies on the fact that comparison of denormal values with zero
41 * returns true. */
42 if (t == 0.0f) {
43 /* The exact bit value of this should be 0x1p-126, but hex floating point values notation is
44 * not available in CUDA/OptiX. */
45 return FLT_MIN;
46 }
47
48 const uint32_t bits = __float_as_uint(t) + 1;
49 const float result = __uint_as_float(bits);
50
51 /* Assert that the calculated value is indeed considered to be offset from the
52 * original value. */
53 kernel_assert(result > t);
54
55 return result;
56}
57
58/* Ray offset to avoid self intersection.
59 *
60 * This function can be used to compute a modified ray start position for rays
61 * leaving from a surface. This is from:
62 * "A Fast and Robust Method for Avoiding Self-Intersection"
63 * Ray Tracing Gems, chapter 6.
64 */
66{
67 const float int_scale = 256.0f;
68 const int3 of_i = make_int3(
69 (int)(int_scale * Ng.x), (int)(int_scale * Ng.y), (int)(int_scale * Ng.z));
70
71 const float3 p_i = make_float3(
72 __int_as_float(__float_as_int(P.x) + ((P.x < 0) ? -of_i.x : of_i.x)),
73 __int_as_float(__float_as_int(P.y) + ((P.y < 0) ? -of_i.y : of_i.y)),
74 __int_as_float(__float_as_int(P.z) + ((P.z < 0) ? -of_i.z : of_i.z)));
75 const float origin = 1.0f / 32.0f;
76 const float float_scale = 1.0f / 65536.0f;
77 return make_float3(fabsf(P.x) < origin ? P.x + float_scale * Ng.x : p_i.x,
78 fabsf(P.y) < origin ? P.y + float_scale * Ng.y : p_i.y,
79 fabsf(P.z) < origin ? P.z + float_scale * Ng.z : p_i.z);
80}
81
82#ifndef __KERNEL_GPU__
83ccl_device int intersections_compare(const void *a, const void *b)
84{
85 const Intersection *isect_a = (const Intersection *)a;
86 const Intersection *isect_b = (const Intersection *)b;
87
88 if (isect_a->t < isect_b->t)
89 return -1;
90 else if (isect_a->t > isect_b->t)
91 return 1;
92 else
93 return 0;
94}
95#endif
96
97/* For subsurface scattering, only sorting a small amount of intersections
98 * so bubble sort is fine for CPU and GPU. */
101 uint num_hits)
102{
103 bool swapped;
104 do {
105 swapped = false;
106 for (int j = 0; j < num_hits - 1; ++j) {
107 if (hits[j].t > hits[j + 1].t) {
108 Intersection tmp_hit = hits[j];
109 float3 tmp_Ng = Ng[j];
110 hits[j] = hits[j + 1];
111 Ng[j] = Ng[j + 1];
112 hits[j + 1] = tmp_hit;
113 Ng[j + 1] = tmp_Ng;
114 swapped = true;
115 }
116 }
117 --num_hits;
118 } while (swapped);
119}
120
121/* Utility to quickly get flags from an intersection. */
122
124 const int prim,
125 const int type)
126{
127 int shader = 0;
128
129 if (type & PRIMITIVE_TRIANGLE) {
130 shader = kernel_data_fetch(tri_shader, prim);
131 }
132#ifdef __POINTCLOUD__
133 else if (type & PRIMITIVE_POINT) {
134 shader = kernel_data_fetch(points_shader, prim);
135 }
136#endif
137#ifdef __HAIR__
138 else if (type & PRIMITIVE_CURVE) {
139 shader = kernel_data_fetch(curves, prim).shader_id;
140 }
141#endif
142
143 return kernel_data_fetch(shaders, (shader & SHADER_MASK)).flags;
144}
145
147 const int prim,
148 const int isect_type)
149{
150 int shader = 0;
151
152 if (isect_type & PRIMITIVE_TRIANGLE) {
153 shader = kernel_data_fetch(tri_shader, prim);
154 }
155#ifdef __POINTCLOUD__
156 else if (isect_type & PRIMITIVE_POINT) {
157 shader = kernel_data_fetch(points_shader, prim);
158 }
159#endif
160#ifdef __HAIR__
161 else if (isect_type & PRIMITIVE_CURVE) {
162 shader = kernel_data_fetch(curves, prim).shader_id;
163 }
164#endif
165
166 return shader & SHADER_MASK;
167}
168
174
177{
178 return kernel_data_fetch(object_flag, isect->object);
179}
180
181/* TODO: find a better (faster) solution for this. Maybe store offset per object for
182 * attributes needed in intersection? */
184 const int object,
185 const uint id)
186{
187 uint attr_offset = kernel_data_fetch(objects, object).attribute_map_offset;
188 AttributeMap attr_map = kernel_data_fetch(attributes_map, attr_offset);
189
190 while (attr_map.id != id) {
191 if (UNLIKELY(attr_map.id == ATTR_STD_NONE)) {
192 if (UNLIKELY(attr_map.element == 0)) {
193 return (int)ATTR_STD_NOT_FOUND;
194 }
195 else {
196 /* Chain jump to a different part of the table. */
197 attr_offset = attr_map.offset;
198 }
199 }
200 else {
201 attr_offset += ATTR_PRIM_TYPES;
202 }
203 attr_map = kernel_data_fetch(attributes_map, attr_offset);
204 }
205
206 /* return result */
207 return (attr_map.element == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : (int)attr_map.offset;
208}
209
210/* Transparent Shadows */
211
212/* Cut-off value to stop transparent shadow tracing when practically opaque. */
213#define CURVE_SHADOW_TRANSPARENCY_CUTOFF 0.001f
214
216 KernelGlobals kg, const int object, const int prim, const int type, const float u)
217{
218 /* Find attribute. */
219 const int offset = intersection_find_attribute(kg, object, ATTR_STD_SHADOW_TRANSPARENCY);
220 if (offset == ATTR_STD_NOT_FOUND) {
221 /* If no shadow transparency attribute, assume opaque. */
222 return 0.0f;
223 }
224
225 /* Interpolate transparency between curve keys. */
226 const KernelCurve kcurve = kernel_data_fetch(curves, prim);
227 const int k0 = kcurve.first_key + PRIMITIVE_UNPACK_SEGMENT(type);
228 const int k1 = k0 + 1;
229
230 const float f0 = kernel_data_fetch(attributes_float, offset + k0);
231 const float f1 = kernel_data_fetch(attributes_float, offset + k1);
232
233 return (1.0f - u) * f0 + u * f1;
234}
235
237 const int object,
238 const int prim)
239{
240 return (self.prim == prim) && (self.object == object);
241}
242
244 const int object,
245 const int prim)
246{
247 return ((self.prim == prim) && (self.object == object)) ||
248 ((self.light_prim == prim) && (self.light_object == object));
249}
250
252 const int prim)
253{
254 return (self.prim == prim);
255}
256
257#ifdef __SHADOW_LINKING__
259ray_get_shadow_set_membership(KernelGlobals kg, ccl_ray_data const RaySelfPrimitives &self)
260{
261 if (self.light != LAMP_NONE) {
262 return kernel_data_fetch(lights, self.light).shadow_set_membership;
263 }
264
265 if (self.light_object != OBJECT_NONE) {
266 return kernel_data_fetch(objects, self.light_object).shadow_set_membership;
267 }
268
269 return LIGHT_LINK_MASK_ALL;
270}
271#endif
272
275 const int isect_object)
276{
277#ifdef __SHADOW_LINKING__
278 if (!(kernel_data.kernel_features & KERNEL_FEATURE_SHADOW_LINKING)) {
279 return false;
280 }
281
282 const uint64_t set_membership = ray_get_shadow_set_membership(kg, self);
283 if (set_membership == LIGHT_LINK_MASK_ALL) {
284 return false;
285 }
286
287 const uint blocker_set = kernel_data_fetch(objects, isect_object).blocker_shadow_set;
288 return ((uint64_t(1) << uint64_t(blocker_set)) & set_membership) == 0;
289#else
290 return false;
291#endif
292}
293
unsigned int uint
#define UNLIKELY(x)
PyObject * self
local_group_size(16, 16) .push_constant(Type b
ccl_device_forceinline int intersection_get_shader_flags(KernelGlobals kg, const int prim, const int type)
ccl_device_inline void sort_intersections_and_normals(ccl_private Intersection *hits, ccl_private float3 *Ng, uint num_hits)
ccl_device_inline bool intersection_skip_self_local(ccl_ray_data const RaySelfPrimitives &self, const int prim)
ccl_device_inline bool intersection_skip_self(ccl_ray_data const RaySelfPrimitives &self, const int object, const int prim)
ccl_device_forceinline int intersection_get_object_flags(KernelGlobals kg, ccl_private const Intersection *ccl_restrict isect)
ccl_device_inline bool intersection_skip_shadow_link(KernelGlobals kg, ccl_ray_data const RaySelfPrimitives &self, const int isect_object)
ccl_device_forceinline float intersection_t_offset(const float t)
ccl_device int intersections_compare(const void *a, const void *b)
ccl_device_forceinline int intersection_get_shader(KernelGlobals kg, ccl_private const Intersection *ccl_restrict isect)
ccl_device_inline float intersection_curve_shadow_transparency(KernelGlobals kg, const int object, const int prim, const int type, const float u)
ccl_device_inline bool intersection_skip_self_shadow(ccl_ray_data const RaySelfPrimitives &self, const int object, const int prim)
ccl_device_inline int intersection_find_attribute(KernelGlobals kg, const int object, const uint id)
ccl_device_inline float3 ray_offset(const float3 P, const float3 Ng)
CCL_NAMESPACE_BEGIN ccl_device_inline bool intersection_ray_valid(ccl_private const Ray *ray)
ccl_device_forceinline int intersection_get_shader_from_isect_prim(KernelGlobals kg, const int prim, const int isect_type)
#define kernel_assert(cond)
#define kernel_data
const KernelGlobalsCPU *ccl_restrict KernelGlobals
#define kernel_data_fetch(name, index)
#define ccl_ray_data
#define ccl_restrict
#define ccl_device_forceinline
#define ccl_device
#define ccl_private
#define ccl_device_inline
#define CCL_NAMESPACE_END
ccl_device_forceinline float3 make_float3(const float x, const float y, const float z)
#define __int_as_float(x)
ccl_device_forceinline int3 make_int3(const int x, const int y, const int z)
#define __float_as_int(x)
#define fabsf(x)
#define __float_as_uint(x)
#define __uint_as_float(x)
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
@ PRIMITIVE_CURVE
@ PRIMITIVE_TRIANGLE
@ PRIMITIVE_POINT
@ ATTR_STD_NOT_FOUND
@ ATTR_STD_NONE
@ ATTR_STD_SHADOW_TRANSPARENCY
#define PRIMITIVE_UNPACK_SEGMENT(type)
#define OBJECT_NONE
@ SHADER_MASK
@ ATTR_ELEMENT_NONE
#define KERNEL_FEATURE_SHADOW_LINKING
#define LIGHT_LINK_MASK_ALL
@ ATTR_PRIM_TYPES
#define LAMP_NONE
ccl_device_inline float len_squared(const float2 a)
unsigned int uint32_t
Definition stdint.h:80
unsigned __int64 uint64_t
Definition stdint.h:90
uint16_t element
float z
Definition sky_float3.h:27
float y
Definition sky_float3.h:27
float x
Definition sky_float3.h:27
ccl_device_inline bool isfinite_safe(float f)
Definition util/math.h:365