Blender  V3.3
kernel/light/light.h
Go to the documentation of this file.
1 /* SPDX-License-Identifier: Apache-2.0
2  * Copyright 2011-2022 Blender Foundation */
3 
4 #pragma once
5 
6 #include "kernel/geom/geom.h"
9 
11 
12 /* Light Sample result */
13 
14 typedef struct LightSample {
15  float3 P; /* position on light, or direction for distant light */
16  float3 Ng; /* normal on light */
17  float3 D; /* direction from shading point to light */
18  float t; /* distance to light (FLT_MAX for distant light) */
19  float u, v; /* parametric coordinate on primitive */
20  float pdf; /* light sampling probability density function */
21  float eval_fac; /* intensity multiplier */
22  int object; /* object id for triangle/curve lights */
23  int prim; /* primitive id for triangle/curve lights */
24  int shader; /* shader id */
25  int lamp; /* lamp id */
26  int group; /* lightgroup */
27  LightType type; /* type of light */
29 
30 /* Regular Light */
31 
32 template<bool in_volume_segment>
34  const int lamp,
35  const float randu,
36  const float randv,
37  const float3 P,
38  const uint32_t path_flag,
40 {
41  const ccl_global KernelLight *klight = &kernel_data_fetch(lights, lamp);
42  if (path_flag & PATH_RAY_SHADOW_CATCHER_PASS) {
43  if (klight->shader_id & SHADER_EXCLUDE_SHADOW_CATCHER) {
44  return false;
45  }
46  }
47 
48  LightType type = (LightType)klight->type;
49  ls->type = type;
50  ls->shader = klight->shader_id;
51  ls->object = PRIM_NONE;
52  ls->prim = PRIM_NONE;
53  ls->lamp = lamp;
54  ls->u = randu;
55  ls->v = randv;
56  ls->group = lamp_lightgroup(kg, lamp);
57 
58  if (in_volume_segment && (type == LIGHT_DISTANT || type == LIGHT_BACKGROUND)) {
59  /* Distant lights in a volume get a dummy sample, position will not actually
60  * be used in that case. Only when sampling from a specific scatter position
61  * do we actually need to evaluate these. */
62  ls->P = zero_float3();
63  ls->Ng = zero_float3();
64  ls->D = zero_float3();
65  ls->pdf = 1.0f;
66  ls->t = FLT_MAX;
67  return true;
68  }
69 
70  if (type == LIGHT_DISTANT) {
71  /* distant light */
72  float3 lightD = make_float3(klight->co[0], klight->co[1], klight->co[2]);
73  float3 D = lightD;
74  float radius = klight->distant.radius;
75  float invarea = klight->distant.invarea;
76 
77  if (radius > 0.0f)
78  D = distant_light_sample(D, radius, randu, randv);
79 
80  ls->P = D;
81  ls->Ng = D;
82  ls->D = -D;
83  ls->t = FLT_MAX;
84 
85  float costheta = dot(lightD, D);
86  ls->pdf = invarea / (costheta * costheta * costheta);
87  ls->eval_fac = ls->pdf;
88  }
89 #ifdef __BACKGROUND_MIS__
90  else if (type == LIGHT_BACKGROUND) {
91  /* infinite area light (e.g. light dome or env light) */
92  float3 D = -background_light_sample(kg, P, randu, randv, &ls->pdf);
93 
94  ls->P = D;
95  ls->Ng = D;
96  ls->D = -D;
97  ls->t = FLT_MAX;
98  ls->eval_fac = 1.0f;
99  }
100 #endif
101  else {
102  ls->P = make_float3(klight->co[0], klight->co[1], klight->co[2]);
103 
104  if (type == LIGHT_SPOT) {
105  const float3 center = make_float3(klight->co[0], klight->co[1], klight->co[2]);
106  const float radius = klight->spot.radius;
107  const float3 dir = make_float3(
108  klight->spot.dir[0], klight->spot.dir[1], klight->spot.dir[2]);
109  /* disk oriented normal */
110  const float3 lightN = normalize(P - center);
111  ls->P = center;
112 
113  if (radius > 0.0f)
114  /* disk light */
115  ls->P += disk_light_sample(lightN, randu, randv) * radius;
116 
117  const float invarea = klight->spot.invarea;
118  ls->pdf = invarea;
119 
120  ls->D = normalize_len(ls->P - P, &ls->t);
121  /* we set the light normal to the outgoing direction to support texturing */
122  ls->Ng = -ls->D;
123 
124  ls->eval_fac = (0.25f * M_1_PI_F) * invarea;
125 
126  /* spot light attenuation */
127  ls->eval_fac *= spot_light_attenuation(
128  dir, klight->spot.spot_angle, klight->spot.spot_smooth, -ls->D);
129  if (!in_volume_segment && ls->eval_fac == 0.0f) {
130  return false;
131  }
132 
133  float2 uv = map_to_sphere(ls->Ng);
134  ls->u = uv.x;
135  ls->v = uv.y;
136 
137  ls->pdf *= lamp_light_pdf(kg, lightN, -ls->D, ls->t);
138  }
139  else if (type == LIGHT_POINT) {
140  float3 center = make_float3(klight->co[0], klight->co[1], klight->co[2]);
141  float radius = klight->spot.radius;
142  /* disk oriented normal */
143  const float3 lightN = normalize(P - center);
144  ls->P = center;
145 
146  if (radius > 0.0f) {
147  ls->P += disk_light_sample(lightN, randu, randv) * radius;
148  }
149  ls->pdf = klight->spot.invarea;
150 
151  ls->D = normalize_len(ls->P - P, &ls->t);
152  /* we set the light normal to the outgoing direction to support texturing */
153  ls->Ng = -ls->D;
154 
155  ls->eval_fac = M_1_PI_F * 0.25f * klight->spot.invarea;
156  if (!in_volume_segment && ls->eval_fac == 0.0f) {
157  return false;
158  }
159 
160  float2 uv = map_to_sphere(ls->Ng);
161  ls->u = uv.x;
162  ls->v = uv.y;
163  ls->pdf *= lamp_light_pdf(kg, lightN, -ls->D, ls->t);
164  }
165  else {
166  /* area light */
167  float3 axisu = make_float3(
168  klight->area.axisu[0], klight->area.axisu[1], klight->area.axisu[2]);
169  float3 axisv = make_float3(
170  klight->area.axisv[0], klight->area.axisv[1], klight->area.axisv[2]);
171  float3 Ng = make_float3(klight->area.dir[0], klight->area.dir[1], klight->area.dir[2]);
172  float invarea = fabsf(klight->area.invarea);
173  bool is_round = (klight->area.invarea < 0.0f);
174 
175  if (!in_volume_segment) {
176  if (dot(ls->P - P, Ng) > 0.0f) {
177  return false;
178  }
179  }
180 
181  float3 inplane;
182 
183  if (is_round || in_volume_segment) {
184  inplane = ellipse_sample(axisu * 0.5f, axisv * 0.5f, randu, randv);
185  ls->P += inplane;
186  ls->pdf = invarea;
187  }
188  else {
189  inplane = ls->P;
190 
191  float3 sample_axisu = axisu;
192  float3 sample_axisv = axisv;
193 
194  if (!in_volume_segment && klight->area.tan_spread > 0.0f) {
196  P, Ng, &ls->P, &sample_axisu, &sample_axisv, klight->area.tan_spread)) {
197  return false;
198  }
199  }
200 
201  ls->pdf = rect_light_sample(P, &ls->P, sample_axisu, sample_axisv, randu, randv, true);
202  inplane = ls->P - inplane;
203  }
204 
205  const float light_u = dot(inplane, axisu) * (1.0f / dot(axisu, axisu));
206  const float light_v = dot(inplane, axisv) * (1.0f / dot(axisv, axisv));
207 
208  /* NOTE: Return barycentric coordinates in the same notation as Embree and OptiX. */
209  ls->u = light_v + 0.5f;
210  ls->v = -light_u - light_v;
211 
212  ls->Ng = Ng;
213  ls->D = normalize_len(ls->P - P, &ls->t);
214 
215  ls->eval_fac = 0.25f * invarea;
216 
217  if (klight->area.tan_spread > 0.0f) {
218  /* Area Light spread angle attenuation */
219  ls->eval_fac *= light_spread_attenuation(
220  ls->D, ls->Ng, klight->area.tan_spread, klight->area.normalize_spread);
221  }
222 
223  if (is_round) {
224  ls->pdf *= lamp_light_pdf(kg, Ng, -ls->D, ls->t);
225  }
226  }
227  }
228 
229  ls->pdf *= kernel_data.integrator.pdf_lights;
230 
231  return in_volume_segment || (ls->pdf > 0.0f);
232 }
233 
236  ccl_private const Ray *ccl_restrict ray,
238  const int last_prim,
239  const int last_object,
240  const int last_type,
241  const uint32_t path_flag)
242 {
243  for (int lamp = 0; lamp < kernel_data.integrator.num_all_lights; lamp++) {
244  const ccl_global KernelLight *klight = &kernel_data_fetch(lights, lamp);
245 
246  if (path_flag & PATH_RAY_CAMERA) {
247  if (klight->shader_id & SHADER_EXCLUDE_CAMERA) {
248  continue;
249  }
250  }
251  else {
252  if (!(klight->shader_id & SHADER_USE_MIS)) {
253  continue;
254  }
255 
256 #ifdef __MNEE__
257  /* This path should have been resolved with mnee, it will
258  * generate a firefly for small lights since it is improbable. */
260  klight->use_caustics) {
261  continue;
262  }
263 #endif
264  }
265 
266  if (path_flag & PATH_RAY_SHADOW_CATCHER_PASS) {
267  if (klight->shader_id & SHADER_EXCLUDE_SHADOW_CATCHER) {
268  continue;
269  }
270  }
271 
272  LightType type = (LightType)klight->type;
273  float t = 0.0f, u = 0.0f, v = 0.0f;
274 
275  if (type == LIGHT_SPOT) {
276  /* Spot/Disk light. */
277  const float3 lightP = make_float3(klight->co[0], klight->co[1], klight->co[2]);
278  const float radius = klight->spot.radius;
279  if (radius == 0.0f) {
280  continue;
281  }
282  /* disk oriented normal */
283  const float3 lightN = normalize(ray->P - lightP);
284  /* One sided. */
285  if (dot(ray->D, lightN) >= 0.0f) {
286  continue;
287  }
288 
289  float3 P;
290  if (!ray_disk_intersect(
291  ray->P, ray->D, ray->tmin, ray->tmax, lightP, lightN, radius, &P, &t)) {
292  continue;
293  }
294  }
295  else if (type == LIGHT_POINT) {
296  /* Sphere light (aka, aligned disk light). */
297  const float3 lightP = make_float3(klight->co[0], klight->co[1], klight->co[2]);
298  const float radius = klight->spot.radius;
299  if (radius == 0.0f) {
300  continue;
301  }
302 
303  /* disk oriented normal */
304  const float3 lightN = normalize(ray->P - lightP);
305  float3 P;
306  if (!ray_disk_intersect(
307  ray->P, ray->D, ray->tmin, ray->tmax, lightP, lightN, radius, &P, &t)) {
308  continue;
309  }
310  }
311  else if (type == LIGHT_AREA) {
312  /* Area light. */
313  const float invarea = fabsf(klight->area.invarea);
314  const bool is_round = (klight->area.invarea < 0.0f);
315  if (invarea == 0.0f) {
316  continue;
317  }
318 
319  const float3 axisu = make_float3(
320  klight->area.axisu[0], klight->area.axisu[1], klight->area.axisu[2]);
321  const float3 axisv = make_float3(
322  klight->area.axisv[0], klight->area.axisv[1], klight->area.axisv[2]);
323  const float3 Ng = make_float3(klight->area.dir[0], klight->area.dir[1], klight->area.dir[2]);
324 
325  /* One sided. */
326  if (dot(ray->D, Ng) >= 0.0f) {
327  continue;
328  }
329 
330  const float3 light_P = make_float3(klight->co[0], klight->co[1], klight->co[2]);
331 
332  float3 P;
333  if (!ray_quad_intersect(ray->P,
334  ray->D,
335  ray->tmin,
336  ray->tmax,
337  light_P,
338  axisu,
339  axisv,
340  Ng,
341  &P,
342  &t,
343  &u,
344  &v,
345  is_round)) {
346  continue;
347  }
348  }
349  else {
350  continue;
351  }
352 
353  if (t < isect->t &&
354  !(last_prim == lamp && last_object == OBJECT_NONE && last_type == PRIMITIVE_LAMP)) {
355  isect->t = t;
356  isect->u = u;
357  isect->v = v;
358  isect->type = PRIMITIVE_LAMP;
359  isect->prim = lamp;
360  isect->object = OBJECT_NONE;
361  }
362  }
363 
364  return isect->prim != PRIM_NONE;
365 }
366 
368  const float3 ray_D,
369  const int lamp,
371 {
372  ccl_global const KernelLight *klight = &kernel_data_fetch(lights, lamp);
373  const int shader = klight->shader_id;
374  const float radius = klight->distant.radius;
375  const LightType type = (LightType)klight->type;
376 
377  if (type != LIGHT_DISTANT) {
378  return false;
379  }
380  if (!(shader & SHADER_USE_MIS)) {
381  return false;
382  }
383  if (radius == 0.0f) {
384  return false;
385  }
386 
387  /* a distant light is infinitely far away, but equivalent to a disk
388  * shaped light exactly 1 unit away from the current shading point.
389  *
390  * radius t^2/cos(theta)
391  * <----------> t = sqrt(1^2 + tan(theta)^2)
392  * tan(th) area = radius*radius*pi
393  * <----->
394  * \ | (1 + tan(theta)^2)/cos(theta)
395  * \ | (1 + tan(acos(cos(theta)))^2)/cos(theta)
396  * t \th| 1 simplifies to
397  * \-| 1/(cos(theta)^3)
398  * \| magic!
399  * P
400  */
401 
402  float3 lightD = make_float3(klight->co[0], klight->co[1], klight->co[2]);
403  float costheta = dot(-lightD, ray_D);
404  float cosangle = klight->distant.cosangle;
405 
406  /* Workaround to prevent a hang in the classroom scene with AMD HIP drivers 22.10,
407  * Remove when a compiler fix is available. */
408 #ifdef __HIP__
409  ls->shader = klight->shader_id;
410 #endif
411 
412  if (costheta < cosangle)
413  return false;
414 
415  ls->type = type;
416 #ifndef __HIP__
417  ls->shader = klight->shader_id;
418 #endif
419  ls->object = PRIM_NONE;
420  ls->prim = PRIM_NONE;
421  ls->lamp = lamp;
422  /* todo: missing texture coordinates */
423  ls->u = 0.0f;
424  ls->v = 0.0f;
425  ls->t = FLT_MAX;
426  ls->P = -ray_D;
427  ls->Ng = -ray_D;
428  ls->D = ray_D;
429  ls->group = lamp_lightgroup(kg, lamp);
430 
431  /* compute pdf */
432  float invarea = klight->distant.invarea;
433  ls->pdf = invarea / (costheta * costheta * costheta);
434  ls->eval_fac = ls->pdf;
435  ls->pdf *= kernel_data.integrator.pdf_lights;
436 
437  return true;
438 }
439 
442  const float3 ray_P,
443  const float3 ray_D,
445 {
446  const int lamp = isect->prim;
447  ccl_global const KernelLight *klight = &kernel_data_fetch(lights, lamp);
448  LightType type = (LightType)klight->type;
449  ls->type = type;
450  ls->shader = klight->shader_id;
451  ls->object = isect->object;
452  ls->prim = isect->prim;
453  ls->lamp = lamp;
454  /* todo: missing texture coordinates */
455  ls->t = isect->t;
456  ls->P = ray_P + ray_D * ls->t;
457  ls->D = ray_D;
458  ls->group = lamp_lightgroup(kg, lamp);
459 
460  if (type == LIGHT_SPOT) {
461  const float3 center = make_float3(klight->co[0], klight->co[1], klight->co[2]);
462  const float3 dir = make_float3(klight->spot.dir[0], klight->spot.dir[1], klight->spot.dir[2]);
463  /* the normal of the oriented disk */
464  const float3 lightN = normalize(ray_P - center);
465  /* We set the light normal to the outgoing direction to support texturing. */
466  ls->Ng = -ls->D;
467 
468  float invarea = klight->spot.invarea;
469  ls->eval_fac = (0.25f * M_1_PI_F) * invarea;
470  ls->pdf = invarea;
471 
472  /* spot light attenuation */
473  ls->eval_fac *= spot_light_attenuation(
474  dir, klight->spot.spot_angle, klight->spot.spot_smooth, -ls->D);
475 
476  if (ls->eval_fac == 0.0f) {
477  return false;
478  }
479 
480  float2 uv = map_to_sphere(ls->Ng);
481  ls->u = uv.x;
482  ls->v = uv.y;
483 
484  /* compute pdf */
485  if (ls->t != FLT_MAX)
486  ls->pdf *= lamp_light_pdf(kg, lightN, -ls->D, ls->t);
487  else
488  ls->pdf = 0.f;
489  }
490  else if (type == LIGHT_POINT) {
491  const float3 center = make_float3(klight->co[0], klight->co[1], klight->co[2]);
492  const float3 lighN = normalize(ray_P - center);
493 
494  /* We set the light normal to the outgoing direction to support texturing. */
495  ls->Ng = -ls->D;
496 
497  float invarea = klight->spot.invarea;
498  ls->eval_fac = (0.25f * M_1_PI_F) * invarea;
499  ls->pdf = invarea;
500 
501  if (ls->eval_fac == 0.0f) {
502  return false;
503  }
504 
505  float2 uv = map_to_sphere(ls->Ng);
506  ls->u = uv.x;
507  ls->v = uv.y;
508 
509  /* compute pdf */
510  if (ls->t != FLT_MAX)
511  ls->pdf *= lamp_light_pdf(kg, lighN, -ls->D, ls->t);
512  else
513  ls->pdf = 0.f;
514  }
515  else if (type == LIGHT_AREA) {
516  /* area light */
517  float invarea = fabsf(klight->area.invarea);
518 
519  float3 axisu = make_float3(
520  klight->area.axisu[0], klight->area.axisu[1], klight->area.axisu[2]);
521  float3 axisv = make_float3(
522  klight->area.axisv[0], klight->area.axisv[1], klight->area.axisv[2]);
523  float3 Ng = make_float3(klight->area.dir[0], klight->area.dir[1], klight->area.dir[2]);
524  float3 light_P = make_float3(klight->co[0], klight->co[1], klight->co[2]);
525 
526  ls->u = isect->u;
527  ls->v = isect->v;
528  ls->D = ray_D;
529  ls->Ng = Ng;
530 
531  const bool is_round = (klight->area.invarea < 0.0f);
532  if (is_round) {
533  ls->pdf = invarea * lamp_light_pdf(kg, Ng, -ray_D, ls->t);
534  }
535  else {
536  float3 sample_axisu = axisu;
537  float3 sample_axisv = axisv;
538 
539  if (klight->area.tan_spread > 0.0f) {
541  ray_P, Ng, &light_P, &sample_axisu, &sample_axisv, klight->area.tan_spread)) {
542  return false;
543  }
544  }
545 
546  ls->pdf = rect_light_sample(ray_P, &light_P, sample_axisu, sample_axisv, 0, 0, false);
547  }
548  ls->eval_fac = 0.25f * invarea;
549 
550  if (klight->area.tan_spread > 0.0f) {
551  /* Area Light spread angle attenuation */
552  ls->eval_fac *= light_spread_attenuation(
553  ls->D, ls->Ng, klight->area.tan_spread, klight->area.normalize_spread);
554  if (ls->eval_fac == 0.0f) {
555  return false;
556  }
557  }
558  }
559  else {
560  kernel_assert(!"Invalid lamp type in light_sample_from_intersection");
561  return false;
562  }
563 
564  ls->pdf *= kernel_data.integrator.pdf_lights;
565 
566  return true;
567 }
568 
569 /* Triangle Light */
570 
571 /* returns true if the triangle is has motion blur or an instancing transform applied */
573  KernelGlobals kg, int object, int prim, float time, float3 V[3])
574 {
575  bool has_motion = false;
576  const int object_flag = kernel_data_fetch(object_flag, object);
577 
578  if (object_flag & SD_OBJECT_HAS_VERTEX_MOTION && time >= 0.0f) {
579  motion_triangle_vertices(kg, object, prim, time, V);
580  has_motion = true;
581  }
582  else {
583  triangle_vertices(kg, prim, V);
584  }
585 
586  if (!(object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
587 #ifdef __OBJECT_MOTION__
588  float object_time = (time >= 0.0f) ? time : 0.5f;
589  Transform tfm = object_fetch_transform_motion_test(kg, object, object_time, NULL);
590 #else
592 #endif
593  V[0] = transform_point(&tfm, V[0]);
594  V[1] = transform_point(&tfm, V[1]);
595  V[2] = transform_point(&tfm, V[2]);
596  has_motion = true;
597  }
598  return has_motion;
599 }
600 
602  const float3 Ng,
603  const float3 I,
604  float t)
605 {
606  float pdf = kernel_data.integrator.pdf_triangles;
607  float cos_pi = fabsf(dot(Ng, I));
608 
609  if (cos_pi == 0.0f)
610  return 0.0f;
611 
612  return t * t * pdf / cos_pi;
613 }
614 
616  ccl_private const ShaderData *sd,
617  float t)
618 {
619  /* A naive heuristic to decide between costly solid angle sampling
620  * and simple area sampling, comparing the distance to the triangle plane
621  * to the length of the edges of the triangle. */
622 
623  float3 V[3];
624  bool has_motion = triangle_world_space_vertices(kg, sd->object, sd->prim, sd->time, V);
625 
626  const float3 e0 = V[1] - V[0];
627  const float3 e1 = V[2] - V[0];
628  const float3 e2 = V[2] - V[1];
629  const float longest_edge_squared = max(len_squared(e0), max(len_squared(e1), len_squared(e2)));
630  const float3 N = cross(e0, e1);
631  const float distance_to_plane = fabsf(dot(N, sd->I * t)) / dot(N, N);
632 
633  if (longest_edge_squared > distance_to_plane * distance_to_plane) {
634  /* sd contains the point on the light source
635  * calculate Px, the point that we're shading */
636  const float3 Px = sd->P + sd->I * t;
637  const float3 v0_p = V[0] - Px;
638  const float3 v1_p = V[1] - Px;
639  const float3 v2_p = V[2] - Px;
640 
641  const float3 u01 = safe_normalize(cross(v0_p, v1_p));
642  const float3 u02 = safe_normalize(cross(v0_p, v2_p));
643  const float3 u12 = safe_normalize(cross(v1_p, v2_p));
644 
645  const float alpha = fast_acosf(dot(u02, u01));
646  const float beta = fast_acosf(-dot(u01, u12));
647  const float gamma = fast_acosf(dot(u02, u12));
648  const float solid_angle = alpha + beta + gamma - M_PI_F;
649 
650  /* pdf_triangles is calculated over triangle area, but we're not sampling over its area */
651  if (UNLIKELY(solid_angle == 0.0f)) {
652  return 0.0f;
653  }
654  else {
655  float area = 1.0f;
656  if (has_motion) {
657  /* get the center frame vertices, this is what the PDF was calculated from */
658  triangle_world_space_vertices(kg, sd->object, sd->prim, -1.0f, V);
659  area = triangle_area(V[0], V[1], V[2]);
660  }
661  else {
662  area = 0.5f * len(N);
663  }
664  const float pdf = area * kernel_data.integrator.pdf_triangles;
665  return pdf / solid_angle;
666  }
667  }
668  else {
669  float pdf = triangle_light_pdf_area(kg, sd->Ng, sd->I, t);
670  if (has_motion) {
671  const float area = 0.5f * len(N);
672  if (UNLIKELY(area == 0.0f)) {
673  return 0.0f;
674  }
675  /* scale the PDF.
676  * area = the area the sample was taken from
677  * area_pre = the are from which pdf_triangles was calculated from */
678  triangle_world_space_vertices(kg, sd->object, sd->prim, -1.0f, V);
679  const float area_pre = triangle_area(V[0], V[1], V[2]);
680  pdf = pdf * area_pre / area;
681  }
682  return pdf;
683  }
684 }
685 
686 template<bool in_volume_segment>
688  int prim,
689  int object,
690  float randu,
691  float randv,
692  float time,
694  const float3 P)
695 {
696  /* A naive heuristic to decide between costly solid angle sampling
697  * and simple area sampling, comparing the distance to the triangle plane
698  * to the length of the edges of the triangle. */
699 
700  float3 V[3];
701  bool has_motion = triangle_world_space_vertices(kg, object, prim, time, V);
702 
703  const float3 e0 = V[1] - V[0];
704  const float3 e1 = V[2] - V[0];
705  const float3 e2 = V[2] - V[1];
706  const float longest_edge_squared = max(len_squared(e0), max(len_squared(e1), len_squared(e2)));
707  const float3 N0 = cross(e0, e1);
708  float Nl = 0.0f;
709  ls->Ng = safe_normalize_len(N0, &Nl);
710  float area = 0.5f * Nl;
711 
712  /* flip normal if necessary */
713  const int object_flag = kernel_data_fetch(object_flag, object);
714  if (object_flag & SD_OBJECT_NEGATIVE_SCALE_APPLIED) {
715  ls->Ng = -ls->Ng;
716  }
717  ls->eval_fac = 1.0f;
718  ls->shader = kernel_data_fetch(tri_shader, prim);
719  ls->object = object;
720  ls->prim = prim;
721  ls->lamp = LAMP_NONE;
722  ls->shader |= SHADER_USE_MIS;
723  ls->type = LIGHT_TRIANGLE;
724  ls->group = object_lightgroup(kg, object);
725 
726  float distance_to_plane = fabsf(dot(N0, V[0] - P) / dot(N0, N0));
727 
728  if (!in_volume_segment && (longest_edge_squared > distance_to_plane * distance_to_plane)) {
729  /* see James Arvo, "Stratified Sampling of Spherical Triangles"
730  * http://www.graphics.cornell.edu/pubs/1995/Arv95c.pdf */
731 
732  /* project the triangle to the unit sphere
733  * and calculate its edges and angles */
734  const float3 v0_p = V[0] - P;
735  const float3 v1_p = V[1] - P;
736  const float3 v2_p = V[2] - P;
737 
738  const float3 u01 = safe_normalize(cross(v0_p, v1_p));
739  const float3 u02 = safe_normalize(cross(v0_p, v2_p));
740  const float3 u12 = safe_normalize(cross(v1_p, v2_p));
741 
742  const float3 A = safe_normalize(v0_p);
743  const float3 B = safe_normalize(v1_p);
744  const float3 C = safe_normalize(v2_p);
745 
746  const float cos_alpha = dot(u02, u01);
747  const float cos_beta = -dot(u01, u12);
748  const float cos_gamma = dot(u02, u12);
749 
750  /* calculate dihedral angles */
751  const float alpha = fast_acosf(cos_alpha);
752  const float beta = fast_acosf(cos_beta);
753  const float gamma = fast_acosf(cos_gamma);
754  /* the area of the unit spherical triangle = solid angle */
755  const float solid_angle = alpha + beta + gamma - M_PI_F;
756 
757  /* precompute a few things
758  * these could be re-used to take several samples
759  * as they are independent of randu/randv */
760  const float cos_c = dot(A, B);
761  const float sin_alpha = fast_sinf(alpha);
762  const float product = sin_alpha * cos_c;
763 
764  /* Select a random sub-area of the spherical triangle
765  * and calculate the third vertex C_ of that new triangle */
766  const float phi = randu * solid_angle - alpha;
767  float s, t;
768  fast_sincosf(phi, &s, &t);
769  const float u = t - cos_alpha;
770  const float v = s + product;
771 
772  const float3 U = safe_normalize(C - dot(C, A) * A);
773 
774  float q = 1.0f;
775  const float det = ((v * s + u * t) * sin_alpha);
776  if (det != 0.0f) {
777  q = ((v * t - u * s) * cos_alpha - v) / det;
778  }
779  const float temp = max(1.0f - q * q, 0.0f);
780 
781  const float3 C_ = safe_normalize(q * A + sqrtf(temp) * U);
782 
783  /* Finally, select a random point along the edge of the new triangle
784  * That point on the spherical triangle is the sampled ray direction */
785  const float z = 1.0f - randv * (1.0f - dot(C_, B));
786  ls->D = z * B + safe_sqrtf(1.0f - z * z) * safe_normalize(C_ - dot(C_, B) * B);
787 
788  /* calculate intersection with the planar triangle */
790  P, ls->D, 0.0f, FLT_MAX, V[0], V[1], V[2], &ls->u, &ls->v, &ls->t)) {
791  ls->pdf = 0.0f;
792  return;
793  }
794 
795  ls->P = P + ls->D * ls->t;
796 
797  /* pdf_triangles is calculated over triangle area, but we're sampling over solid angle */
798  if (UNLIKELY(solid_angle == 0.0f)) {
799  ls->pdf = 0.0f;
800  return;
801  }
802  else {
803  if (has_motion) {
804  /* get the center frame vertices, this is what the PDF was calculated from */
805  triangle_world_space_vertices(kg, object, prim, -1.0f, V);
806  area = triangle_area(V[0], V[1], V[2]);
807  }
808  const float pdf = area * kernel_data.integrator.pdf_triangles;
809  ls->pdf = pdf / solid_angle;
810  }
811  }
812  else {
813  /* compute random point in triangle. From Eric Heitz's "A Low-Distortion Map Between Triangle
814  * and Square" */
815  float u = randu;
816  float v = randv;
817  if (v > u) {
818  u *= 0.5f;
819  v -= u;
820  }
821  else {
822  v *= 0.5f;
823  u -= v;
824  }
825 
826  const float t = 1.0f - u - v;
827  ls->P = u * V[0] + v * V[1] + t * V[2];
828  /* compute incoming direction, distance and pdf */
829  ls->D = normalize_len(ls->P - P, &ls->t);
830  ls->pdf = triangle_light_pdf_area(kg, ls->Ng, -ls->D, ls->t);
831  if (has_motion && area != 0.0f) {
832  /* scale the PDF.
833  * area = the area the sample was taken from
834  * area_pre = the are from which pdf_triangles was calculated from */
835  triangle_world_space_vertices(kg, object, prim, -1.0f, V);
836  const float area_pre = triangle_area(V[0], V[1], V[2]);
837  ls->pdf = ls->pdf * area_pre / area;
838  }
839  ls->u = u;
840  ls->v = v;
841  }
842 }
843 
844 /* Light Distribution */
845 
847 {
848  /* This is basically std::upper_bound as used by PBRT, to find a point light or
849  * triangle to emit from, proportional to area. a good improvement would be to
850  * also sample proportional to power, though it's not so well defined with
851  * arbitrary shaders. */
852  int first = 0;
853  int len = kernel_data.integrator.num_distribution + 1;
854  float r = *randu;
855 
856  do {
857  int half_len = len >> 1;
858  int middle = first + half_len;
859 
860  if (r < kernel_data_fetch(light_distribution, middle).totarea) {
861  len = half_len;
862  }
863  else {
864  first = middle + 1;
865  len = len - half_len - 1;
866  }
867  } while (len > 0);
868 
869  /* Clamping should not be needed but float rounding errors seem to
870  * make this fail on rare occasions. */
871  int index = clamp(first - 1, 0, kernel_data.integrator.num_distribution - 1);
872 
873  /* Rescale to reuse random number. this helps the 2D samples within
874  * each area light be stratified as well. */
875  float distr_min = kernel_data_fetch(light_distribution, index).totarea;
876  float distr_max = kernel_data_fetch(light_distribution, index + 1).totarea;
877  *randu = (r - distr_min) / (distr_max - distr_min);
878 
879  return index;
880 }
881 
882 /* Generic Light */
883 
885 {
886  return (bounce > kernel_data_fetch(lights, index).max_bounces);
887 }
888 
889 template<bool in_volume_segment>
891  float randu,
892  const float randv,
893  const float time,
894  const float3 P,
895  const int bounce,
896  const uint32_t path_flag,
898 {
899  /* Sample light index from distribution. */
900  const int index = light_distribution_sample(kg, &randu);
901  ccl_global const KernelLightDistribution *kdistribution = &kernel_data_fetch(light_distribution,
902  index);
903  const int prim = kdistribution->prim;
904 
905  if (prim >= 0) {
906  /* Mesh light. */
907  const int object = kdistribution->mesh_light.object_id;
908 
909  /* Exclude synthetic meshes from shadow catcher pass. */
910  if ((path_flag & PATH_RAY_SHADOW_CATCHER_PASS) &&
911  !(kernel_data_fetch(object_flag, object) & SD_OBJECT_SHADOW_CATCHER)) {
912  return false;
913  }
914 
915  const int shader_flag = kdistribution->mesh_light.shader_flag;
916  triangle_light_sample<in_volume_segment>(kg, prim, object, randu, randv, time, ls, P);
917  ls->shader |= shader_flag;
918  return (ls->pdf > 0.0f);
919  }
920 
921  const int lamp = -prim - 1;
922 
923  if (UNLIKELY(light_select_reached_max_bounces(kg, lamp, bounce))) {
924  return false;
925  }
926 
927  return light_sample<in_volume_segment>(kg, lamp, randu, randv, P, path_flag, ls);
928 }
929 
931  float randu,
932  const float randv,
933  const float time,
934  const float3 P,
935  const int bounce,
936  const uint32_t path_flag,
938 {
939  return light_distribution_sample<true>(kg, randu, randv, time, P, bounce, path_flag, ls);
940 }
941 
943  float randu,
944  const float randv,
945  const float time,
946  const float3 P,
947  const int bounce,
948  const uint32_t path_flag,
950 {
951  return light_distribution_sample<false>(kg, randu, randv, time, P, bounce, path_flag, ls);
952 }
953 
955  const float randu,
956  const float randv,
957  const float time,
958  const float3 P,
960 {
961  /* Sample a new position on the same light, for volume sampling. */
962  if (ls->type == LIGHT_TRIANGLE) {
963  triangle_light_sample<false>(kg, ls->prim, ls->object, randu, randv, time, ls, P);
964  return (ls->pdf > 0.0f);
965  }
966  else {
967  return light_sample<false>(kg, ls->lamp, randu, randv, P, 0, ls);
968  }
969 }
970 
MINLINE float safe_sqrtf(float a)
void map_to_sphere(float *r_u, float *r_v, float x, float y, float z)
Definition: math_geom.c:4932
#define UNLIKELY(x)
NSNotificationCenter * center
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble z
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble GLdouble r _GL_VOID_RET _GL_VOID GLfloat GLfloat r _GL_VOID_RET _GL_VOID GLint GLint r _GL_VOID_RET _GL_VOID GLshort GLshort r _GL_VOID_RET _GL_VOID GLdouble GLdouble r
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble t
#define C
Definition: RandGen.cpp:25
ATTR_WARN_UNUSED_RESULT const BMVert * v
#define A
unsigned int U
Definition: btGjkEpa3.h:78
ccl_device float spot_light_attenuation(float3 dir, float spot_angle, float spot_smooth, float3 N)
Definition: common.h:123
ccl_device float3 disk_light_sample(float3 v, float randu, float randv)
Definition: common.h:103
ccl_device bool light_spread_clamp_area_light(const float3 P, const float3 lightNg, ccl_private float3 *lightP, ccl_private float3 *axisu, ccl_private float3 *axisv, const float tan_spread)
Definition: common.h:155
ccl_device_inline float3 ellipse_sample(float3 ru, float3 rv, float randu, float randv)
Definition: common.h:97
ccl_device float3 distant_light_sample(float3 D, float radius, float randu, float randv)
Definition: common.h:112
ccl_device float light_spread_attenuation(const float3 D, const float3 lightNg, const float tan_spread, const float normalize_spread)
Definition: common.h:140
ccl_device float lamp_light_pdf(KernelGlobals kg, const float3 Ng, const float3 I, float t)
Definition: common.h:204
CCL_NAMESPACE_BEGIN ccl_device_inline float rect_light_sample(float3 P, ccl_private float3 *light_p, float3 axisu, float3 axisv, float randu, float randv, bool sample_coord)
Definition: common.h:21
#define kernel_assert(cond)
Definition: cpu/compat.h:34
#define ccl_restrict
Definition: cuda/compat.h:50
#define ccl_device_forceinline
Definition: cuda/compat.h:35
#define ccl_device
Definition: cuda/compat.h:32
#define ccl_private
Definition: cuda/compat.h:48
#define ccl_device_inline
Definition: cuda/compat.h:34
#define ccl_global
Definition: cuda/compat.h:43
#define ccl_device_noinline
Definition: cuda/compat.h:40
#define CCL_NAMESPACE_END
Definition: cuda/compat.h:9
double time
Light lamp
#define kernel_data
const KernelGlobalsCPU *ccl_restrict KernelGlobals
#define kernel_data_fetch(name, index)
int len
Definition: draw_manager.c:108
CCL_NAMESPACE_END CCL_NAMESPACE_BEGIN ccl_device_inline float3 transform_point(ccl_private const Transform *t, const float3 a)
const int state
@ OBJECT_TRANSFORM
ccl_device_inline Transform object_fetch_transform(KernelGlobals kg, int object, enum ObjectTransform type)
ccl_device_inline int lamp_lightgroup(KernelGlobals kg, int lamp)
ccl_device_inline int object_lightgroup(KernelGlobals kg, int object)
ccl_device int light_distribution_sample(KernelGlobals kg, ccl_private float *randu)
ccl_device bool light_sample_from_distant_ray(KernelGlobals kg, const float3 ray_D, const int lamp, ccl_private LightSample *ccl_restrict ls)
ccl_device bool lights_intersect(KernelGlobals kg, IntegratorState state, ccl_private const Ray *ccl_restrict ray, ccl_private Intersection *ccl_restrict isect, const int last_prim, const int last_object, const int last_type, const uint32_t path_flag)
ccl_device_inline bool triangle_world_space_vertices(KernelGlobals kg, int object, int prim, float time, float3 V[3])
ccl_device_inline bool light_sample(KernelGlobals kg, const int lamp, const float randu, const float randv, const float3 P, const uint32_t path_flag, ccl_private LightSample *ls)
ccl_device_inline bool light_distribution_sample_from_volume_segment(KernelGlobals kg, float randu, const float randv, const float time, const float3 P, const int bounce, const uint32_t path_flag, ccl_private LightSample *ls)
ccl_device_inline bool light_distribution_sample_from_position(KernelGlobals kg, float randu, const float randv, const float time, const float3 P, const int bounce, const uint32_t path_flag, ccl_private LightSample *ls)
ccl_device_forceinline void triangle_light_sample(KernelGlobals kg, int prim, int object, float randu, float randv, float time, ccl_private LightSample *ls, const float3 P)
ccl_device bool light_sample_from_intersection(KernelGlobals kg, ccl_private const Intersection *ccl_restrict isect, const float3 ray_P, const float3 ray_D, ccl_private LightSample *ccl_restrict ls)
CCL_NAMESPACE_BEGIN struct LightSample LightSample
ccl_device_inline bool light_select_reached_max_bounces(KernelGlobals kg, int index, int bounce)
ccl_device_inline float triangle_light_pdf_area(KernelGlobals kg, const float3 Ng, const float3 I, float t)
ccl_device_forceinline float triangle_light_pdf(KernelGlobals kg, ccl_private const ShaderData *sd, float t)
ccl_device_inline bool light_distribution_sample_new_position(KernelGlobals kg, const float randu, const float randv, const float time, const float3 P, ccl_private LightSample *ls)
@ PATH_MNEE_CULL_LIGHT_CONNECTION
Definition: kernel/types.h:295
@ PRIMITIVE_LAMP
Definition: kernel/types.h:556
#define PRIM_NONE
Definition: kernel/types.h:41
@ PATH_RAY_SHADOW_CATCHER_PASS
Definition: kernel/types.h:285
@ PATH_RAY_CAMERA
Definition: kernel/types.h:194
#define OBJECT_NONE
Definition: kernel/types.h:40
ShaderData
Definition: kernel/types.h:925
@ SHADER_EXCLUDE_SHADOW_CATCHER
Definition: kernel/types.h:444
@ SHADER_EXCLUDE_CAMERA
Definition: kernel/types.h:442
@ SHADER_USE_MIS
Definition: kernel/types.h:438
@ SD_OBJECT_SHADOW_CATCHER
Definition: kernel/types.h:818
@ SD_OBJECT_TRANSFORM_APPLIED
Definition: kernel/types.h:808
@ SD_OBJECT_HAS_VERTEX_MOTION
Definition: kernel/types.h:816
@ SD_OBJECT_NEGATIVE_SCALE_APPLIED
Definition: kernel/types.h:810
LightType
Definition: kernel/types.h:455
@ LIGHT_AREA
Definition: kernel/types.h:459
@ LIGHT_DISTANT
Definition: kernel/types.h:457
@ LIGHT_SPOT
Definition: kernel/types.h:460
@ LIGHT_BACKGROUND
Definition: kernel/types.h:458
@ LIGHT_TRIANGLE
Definition: kernel/types.h:461
@ LIGHT_POINT
Definition: kernel/types.h:456
#define LAMP_NONE
Definition: kernel/types.h:42
ccl_device void fast_sincosf(float x, ccl_private float *sine, ccl_private float *cosine)
Definition: math_fast.h:134
ccl_device float fast_acosf(float x)
Definition: math_fast.h:253
ccl_device float fast_sinf(float x)
Definition: math_fast.h:70
ccl_device_inline float2 safe_normalize(const float2 &a)
Definition: math_float2.h:201
ccl_device_inline float2 normalize_len(const float2 &a, float *t)
ccl_device_inline float3 zero_float3()
Definition: math_float3.h:80
ccl_device_inline float3 safe_normalize_len(const float3 a, ccl_private float *t)
Definition: math_float3.h:471
ccl_device_inline float len_squared(const float3 a)
Definition: math_float3.h:423
static float P(float k)
Definition: math_interp.c:25
ccl_device bool ray_disk_intersect(float3 ray_P, float3 ray_D, float ray_tmin, float ray_tmax, float3 disk_P, float3 disk_N, float disk_radius, ccl_private float3 *isect_P, ccl_private float *isect_t)
ccl_device bool ray_quad_intersect(float3 ray_P, float3 ray_D, float ray_tmin, float ray_tmax, float3 quad_P, float3 quad_u, float3 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_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)
#define N
#define B
#define fabsf(x)
Definition: metal/compat.h:219
#define sqrtf(x)
Definition: metal/compat.h:243
#define make_float3(x, y, z)
Definition: metal/compat.h:204
ccl_device_inline void motion_triangle_vertices(KernelGlobals kg, int object, int prim, float time, float3 verts[3])
static void area(int d1, int d2, int e1, int e2, float weights[2])
T dot(const vec_base< T, Size > &a, const vec_base< T, Size > &b)
vec_base< T, 3 > cross(const vec_base< T, 3 > &a, const vec_base< T, 3 > &b)
T clamp(const T &a, const T &min, const T &max)
vec_base< T, Size > normalize(const vec_base< T, Size > &v)
#define I
IntegratorStateCPU *ccl_restrict IntegratorState
Definition: state.h:147
#define INTEGRATOR_STATE(state, nested_struct, member)
Definition: state.h:154
unsigned int uint32_t
Definition: stdint.h:80
float x
Definition: types_float2.h:15
float y
Definition: types_float2.h:15
float max
ccl_device_inline void triangle_vertices(KernelGlobals kg, int prim, float3 P[3])
Definition: triangle.h:65
ccl_device_inline float triangle_area(ccl_private const float3 &v1, ccl_private const float3 &v2, ccl_private const float3 &v3)
Definition: util/math.h:557
#define M_1_PI_F
Definition: util/math.h:43
#define M_PI_F
Definition: util/math.h:34
ccl_device_inline float beta(float x, float y)
Definition: util/math.h:775
BLI_INLINE float D(const float *data, const int res[3], int x, int y, int z)
Definition: voxel.c:13
CCL_NAMESPACE_BEGIN struct Window V