32 float z0 =
dot(dir,
z);
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;
43 nz /=
sqrt(nz * nz + z0 * z0);
52 float S = -(g0 + g1 + g2 + g3);
64 float au = rand.
x * S + g2 + g3;
67 cu =
clamp(cu, -1.0f, 1.0f);
69 float xu = -(cu * z0) /
max(
sqrtf(1.0f - cu * cu), 1e-7f);
70 xu =
clamp(xu, x0, x1);
72 float d2 =
sqr(xu) +
sqr(z0);
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;
79 *light_p =
P + xu * x + yv * y + z0 *
z;
92 const float t =
len(dir);
93 return -t * t * t / (z0 * len_u * len_v);
104 const float tan_half_spread,
105 const float normalize_spread)
109 const float tan_a =
tan_angle(-D, lightNg);
111 if (tan_half_spread == 0.0f) {
113 return (tan_a > 1e-5f) ? 0.0f :
M_PI_F;
116 return max((tan_half_spread - tan_a) * normalize_spread, 0.0f);
128 const float tan_half_spread,
132 const float t =
dot(lightNg,
P - *lightP);
133 const float3 closest_P =
P - t * lightNg;
136 const float r_spread = t * tan_half_spread;
139 const float spread_u =
dot(*axis_u, closest_P - *lightP);
140 const float spread_v =
dot(*axis_v, closest_P - *lightP);
142 const bool is_round = !(*sample_rectangle) && (*len_u == *len_v);
145 bool sample_spread = (r_spread == 0.0f);
146 if (is_round && !sample_spread) {
151 const float r = *len_u * 0.5f;
153 if (dist >= r + r_spread) {
158 sample_spread = (dist <=
fabsf(r - r_spread)) && (r_spread < r);
159 if (dist >
fabsf(r - r_spread)) {
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) :
165 sqr(dist + (
sqr(r_spread) -
sqr(r)) / dist));
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);
172 if (rect_area <
fminf(circle_area, spread_area)) {
173 *sample_rectangle =
true;
174 *axis_u =
normalize(*lightP - closest_P);
178 *lightP = 0.5f * (*lightP + closest_P + *axis_u * (r_spread - r));
182 sample_spread = (spread_area < circle_area);
185 else if (!is_round && !sample_spread) {
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);
194 if (min_u >= max_u || min_v >= max_v) {
198 const float rect_len_u = max_u - min_u;
199 const float rect_len_v = max_v - min_v;
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);
209 if (*sample_rectangle || rect_area <
fminf(ellipse_area, spread_area)) {
210 *sample_rectangle =
true;
214 const float new_center_u = 0.5f * (min_u + max_u);
215 const float new_center_v = 0.5f * (min_v + max_v);
219 *lightP = *lightP + *axis_u * new_center_u + *axis_v * new_center_v;
222 *sample_rectangle =
false;
223 sample_spread = (spread_area < ellipse_area);
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;
240 return light->invarea < 0.0f;
245template<
bool in_volume_segment>
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;
258 const float3 Ng = klight->area.dir;
259 const float invarea =
fabsf(klight->area.invarea);
260 bool sample_rectangle = (klight->area.invarea > 0.0f);
262 float3 light_P_new = *light_P;
264 if (in_volume_segment) {
265 light_P_new += sample_rectangle ?
267 ellipse_sample(axis_u * len_u * 0.5f, axis_v * len_v * 0.5f, rand);
271 if (klight->area.normalize_spread > 0) {
279 klight->area.tan_half_spread,
286 if (sample_rectangle) {
288 ray_P, &light_P_new, axis_u, len_u, axis_v, len_v, rand, sample_coord);
291 if (klight->area.tan_half_spread == 0.0f) {
296 light_P_new +=
ellipse_sample(axis_u * len_u * 0.5f, axis_v * len_v * 0.5f, rand);
298 ls->pdf = 4.0f * M_1_PI_F / (len_u * len_v);
304 *light_P = light_P_new;
309 ls->eval_fac = M_1_PI_F * invarea;
311 if (klight->area.normalize_spread > 0) {
314 ls->D, Ng, klight->area.tan_half_spread, klight->area.normalize_spread);
317 if (in_volume_segment || (!sample_rectangle && klight->area.tan_half_spread > 0)) {
321 return in_volume_segment || ls->eval_fac > 0;
324template<
bool in_volume_segment>
331 ls->Ng = klight->area.dir;
333 if (!in_volume_segment) {
334 if (
dot(ls->P -
P, ls->Ng) > 0.0f) {
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);
347 if (!in_volume_segment && klight->area.normalize_spread > 0) {
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)) {
359 if (!is_ellipse && (
fabsf(light_u) > len_u_epsilon ||
fabsf(light_v) > len_v_epsilon)) {
364 light_u /= klight->area.len_u;
365 light_v /= klight->area.len_v;
368 ls->u = light_v + 0.5f;
369 ls->v = -light_u - light_v;
378 if (klight->area.tan_half_spread == 0) {
397 const float invarea =
fabsf(klight->area.invarea);
399 if (invarea == 0.0f) {
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;
408 if (
dot(ray->D, Ng) >= 0.0f) {
412 const float3 light_P = klight->co;
440 ls->Ng = klight->area.dir;
442 float3 light_P = klight->co;
460 const float tan_half_spread = light->tan_half_spread;
463 const bool angle_almost_zero = (tan_half_spread < 1e-5f);
464 if (angle_almost_zero) {
472 const float half_len_u = 0.5f * light->len_u;
473 const float half_len_v = 0.5f * light->len_v;
486 const float cos_angle_sq = 1.0f / (1.0f +
sqr(tan_half_spread));
495template<
bool in_volume_segment>
509 distance =
make_float2(min_distance, min_distance);
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;
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);
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)) +
530 return front_facing && shape_above_surface;
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)
ccl_device_forceinline bool area_light_is_ellipse(const ccl_global KernelAreaLight *light)
ccl_device_inline bool area_light_sample(const ccl_global KernelLight *klight, const float2 rand, const float3 P, ccl_private LightSample *ls)
ccl_device_inline bool area_light_valid_ray_segment(const ccl_global KernelAreaLight *light, float3 P, float3 D, ccl_private float2 *t_range)
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)
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)
ccl_device float area_light_spread_attenuation(const float3 D, const float3 lightNg, const float tan_half_spread, const float normalize_spread)
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)
ccl_device_forceinline void area_light_mnee_sample_update(const ccl_global KernelLight *klight, ccl_private LightSample *ls, const float3 P)
ccl_device_forceinline float area_light_max_extent(const ccl_global KernelAreaLight *light)
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)
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)
ATTR_WARN_UNUSED_RESULT const BMVert * v
SIMD_FORCE_INLINE const btScalar & z() const
Return the z value.
SIMD_FORCE_INLINE btVector3 & normalize()
Normalize this vector x^2 + y^2 + z^2 = 1.
additional_info("compositor_sum_squared_difference_float_shared") .push_constant(Type output_img float dot(value.rgb, luminance_coefficients)") .define("LOAD(value)"
#define ccl_device_forceinline
#define ccl_device_inline
#define CCL_NAMESPACE_END
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()
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)
smooth(Type::FLOAT, "selectionFac") .flat(Type au[]
ccl_device_inline float tan_angle(float3 a, float3 b)
ccl_device_inline float sqr(float a)
ccl_device_inline float3 rotate_around_axis(float3 p, float3 axis, float angle)
ccl_device_inline int clamp(int a, int mn, int mx)