20 const float sphere_radius,
24 const float3 d_vec = sphere_P - ray_P;
25 const float r_sq = sphere_radius * sphere_radius;
26 const float d_sq =
dot(d_vec, d_vec);
27 const float d_cos_theta =
dot(d_vec, ray_D);
29 if (d_sq > r_sq && d_cos_theta < 0.0f) {
34 const float d_sin_theta_sq =
len_squared(d_vec - d_cos_theta * ray_D);
36 if (d_sin_theta_sq > r_sq) {
42 const float t = d_cos_theta -
copysignf(
sqrtf(r_sq - d_sin_theta_sq), d_sq - r_sq);
44 if (t > ray_tmin && t < ray_tmax) {
46 *isect_P = ray_P + ray_D * t;
58 const float disk_radius,
65 const float div =
dot(ray_D, disk_N);
70 const float t = -disk_t / div;
71 if (!(t > ray_tmin && t < ray_tmax)) {
75 const float3 P = ray_P + ray_D * t;
76 if (
len_squared(
P - disk_P) > disk_radius * disk_radius) {
90 const float disk_radius,
94 const float3 vp = ray_P - disk_P;
95 const float dp =
dot(vp, disk_N);
96 const float cos_angle =
dot(disk_N, -ray_D);
97 if (dp * cos_angle > 0.f)
99 const float t = dp / cos_angle;
103 const float3 P = ray_P + t * ray_D;
106 if (
dot(
T,
T) <
sqr(disk_radius) && (t > ray_tmin && t < ray_tmax)) {
107 *isect_P = ray_P + t * ray_D;
118#ifdef __KERNEL_NEON__
121 a = vsetq_lane_f32(
x, a, 0);
122 float32x4_t rt_rcp = vrecpeq_f32(a);
123 rt_rcp = vmulq_f32(vrecpsq_f32(a, rt_rcp), rt_rcp);
124 rt_rcp = vmulq_f32(vrecpsq_f32(a, rt_rcp), rt_rcp);
125 return vgetq_lane_f32(rt_rcp, 0);
126#elif defined(__KERNEL_SSE__)
127 const __m128 a = _mm_set_ss(
x);
128 const __m128 r = _mm_rcp_ss(a);
130# ifdef __KERNEL_AVX2_
131 return _mm_cvtss_f32(_mm_mul_ss(r, _mm_fnmadd_ss(r, a, _mm_set_ss(2.0f))));
133 return _mm_cvtss_f32(_mm_mul_ss(r, _mm_sub_ss(_mm_set_ss(2.0f), _mm_mul_ss(r, a))));
142#if defined(__KERNEL_SSE42__) && defined(__KERNEL_SSE__)
147 return a.
x *
b.x + a.
y *
b.y + a.
z *
b.z;
153#if defined(__KERNEL_SSE42__) && defined(__KERNEL_SSE__)
165 const float ray_tmin,
166 const float ray_tmax,
178 const float3 v0 = tri_a - ray_P;
179 const float3 v1 = tri_b - ray_P;
184 const float3 e1 = v0 - v1;
192 const float UVW =
U +
V +
W;
193 const float eps = FLT_EPSILON *
fabsf(UVW);
197 if (!(minUVW >= -
eps || maxUVW <=
eps)) {
203 const float3 Ng = Ng1 + Ng1;
204 const float den =
dot(Ng, ray_D);
211 const float T =
dot(v0, Ng);
212 const float t =
T / den;
213 if (!(t >= ray_tmin && t <= ray_tmax)) {
218 *isect_u =
min(
U * rcp_uvw, 1.0f);
219 *isect_v =
min(
V * rcp_uvw, 1.0f);
238 const float3 e1 = v0 - v1;
252 return (minUVW >=
eps || maxUVW <= -
eps);
262 const float ray_tmin,
263 const float ray_tmax,
275 const float t = -(
dot(ray_P, quad_n) -
dot(quad_P, quad_n)) /
dot(ray_D, quad_n);
276 if (!(t > ray_tmin && t < ray_tmax)) {
279 const float3 hit = ray_P + t * ray_D;
280 const float3 inplane = hit - quad_P;
281 const float u =
dot(inplane, inv_quad_u);
282 if (u < -0.5f || u > 0.5f) {
285 const float v =
dot(inplane, inv_quad_v);
289 if (ellipse && (u * u +
v *
v > 0.25f)) {
294 if (isect_P !=
nullptr) {
297 if (isect_t !=
nullptr) {
302 if (isect_u !=
nullptr) {
305 if (isect_v !=
nullptr) {
319 const float DN =
dot(ray_D,
N);
322 const float t = -
dot(
P,
N) / DN;
326 t_range->min =
fmaxf(t_range->min, t);
329 t_range->max =
fminf(t_range->max, t);
332 return !t_range->is_empty();
345 const float3 t_lower = (bbox_min - ray_P) * inv_ray_D;
346 const float3 t_upper = (bbox_max - ray_P) * inv_ray_D;
356 *t_range = {tmin, tmax};
358 return !t_range->is_empty();
375 const float a =
dot(D_proj, D_proj);
376 float b =
dot(P_proj, D_proj);
379 const float t_mid = -
b / a;
380 P_proj += D_proj * t_mid;
383 b =
dot(P_proj, D_proj);
384 const float c =
dot(P_proj, P_proj) - 1.0f;
392 return valid && !t_range->is_empty();
410 const float cos_angle_sq,
413 if (cos_angle_sq < 1e-4f) {
421 const float AD =
dot(axis,
D);
422 const float AP =
dot(axis,
P);
424 const float a =
sqr(AD) - cos_angle_sq;
425 const float b = 2.0f * (AD * AP - cos_angle_sq *
dot(
D,
P));
426 const float c =
sqr(AP) - cos_angle_sq *
dot(
P,
P);
433 const bool tmin_valid = AP + tmin * AD > 0.0f;
434 const bool tmax_valid = AP + tmax * AD > 0.0f;
436 valid &= (tmin_valid || tmax_valid);
442 else if (!tmin_valid) {
449 return valid && !t_range->is_empty();
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert * v
reduce_max(value.rgb)") DEFINE_VALUE("REDUCE(lhs
dot(value.rgb, luminance_coefficients)") DEFINE_VALUE("REDUCE(lhs
#define ccl_device_forceinline
#define ccl_device_inline
#define CCL_NAMESPACE_END
ccl_device_inline float inversesqrtf(const float f)
ccl_device_inline bool solve_quadratic(const float a, const float b, const float c, ccl_private float &x1, ccl_private float &x2)
ccl_device_inline Interval< T > intervals_intersection(const ccl_private Interval< T > &first, const ccl_private Interval< T > &second)
CCL_NAMESPACE_BEGIN ccl_device_inline float madd(const float a, const float b, const float c)
ccl_device_inline float len_squared(const float2 a)
ccl_device_inline float2 normalize_len(const float2 a, ccl_private float *t)
ccl_device_inline float reduce_min(const float2 a)
ccl_device_inline float3 reciprocal(const float3 a)
ccl_device_inline float4 msub(const float4 a, const float4 b, const float4 c)
ccl_device_inline bool ray_cone_intersect(const float3 axis, const float3 P, float3 D, const float cos_angle_sq, ccl_private Interval< float > *t_range)
ccl_device bool ray_disk_intersect(const float3 ray_P, const float3 ray_D, const float ray_tmin, const float ray_tmax, const float3 disk_P, const float3 disk_N, const float disk_radius, ccl_private float3 *isect_P, ccl_private float *isect_t)
ccl_device bool ray_aabb_intersect(const float3 bbox_min, const float3 bbox_max, const float3 ray_P, const float3 ray_D, ccl_private Interval< float > *t_range)
CCL_NAMESPACE_BEGIN ccl_device bool ray_sphere_intersect(const float3 ray_P, const float3 ray_D, const float ray_tmin, const float ray_tmax, const float3 sphere_P, const float sphere_radius, ccl_private float3 *isect_P, ccl_private float *isect_t)
ccl_device_forceinline bool ray_triangle_intersect(const float3 ray_P, const float3 ray_D, const float ray_tmin, const float ray_tmax, const float3 tri_a, const float3 tri_b, const float3 tri_c, ccl_private float *isect_u, ccl_private float *isect_v, ccl_private float *isect_t)
ccl_device_forceinline float ray_triangle_reciprocal(const float x)
ccl_device bool ray_aligned_disk_intersect(const float3 ray_P, const float3 ray_D, const float ray_tmin, const float ray_tmax, const float3 disk_P, const float disk_radius, ccl_private float3 *isect_P, ccl_private float *isect_t)
ccl_device_inline bool ray_infinite_cylinder_intersect(const float3 P, const float3 D, const float len_u, const float len_v, ccl_private Interval< float > *t_range)
ccl_device bool ray_plane_intersect(const float3 N, const float3 P, const float3 ray_D, ccl_private Interval< float > *t_range)
ccl_device_forceinline bool ray_triangle_intersect_self(const float3 ray_P, const float3 ray_D, const float3 verts[3])
ccl_device_inline float3 ray_triangle_cross(const float3 a, const float3 b)
ccl_device bool ray_quad_intersect(const float3 ray_P, const float3 ray_D, const float ray_tmin, const float ray_tmax, const float3 quad_P, const float3 inv_quad_u, const float3 inv_quad_v, const 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_inline float ray_triangle_dot(const float3 a, const float3 b)
CCL_NAMESPACE_BEGIN struct Window V