Blender V4.3
area.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/* Importance sampling.
12 *
13 * An Area-Preserving Parametrization for Spherical Rectangles.
14 * Carlos Urena et al.
15 *
16 * NOTE: light_p is modified when sample_coord is true. */
18 ccl_private float3 *light_p,
19 const float3 axis_u,
20 const float len_u,
21 const float3 axis_v,
22 const float len_v,
23 const float2 rand,
24 bool sample_coord)
25{
26 /* Compute local reference system R. */
27 float3 x = axis_u;
28 float3 y = axis_v;
29 float3 z = cross(x, y);
30 /* Compute rectangle coords in local reference system. */
31 float3 dir = *light_p - P;
32 float z0 = dot(dir, z);
33 /* Flip 'z' to make it point against Q. */
34 if (z0 > 0.0f) {
35 z *= -1.0f;
36 z0 *= -1.0f;
37 }
38 float xc = dot(dir, x), yc = dot(dir, y);
39 float x0 = xc - 0.5f * len_u, x1 = xc + 0.5f * len_u;
40 float y0 = yc - 0.5f * len_v, y1 = yc + 0.5f * len_v;
41 /* Compute predefined constants. */
42 float4 nz = make_float4(-y0, x1, y1, -x0);
43 nz /= sqrt(nz * nz + z0 * z0);
44 /* The original paper uses `acos()` to compute the internal angles here, and then computes the
45 * solid angle as their sum minus 2*pi. However, for very small rectangles, this results in
46 * excessive cancellation error since the sum will be almost 2*pi as well.
47 * This can be avoided by using that `asin(x) = pi/2 - acos(x)`. */
48 float g0 = safe_asinf(-nz.x * nz.y);
49 float g1 = safe_asinf(-nz.y * nz.z);
50 float g2 = safe_asinf(-nz.z * nz.w);
51 float g3 = safe_asinf(-nz.w * nz.x);
52 float S = -(g0 + g1 + g2 + g3);
53
54 if (sample_coord) {
55 /* Compute predefined constants. */
56 float b0 = nz.x;
57 float b1 = nz.z;
58 float b0sq = b0 * b0;
59 /* Compute cu.
60 * In the original paper, an additional constant k is involved here. However, just like above,
61 * it causes cancellation issues. The same `asin()` terms from above can be used instead, and
62 * the extra +pi that would remain in the expression for au can be removed by flipping the sign
63 * of cos(au) and sin(au), which also cancels if we flip the sign of b1 in the fu term. */
64 float au = rand.x * S + g2 + g3;
65 float fu = (cosf(au) * b0 + b1) / sinf(au);
66 float cu = copysignf(1.0f / sqrtf(fu * fu + b0sq), fu);
67 cu = clamp(cu, -1.0f, 1.0f);
68 /* Compute xu. */
69 float xu = -(cu * z0) / max(sqrtf(1.0f - cu * cu), 1e-7f);
70 xu = clamp(xu, x0, x1);
71 /* Compute yv. */
72 float d2 = sqr(xu) + sqr(z0);
73 float h0 = y0 / sqrtf(d2 + sqr(y0));
74 float h1 = y1 / sqrtf(d2 + sqr(y1));
75 float hv = h0 + rand.y * (h1 - h0), hv2 = hv * hv;
76 float yv = (hv2 < 1.0f - 1e-6f) ? hv * sqrtf(d2 / (1.0f - hv2)) : y1;
77
78 /* Transform (xu, yv, z0) to world coords. */
79 *light_p = P + xu * x + yv * y + z0 * z;
80 }
81
82 /* return pdf */
83 if (S < 1e-5f || reduce_min(sqr(nz)) > 0.99999f) {
84 /* The solid angle is too small to be computed accurately in single precision.
85 * As a fallback, approximate it using the planar sampling PDF,
86 * for such tiny lights the difference is irrelevant.
87 *
88 * A threshold of 1e-5 was found to be the smallest option that avoids structured
89 * artifacts at all tested parameter combinations. The additional check of nz is
90 * needed for the case where the light is viewed from grazing angles, see e.g. #98930.
91 */
92 const float t = len(dir);
93 return -t * t * t / (z0 * len_u * len_v);
94 }
95 else {
96 return 1.0f / S;
97 }
98}
99
100/* Light spread. */
101
103 const float3 lightNg,
104 const float tan_half_spread,
105 const float normalize_spread)
106{
107 /* Model a soft-box grid, computing the ratio of light not hidden by the
108 * slats of the grid at a given angle. (see D10594). */
109 const float tan_a = tan_angle(-D, lightNg);
110
111 if (tan_half_spread == 0.0f) {
112 /* The factor M_PI_F comes from integrating the radiance over the hemisphere */
113 return (tan_a > 1e-5f) ? 0.0f : M_PI_F;
114 }
115
116 return max((tan_half_spread - tan_a) * normalize_spread, 0.0f);
117}
118
119/* Compute the minimal rectangle, circle or ellipse that covers the valid sample region, to reduce
120 * noise with low spread. */
122 const float3 lightNg,
123 ccl_private float3 *lightP,
124 ccl_private float3 *axis_u,
125 ccl_private float *len_u,
126 ccl_private float3 *axis_v,
127 ccl_private float *len_v,
128 const float tan_half_spread,
129 ccl_private bool *sample_rectangle)
130{
131 /* Distance from shading point to area light plane and the closest point on that plane. */
132 const float t = dot(lightNg, P - *lightP);
133 const float3 closest_P = P - t * lightNg;
134
135 /* Radius of circle on area light that actually affects the shading point. */
136 const float r_spread = t * tan_half_spread;
137
138 /* Local uv coordinates of closest point. */
139 const float spread_u = dot(*axis_u, closest_P - *lightP);
140 const float spread_v = dot(*axis_v, closest_P - *lightP);
141
142 const bool is_round = !(*sample_rectangle) && (*len_u == *len_v);
143
144 /* Whether we should sample the spread circle. */
145 bool sample_spread = (r_spread == 0.0f);
146 if (is_round && !sample_spread) {
147 /* Distance between the centers of the disk light and the valid region circle. */
148 const float dist = len(make_float2(spread_u, spread_v));
149
150 /* Radius of the disk light. */
151 const float r = *len_u * 0.5f;
152
153 if (dist >= r + r_spread) {
154 /* Two circles are outside each other or touch externally. */
155 return false;
156 }
157
158 sample_spread = (dist <= fabsf(r - r_spread)) && (r_spread < r);
159 if (dist > fabsf(r - r_spread)) {
160 /* Two circles intersect. Find the smallest rectangle that covers the intersection */
161 const float len_u_ = r + r_spread - dist;
162 const float len_v_ = (fabsf(sqr(r) - sqr(r_spread)) >= sqr(dist)) ?
163 2.0f * fminf(r, r_spread) :
164 sqrtf(sqr(2.0f * r_spread) -
165 sqr(dist + (sqr(r_spread) - sqr(r)) / dist));
166
167 const float rect_area = len_u_ * len_v_;
168 const float circle_area = M_PI_F * sqr(r);
169 const float spread_area = M_PI_F * sqr(r_spread);
170
171 /* Sample the shape with minimal area. */
172 if (rect_area < fminf(circle_area, spread_area)) {
173 *sample_rectangle = true;
174 *axis_u = normalize(*lightP - closest_P);
175 *axis_v = rotate_around_axis(*axis_u, lightNg, M_PI_2_F);
176 *len_u = len_u_;
177 *len_v = len_v_;
178 *lightP = 0.5f * (*lightP + closest_P + *axis_u * (r_spread - r));
179 return true;
180 }
181
182 sample_spread = (spread_area < circle_area);
183 }
184 }
185 else if (!is_round && !sample_spread) {
186 /* Compute rectangle encompassing the circle that affects the shading point,
187 * clamped to the bounds of the area light. */
188 const float min_u = max(spread_u - r_spread, -*len_u * 0.5f);
189 const float max_u = min(spread_u + r_spread, *len_u * 0.5f);
190 const float min_v = max(spread_v - r_spread, -*len_v * 0.5f);
191 const float max_v = min(spread_v + r_spread, *len_v * 0.5f);
192
193 /* Skip if rectangle is empty. */
194 if (min_u >= max_u || min_v >= max_v) {
195 return false;
196 }
197
198 const float rect_len_u = max_u - min_u;
199 const float rect_len_v = max_v - min_v;
200
201 const float rect_area = rect_len_u * rect_len_v;
202 const float ellipse_area = (*sample_rectangle) ? FLT_MAX : M_PI_4_F * (*len_u) * (*len_v);
203 const float spread_area = M_PI_F * sqr(r_spread);
204
205 /* Sample the shape with minimal area. */
206 /* NOTE: we don't switch to spread circle sampling for rectangle light because rectangle light
207 * supports solid angle sampling, which has less variance than sampling the area. If ellipse
208 * area light also supports solid angle sampling, `*sample_rectangle ||` could be deleted. */
209 if (*sample_rectangle || rect_area < fminf(ellipse_area, spread_area)) {
210 *sample_rectangle = true;
211
212 /* Compute new area light center position and axes from rectangle in local
213 * uv coordinates. */
214 const float new_center_u = 0.5f * (min_u + max_u);
215 const float new_center_v = 0.5f * (min_v + max_v);
216
217 *len_u = rect_len_u;
218 *len_v = rect_len_v;
219 *lightP = *lightP + *axis_u * new_center_u + *axis_v * new_center_v;
220 return true;
221 }
222 *sample_rectangle = false;
223 sample_spread = (spread_area < ellipse_area);
224 }
225
226 if (sample_spread) {
227 *sample_rectangle = false;
228 *lightP = *lightP + *axis_u * spread_u + *axis_v * spread_v;
229 *len_u = r_spread * 2.0f;
230 *len_v = r_spread * 2.0f;
231 return true;
232 }
233
234 /* Don't clamp. */
235 return true;
236}
237
239{
240 return light->invarea < 0.0f;
241}
242
243/* Common API. */
244/* Compute `eval_fac` and `pdf`. Also sample a new position on the light if `sample_coord`. */
245template<bool in_volume_segment>
247 const float3 ray_P,
248 ccl_private float3 *light_P,
250 const float2 rand,
251 bool sample_coord)
252{
253 float3 axis_u = klight->area.axis_u;
254 float3 axis_v = klight->area.axis_v;
255 float len_u = klight->area.len_u;
256 float len_v = klight->area.len_v;
257
258 const float3 Ng = klight->area.dir;
259 const float invarea = fabsf(klight->area.invarea);
260 bool sample_rectangle = (klight->area.invarea > 0.0f);
261
262 float3 light_P_new = *light_P;
263
264 if (in_volume_segment) {
265 light_P_new += sample_rectangle ?
266 rectangle_sample(axis_u * len_u * 0.5f, axis_v * len_v * 0.5f, rand) :
267 ellipse_sample(axis_u * len_u * 0.5f, axis_v * len_v * 0.5f, rand);
268 ls->pdf = invarea;
269 }
270 else {
271 if (klight->area.normalize_spread > 0) {
273 Ng,
274 &light_P_new,
275 &axis_u,
276 &len_u,
277 &axis_v,
278 &len_v,
279 klight->area.tan_half_spread,
280 &sample_rectangle))
281 {
282 return false;
283 }
284 }
285
286 if (sample_rectangle) {
287 ls->pdf = area_light_rect_sample(
288 ray_P, &light_P_new, axis_u, len_u, axis_v, len_v, rand, sample_coord);
289 }
290 else {
291 if (klight->area.tan_half_spread == 0.0f) {
292 ls->pdf = 1.0f;
293 }
294 else {
295 if (sample_coord) {
296 light_P_new += ellipse_sample(axis_u * len_u * 0.5f, axis_v * len_v * 0.5f, rand);
297 }
298 ls->pdf = 4.0f * M_1_PI_F / (len_u * len_v);
299 }
300 }
301 }
302
303 if (sample_coord) {
304 *light_P = light_P_new;
305 ls->D = normalize_len(*light_P - ray_P, &ls->t);
306 }
307
308 /* Convert radiant flux to radiance. */
309 ls->eval_fac = M_1_PI_F * invarea;
310
311 if (klight->area.normalize_spread > 0) {
312 /* Area Light spread angle attenuation */
313 ls->eval_fac *= area_light_spread_attenuation(
314 ls->D, Ng, klight->area.tan_half_spread, klight->area.normalize_spread);
315 }
316
317 if (in_volume_segment || (!sample_rectangle && klight->area.tan_half_spread > 0)) {
318 ls->pdf *= light_pdf_area_to_solid_angle(Ng, -ls->D, ls->t);
319 }
320
321 return in_volume_segment || ls->eval_fac > 0;
322}
323
324template<bool in_volume_segment>
326 const float2 rand,
327 const float3 P,
329{
330 ls->P = klight->co;
331 ls->Ng = klight->area.dir;
332
333 if (!in_volume_segment) {
334 if (dot(ls->P - P, ls->Ng) > 0.0f) {
335 return false;
336 }
337 }
338
339 if (!area_light_eval<in_volume_segment>(klight, P, &ls->P, ls, rand, true)) {
340 return false;
341 }
342
343 const float3 inplane = ls->P - klight->co;
344 float light_u = dot(inplane, klight->area.axis_u);
345 float light_v = dot(inplane, klight->area.axis_v);
346
347 if (!in_volume_segment && klight->area.normalize_spread > 0) {
348 const bool is_ellipse = area_light_is_ellipse(&klight->area);
349
350 /* Check whether the sampled point lies outside of the area light.
351 * For very small area lights, numerical issues can cause this to be
352 * slightly off since the sampling logic clamps the result right at the border,
353 * so allow for a small margin of error. */
354 const float len_u_epsilon = ((0.5f + 1e-7f) * klight->area.len_u + 1e-6f);
355 const float len_v_epsilon = ((0.5f + 1e-7f) * klight->area.len_v + 1e-6f);
356 if (is_ellipse && (sqr(light_u / len_u_epsilon) + sqr(light_v / len_v_epsilon) > 1.0f)) {
357 return false;
358 }
359 if (!is_ellipse && (fabsf(light_u) > len_u_epsilon || fabsf(light_v) > len_v_epsilon)) {
360 return false;
361 }
362 }
363
364 light_u /= klight->area.len_u;
365 light_v /= klight->area.len_v;
366
367 /* NOTE: Return barycentric coordinates in the same notation as Embree and OptiX. */
368 ls->u = light_v + 0.5f;
369 ls->v = -light_u - light_v;
370
371 return true;
372}
373
376 const float3 P)
377{
378 if (klight->area.tan_half_spread == 0) {
379 /* Update position on the light to keep the direction fixed. */
380 area_light_eval<false>(klight, P, &ls->P, ls, zero_float2(), true);
381 }
382 else {
383 ls->D = normalize_len(ls->P - P, &ls->t);
384 area_light_eval<false>(klight, P, &ls->P, ls, zero_float2(), false);
385 /* Convert pdf to be in area measure. */
386 ls->pdf /= light_pdf_area_to_solid_angle(ls->Ng, -ls->D, ls->t);
387 }
388}
389
391 const ccl_private Ray *ccl_restrict ray,
392 ccl_private float *t,
393 ccl_private float *u,
394 ccl_private float *v)
395{
396 /* Area light. */
397 const float invarea = fabsf(klight->area.invarea);
398 const bool is_ellipse = area_light_is_ellipse(&klight->area);
399 if (invarea == 0.0f) {
400 return false;
401 }
402
403 const float3 inv_extent_u = klight->area.axis_u / klight->area.len_u;
404 const float3 inv_extent_v = klight->area.axis_v / klight->area.len_v;
405 const float3 Ng = klight->area.dir;
406
407 /* One sided. */
408 if (dot(ray->D, Ng) >= 0.0f) {
409 return false;
410 }
411
412 const float3 light_P = klight->co;
413
414 float3 P;
415 return ray_quad_intersect(ray->P,
416 ray->D,
417 ray->tmin,
418 ray->tmax,
419 light_P,
420 inv_extent_u,
421 inv_extent_v,
422 Ng,
423 &P,
424 t,
425 u,
426 v,
427 is_ellipse);
428}
429
431 const ccl_global KernelLight *klight,
433 const float3 ray_P,
434 const float3 ray_D,
436{
437 ls->u = isect->u;
438 ls->v = isect->v;
439 ls->D = ray_D;
440 ls->Ng = klight->area.dir;
441
442 float3 light_P = klight->co;
443 return area_light_eval<false>(klight, ray_P, &light_P, ls, zero_float2(), false);
444}
445
446/* Returns the maximal distance between the light center and the boundary. */
448{
449 return 0.5f * (area_light_is_ellipse(light) ? fmaxf(light->len_u, light->len_v) :
450 len(make_float2(light->len_u, light->len_v)));
451}
452
453/* Find the ray segment lit by the area light. */
455 float3 P,
456 float3 D,
457 ccl_private float2 *t_range)
458{
459 bool valid;
460 const float tan_half_spread = light->tan_half_spread;
461 float3 axis = light->dir;
462
463 const bool angle_almost_zero = (tan_half_spread < 1e-5f);
464 if (angle_almost_zero) {
465 /* Map to local coordinate of the light. Do not use `itfm` in `KernelLight` as there might be
466 * additional scaling in the light size. */
467 const Transform tfm = make_transform(light->axis_u, light->axis_v, axis);
468 P = transform_point(&tfm, P);
469 D = transform_direction(&tfm, D);
470 axis = make_float3(0.0f, 0.0f, 1.0f);
471
472 const float half_len_u = 0.5f * light->len_u;
473 const float half_len_v = 0.5f * light->len_v;
474 if (area_light_is_ellipse(light)) {
475 valid = ray_infinite_cylinder_intersect(P, D, half_len_u, half_len_v, t_range);
476 }
477 else {
478 const float3 bbox_min = make_float3(-half_len_u, -half_len_v, 0.0f);
479 const float3 bbox_max = make_float3(half_len_u, half_len_v, FLT_MAX);
480 valid = ray_aabb_intersect(bbox_min, bbox_max, P, D, t_range);
481 }
482 }
483 else {
484 /* Conservative estimation with the smallest possible cone covering the whole spread. */
485 const float3 apex_to_point = P + area_light_max_extent(light) / tan_half_spread * axis;
486 const float cos_angle_sq = 1.0f / (1.0f + sqr(tan_half_spread));
487
488 valid = ray_cone_intersect(axis, apex_to_point, D, cos_angle_sq, t_range);
489 }
490
491 /* Limit the range to the positive side of the area light. */
492 return valid && ray_plane_intersect(axis, P, D, t_range);
493}
494
495template<bool in_volume_segment>
497 const float3 centroid,
498 const float3 P,
499 const float3 N,
500 const float3 bcone_axis,
501 ccl_private float &cos_theta_u,
502 ccl_private float2 &distance,
503 ccl_private float3 &point_to_centroid)
504{
505 /* TODO: a cheap substitute for minimal distance between point and primitive. Does it worth the
506 * overhead to compute the accurate minimal distance? */
507 float min_distance;
508 point_to_centroid = safe_normalize_len(centroid - P, &min_distance);
509 distance = make_float2(min_distance, min_distance);
510
511 cos_theta_u = FLT_MAX;
512
513 const float3 extentu = klight->area.axis_u * klight->area.len_u;
514 const float3 extentv = klight->area.axis_v * klight->area.len_v;
515 for (int i = 0; i < 4; i++) {
516 const float3 corner = ((i & 1) - 0.5f) * extentu + 0.5f * ((i & 2) - 1) * extentv + centroid;
517 float distance_point_to_corner;
518 const float3 point_to_corner = safe_normalize_len(corner - P, &distance_point_to_corner);
519 cos_theta_u = fminf(cos_theta_u, dot(point_to_centroid, point_to_corner));
520 if (!in_volume_segment) {
521 distance.x = fmaxf(distance.x, distance_point_to_corner);
522 }
523 }
524
525 const bool front_facing = dot(bcone_axis, point_to_centroid) < 0;
526 const bool shape_above_surface = dot(N, centroid - P) + fabsf(dot(N, extentu)) +
527 fabsf(dot(N, extentv)) >
528 0;
529
530 return front_facing && shape_above_surface;
531}
532
sqrt(x)+1/max(0
MINLINE float safe_asinf(float a)
ccl_device bool area_light_spread_clamp_light(const float3 P, const float3 lightNg, ccl_private float3 *lightP, ccl_private float3 *axis_u, ccl_private float *len_u, ccl_private float3 *axis_v, ccl_private float *len_v, const float tan_half_spread, ccl_private bool *sample_rectangle)
Definition area.h:121
ccl_device_forceinline bool area_light_is_ellipse(const ccl_global KernelAreaLight *light)
Definition area.h:238
ccl_device_inline bool area_light_sample(const ccl_global KernelLight *klight, const float2 rand, const float3 P, ccl_private LightSample *ls)
Definition area.h:325
ccl_device_inline bool area_light_valid_ray_segment(const ccl_global KernelAreaLight *light, float3 P, float3 D, ccl_private float2 *t_range)
Definition area.h:454
CCL_NAMESPACE_BEGIN ccl_device_inline float area_light_rect_sample(float3 P, ccl_private float3 *light_p, const float3 axis_u, const float len_u, const float3 axis_v, const float len_v, const float2 rand, bool sample_coord)
Definition area.h:17
ccl_device_inline bool area_light_intersect(const ccl_global KernelLight *klight, const ccl_private Ray *ccl_restrict ray, ccl_private float *t, ccl_private float *u, ccl_private float *v)
Definition area.h:390
ccl_device float area_light_spread_attenuation(const float3 D, const float3 lightNg, const float tan_half_spread, const float normalize_spread)
Definition area.h:102
ccl_device_inline bool area_light_eval(const ccl_global KernelLight *klight, const float3 ray_P, ccl_private float3 *light_P, ccl_private LightSample *ccl_restrict ls, const float2 rand, bool sample_coord)
Definition area.h:246
ccl_device_forceinline void area_light_mnee_sample_update(const ccl_global KernelLight *klight, ccl_private LightSample *ls, const float3 P)
Definition area.h:374
ccl_device_forceinline float area_light_max_extent(const ccl_global KernelAreaLight *light)
Definition area.h:447
ccl_device_forceinline bool area_light_tree_parameters(const ccl_global KernelLight *klight, const float3 centroid, const float3 P, const float3 N, const float3 bcone_axis, ccl_private float &cos_theta_u, ccl_private float2 &distance, ccl_private float3 &point_to_centroid)
Definition area.h:496
ccl_device_inline bool area_light_sample_from_intersection(const ccl_global KernelLight *klight, ccl_private const Intersection *ccl_restrict isect, const float3 ray_P, const float3 ray_D, ccl_private LightSample *ccl_restrict ls)
Definition area.h:430
ATTR_WARN_UNUSED_RESULT const BMVert * v
SIMD_FORCE_INLINE const btScalar & z() const
Return the z value.
Definition btQuadWord.h:117
SIMD_FORCE_INLINE btVector3 & normalize()
Normalize this vector x^2 + y^2 + z^2 = 1.
Definition btVector3.h:303
additional_info("compositor_sum_squared_difference_float_shared") .push_constant(Type output_img float dot(value.rgb, luminance_coefficients)") .define("LOAD(value)"
#define ccl_restrict
#define ccl_device_forceinline
#define sinf(x)
#define cosf(x)
#define ccl_device
#define ccl_private
#define ccl_device_inline
#define ccl_global
#define CCL_NAMESPACE_END
ccl_device_forceinline float4 make_float4(const float x, const float y, const float z, const float w)
ccl_device_forceinline float3 make_float3(const float x, const float y, const float z)
#define fmaxf(x, y)
#define fminf(x, y)
ccl_device_forceinline float2 make_float2(const float x, const float y)
#define copysignf(x, y)
#define fabsf(x)
#define sqrtf(x)
int len
ccl_device_inline float3 rectangle_sample(float3 ru, float3 rv, float2 rand)
ccl_device_inline float3 ellipse_sample(float3 ru, float3 rv, float2 rand)
ccl_device float light_pdf_area_to_solid_angle(const float3 Ng, const float3 I, float t)
CCL_NAMESPACE_BEGIN ccl_device_inline float2 zero_float2()
Definition math_float2.h:14
ccl_device_inline float2 normalize_len(const float2 a, ccl_private float *t)
ccl_device_inline float cross(const float2 a, const float2 b)
ccl_device_inline float reduce_min(const float2 a)
ccl_device_inline float3 safe_normalize_len(const float3 a, ccl_private float *t)
ccl_device_inline bool ray_cone_intersect(const float3 axis, const float3 P, float3 D, const float cos_angle_sq, ccl_private float2 *t_range)
ccl_device bool ray_aabb_intersect(const float3 bbox_min, const float3 bbox_max, const float3 ray_P, const float3 ray_D, ccl_private float2 *t_range)
ccl_device_inline bool ray_infinite_cylinder_intersect(const float3 P, const float3 D, const float len_u, const float len_v, ccl_private float2 *t_range)
ccl_device bool ray_quad_intersect(float3 ray_P, float3 ray_D, float ray_tmin, float ray_tmax, float3 quad_P, float3 inv_quad_u, float3 inv_quad_v, float3 quad_n, ccl_private float3 *isect_P, ccl_private float *isect_t, ccl_private float *isect_u, ccl_private float *isect_v, bool ellipse)
ccl_device bool ray_plane_intersect(const float3 N, const float3 P, const float3 ray_D, ccl_private float2 *t_range)
#define N
#define M_PI_F
Definition mikk_util.hh:15
smooth(Type::FLOAT, "selectionFac") .flat(Type au[]
#define M_PI_2_F
Definition sky_float3.h:20
#define min(a, b)
Definition sort.c:32
#define FLT_MAX
Definition stdcycles.h:14
float x
float y
ccl_device_inline Transform make_transform(float a, float b, float c, float d, float e, float f, float g, float h, float i, float j, float k, float l)
Definition transform.h:133
ccl_device_inline float3 transform_direction(ccl_private const Transform *t, const float3 a)
Definition transform.h:94
CCL_NAMESPACE_END CCL_NAMESPACE_BEGIN ccl_device_inline float3 transform_point(ccl_private const Transform *t, const float3 a)
Definition transform.h:63
float max
ccl_device_inline float tan_angle(float3 a, float3 b)
Definition util/math.h:994
ccl_device_inline float sqr(float a)
Definition util/math.h:782
ccl_device_inline float3 rotate_around_axis(float3 p, float3 axis, float angle)
Definition util/math.h:683
ccl_device_inline int clamp(int a, int mn, int mx)
Definition util/math.h:379