Blender  V2.93
kernel_light.h
Go to the documentation of this file.
1 /*
2  * Copyright 2011-2013 Blender Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
18 
20 
21 /* Light Sample result */
22 
23 typedef struct LightSample {
24  float3 P; /* position on light, or direction for distant light */
25  float3 Ng; /* normal on light */
26  float3 D; /* direction from shading point to light */
27  float t; /* distance to light (FLT_MAX for distant light) */
28  float u, v; /* parametric coordinate on primitive */
29  float pdf; /* light sampling probability density function */
30  float eval_fac; /* intensity multiplier */
31  int object; /* object id for triangle/curve lights */
32  int prim; /* primitive id for triangle/curve lights */
33  int shader; /* shader id */
34  int lamp; /* lamp id */
35  LightType type; /* type of light */
37 
38 /* Regular Light */
39 
41  KernelGlobals *kg, int lamp, float randu, float randv, float3 P, LightSample *ls)
42 {
43  const ccl_global KernelLight *klight = &kernel_tex_fetch(__lights, lamp);
44  LightType type = (LightType)klight->type;
45  ls->type = type;
46  ls->shader = klight->shader_id;
47  ls->object = PRIM_NONE;
48  ls->prim = PRIM_NONE;
49  ls->lamp = lamp;
50  ls->u = randu;
51  ls->v = randv;
52 
53  if (type == LIGHT_DISTANT) {
54  /* distant light */
55  float3 lightD = make_float3(klight->co[0], klight->co[1], klight->co[2]);
56  float3 D = lightD;
57  float radius = klight->distant.radius;
58  float invarea = klight->distant.invarea;
59 
60  if (radius > 0.0f)
61  D = distant_light_sample(D, radius, randu, randv);
62 
63  ls->P = D;
64  ls->Ng = D;
65  ls->D = -D;
66  ls->t = FLT_MAX;
67 
68  float costheta = dot(lightD, D);
69  ls->pdf = invarea / (costheta * costheta * costheta);
70  ls->eval_fac = ls->pdf;
71  }
72 #ifdef __BACKGROUND_MIS__
73  else if (type == LIGHT_BACKGROUND) {
74  /* infinite area light (e.g. light dome or env light) */
75  float3 D = -background_light_sample(kg, P, randu, randv, &ls->pdf);
76 
77  ls->P = D;
78  ls->Ng = D;
79  ls->D = -D;
80  ls->t = FLT_MAX;
81  ls->eval_fac = 1.0f;
82  }
83 #endif
84  else {
85  ls->P = make_float3(klight->co[0], klight->co[1], klight->co[2]);
86 
87  if (type == LIGHT_POINT || type == LIGHT_SPOT) {
88  float radius = klight->spot.radius;
89 
90  if (radius > 0.0f)
91  /* sphere light */
92  ls->P += sphere_light_sample(P, ls->P, radius, randu, randv);
93 
94  ls->D = normalize_len(ls->P - P, &ls->t);
95  ls->Ng = -ls->D;
96 
97  float invarea = klight->spot.invarea;
98  ls->eval_fac = (0.25f * M_1_PI_F) * invarea;
99  ls->pdf = invarea;
100 
101  if (type == LIGHT_SPOT) {
102  /* spot light attenuation */
103  float3 dir = make_float3(klight->spot.dir[0], klight->spot.dir[1], klight->spot.dir[2]);
105  dir, klight->spot.spot_angle, klight->spot.spot_smooth, ls->Ng);
106  if (ls->eval_fac == 0.0f) {
107  return false;
108  }
109  }
110  float2 uv = map_to_sphere(ls->Ng);
111  ls->u = uv.x;
112  ls->v = uv.y;
113 
114  ls->pdf *= lamp_light_pdf(kg, ls->Ng, -ls->D, ls->t);
115  }
116  else {
117  /* area light */
118  float3 axisu = make_float3(
119  klight->area.axisu[0], klight->area.axisu[1], klight->area.axisu[2]);
120  float3 axisv = make_float3(
121  klight->area.axisv[0], klight->area.axisv[1], klight->area.axisv[2]);
122  float3 Ng = make_float3(klight->area.dir[0], klight->area.dir[1], klight->area.dir[2]);
123  float invarea = fabsf(klight->area.invarea);
124  bool is_round = (klight->area.invarea < 0.0f);
125 
126  if (dot(ls->P - P, Ng) > 0.0f) {
127  return false;
128  }
129 
130  float3 inplane;
131 
132  if (is_round) {
133  inplane = ellipse_sample(axisu * 0.5f, axisv * 0.5f, randu, randv);
134  ls->P += inplane;
135  ls->pdf = invarea;
136  }
137  else {
138  inplane = ls->P;
139 
140  float3 sample_axisu = axisu;
141  float3 sample_axisv = axisv;
142 
143  if (klight->area.tan_spread > 0.0f) {
145  P, Ng, &ls->P, &sample_axisu, &sample_axisv, klight->area.tan_spread)) {
146  return false;
147  }
148  }
149 
150  ls->pdf = rect_light_sample(P, &ls->P, sample_axisu, sample_axisv, randu, randv, true);
151  inplane = ls->P - inplane;
152  }
153 
154  ls->u = dot(inplane, axisu) * (1.0f / dot(axisu, axisu)) + 0.5f;
155  ls->v = dot(inplane, axisv) * (1.0f / dot(axisv, axisv)) + 0.5f;
156 
157  ls->Ng = Ng;
158  ls->D = normalize_len(ls->P - P, &ls->t);
159 
160  ls->eval_fac = 0.25f * invarea;
161 
162  if (klight->area.tan_spread > 0.0f) {
163  /* Area Light spread angle attenuation */
165  ls->D, ls->Ng, klight->area.tan_spread, klight->area.normalize_spread);
166  }
167 
168  if (is_round) {
169  ls->pdf *= lamp_light_pdf(kg, Ng, -ls->D, ls->t);
170  }
171  }
172  }
173 
174  ls->pdf *= kernel_data.integrator.pdf_lights;
175 
176  return (ls->pdf > 0.0f);
177 }
178 
180  KernelGlobals *kg, int lamp, float3 P, float3 D, float t, LightSample *ls)
181 {
182  const ccl_global KernelLight *klight = &kernel_tex_fetch(__lights, lamp);
183  LightType type = (LightType)klight->type;
184  ls->type = type;
185  ls->shader = klight->shader_id;
186  ls->object = PRIM_NONE;
187  ls->prim = PRIM_NONE;
188  ls->lamp = lamp;
189  /* todo: missing texture coordinates */
190  ls->u = 0.0f;
191  ls->v = 0.0f;
192 
193  if (!(ls->shader & SHADER_USE_MIS))
194  return false;
195 
196  if (type == LIGHT_DISTANT) {
197  /* distant light */
198  float radius = klight->distant.radius;
199 
200  if (radius == 0.0f)
201  return false;
202  if (t != FLT_MAX)
203  return false;
204 
205  /* a distant light is infinitely far away, but equivalent to a disk
206  * shaped light exactly 1 unit away from the current shading point.
207  *
208  * radius t^2/cos(theta)
209  * <----------> t = sqrt(1^2 + tan(theta)^2)
210  * tan(th) area = radius*radius*pi
211  * <----->
212  * \ | (1 + tan(theta)^2)/cos(theta)
213  * \ | (1 + tan(acos(cos(theta)))^2)/cos(theta)
214  * t \th| 1 simplifies to
215  * \-| 1/(cos(theta)^3)
216  * \| magic!
217  * P
218  */
219 
220  float3 lightD = make_float3(klight->co[0], klight->co[1], klight->co[2]);
221  float costheta = dot(-lightD, D);
222  float cosangle = klight->distant.cosangle;
223 
224  if (costheta < cosangle)
225  return false;
226 
227  ls->P = -D;
228  ls->Ng = -D;
229  ls->D = D;
230  ls->t = FLT_MAX;
231 
232  /* compute pdf */
233  float invarea = klight->distant.invarea;
234  ls->pdf = invarea / (costheta * costheta * costheta);
235  ls->eval_fac = ls->pdf;
236  }
237  else if (type == LIGHT_POINT || type == LIGHT_SPOT) {
238  float3 lightP = make_float3(klight->co[0], klight->co[1], klight->co[2]);
239 
240  float radius = klight->spot.radius;
241 
242  /* sphere light */
243  if (radius == 0.0f)
244  return false;
245 
246  if (!ray_aligned_disk_intersect(P, D, t, lightP, radius, &ls->P, &ls->t)) {
247  return false;
248  }
249 
250  ls->Ng = -D;
251  ls->D = D;
252 
253  float invarea = klight->spot.invarea;
254  ls->eval_fac = (0.25f * M_1_PI_F) * invarea;
255  ls->pdf = invarea;
256 
257  if (type == LIGHT_SPOT) {
258  /* spot light attenuation */
259  float3 dir = make_float3(klight->spot.dir[0], klight->spot.dir[1], klight->spot.dir[2]);
261  dir, klight->spot.spot_angle, klight->spot.spot_smooth, ls->Ng);
262 
263  if (ls->eval_fac == 0.0f)
264  return false;
265  }
266  float2 uv = map_to_sphere(ls->Ng);
267  ls->u = uv.x;
268  ls->v = uv.y;
269 
270  /* compute pdf */
271  if (ls->t != FLT_MAX)
272  ls->pdf *= lamp_light_pdf(kg, ls->Ng, -ls->D, ls->t);
273  }
274  else if (type == LIGHT_AREA) {
275  /* area light */
276  float invarea = fabsf(klight->area.invarea);
277  bool is_round = (klight->area.invarea < 0.0f);
278  if (invarea == 0.0f)
279  return false;
280 
281  float3 axisu = make_float3(
282  klight->area.axisu[0], klight->area.axisu[1], klight->area.axisu[2]);
283  float3 axisv = make_float3(
284  klight->area.axisv[0], klight->area.axisv[1], klight->area.axisv[2]);
285  float3 Ng = make_float3(klight->area.dir[0], klight->area.dir[1], klight->area.dir[2]);
286 
287  /* one sided */
288  if (dot(D, Ng) >= 0.0f)
289  return false;
290 
291  float3 light_P = make_float3(klight->co[0], klight->co[1], klight->co[2]);
292 
293  if (!ray_quad_intersect(
294  P, D, 0.0f, t, light_P, axisu, axisv, Ng, &ls->P, &ls->t, &ls->u, &ls->v, is_round)) {
295  return false;
296  }
297 
298  ls->D = D;
299  ls->Ng = Ng;
300  if (is_round) {
301  ls->pdf = invarea * lamp_light_pdf(kg, Ng, -D, ls->t);
302  }
303  else {
304  float3 sample_axisu = axisu;
305  float3 sample_axisv = axisv;
306 
307  if (klight->area.tan_spread > 0.0f) {
309  P, Ng, &light_P, &sample_axisu, &sample_axisv, klight->area.tan_spread)) {
310  return false;
311  }
312  }
313 
314  ls->pdf = rect_light_sample(P, &light_P, sample_axisu, sample_axisv, 0, 0, false);
315  }
316  ls->eval_fac = 0.25f * invarea;
317 
318  if (klight->area.tan_spread > 0.0f) {
319  /* Area Light spread angle attenuation */
321  ls->D, ls->Ng, klight->area.tan_spread, klight->area.normalize_spread);
322  if (ls->eval_fac == 0.0f) {
323  return false;
324  }
325  }
326  }
327  else {
328  return false;
329  }
330 
331  ls->pdf *= kernel_data.integrator.pdf_lights;
332 
333  return true;
334 }
335 
336 /* Triangle Light */
337 
338 /* returns true if the triangle is has motion blur or an instancing transform applied */
340  KernelGlobals *kg, int object, int prim, float time, float3 V[3])
341 {
342  bool has_motion = false;
343  const int object_flag = kernel_tex_fetch(__object_flag, object);
344 
345  if (object_flag & SD_OBJECT_HAS_VERTEX_MOTION && time >= 0.0f) {
346  motion_triangle_vertices(kg, object, prim, time, V);
347  has_motion = true;
348  }
349  else {
350  triangle_vertices(kg, prim, V);
351  }
352 
353  if (!(object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
354 #ifdef __OBJECT_MOTION__
355  float object_time = (time >= 0.0f) ? time : 0.5f;
356  Transform tfm = object_fetch_transform_motion_test(kg, object, object_time, NULL);
357 #else
359 #endif
360  V[0] = transform_point(&tfm, V[0]);
361  V[1] = transform_point(&tfm, V[1]);
362  V[2] = transform_point(&tfm, V[2]);
363  has_motion = true;
364  }
365  return has_motion;
366 }
367 
369  const float3 Ng,
370  const float3 I,
371  float t)
372 {
373  float pdf = kernel_data.integrator.pdf_triangles;
374  float cos_pi = fabsf(dot(Ng, I));
375 
376  if (cos_pi == 0.0f)
377  return 0.0f;
378 
379  return t * t * pdf / cos_pi;
380 }
381 
382 ccl_device_forceinline float triangle_light_pdf(KernelGlobals *kg, ShaderData *sd, float t)
383 {
384  /* A naive heuristic to decide between costly solid angle sampling
385  * and simple area sampling, comparing the distance to the triangle plane
386  * to the length of the edges of the triangle. */
387 
388  float3 V[3];
389  bool has_motion = triangle_world_space_vertices(kg, sd->object, sd->prim, sd->time, V);
390 
391  const float3 e0 = V[1] - V[0];
392  const float3 e1 = V[2] - V[0];
393  const float3 e2 = V[2] - V[1];
394  const float longest_edge_squared = max(len_squared(e0), max(len_squared(e1), len_squared(e2)));
395  const float3 N = cross(e0, e1);
396  const float distance_to_plane = fabsf(dot(N, sd->I * t)) / dot(N, N);
397 
398  if (longest_edge_squared > distance_to_plane * distance_to_plane) {
399  /* sd contains the point on the light source
400  * calculate Px, the point that we're shading */
401  const float3 Px = sd->P + sd->I * t;
402  const float3 v0_p = V[0] - Px;
403  const float3 v1_p = V[1] - Px;
404  const float3 v2_p = V[2] - Px;
405 
406  const float3 u01 = safe_normalize(cross(v0_p, v1_p));
407  const float3 u02 = safe_normalize(cross(v0_p, v2_p));
408  const float3 u12 = safe_normalize(cross(v1_p, v2_p));
409 
410  const float alpha = fast_acosf(dot(u02, u01));
411  const float beta = fast_acosf(-dot(u01, u12));
412  const float gamma = fast_acosf(dot(u02, u12));
413  const float solid_angle = alpha + beta + gamma - M_PI_F;
414 
415  /* pdf_triangles is calculated over triangle area, but we're not sampling over its area */
416  if (UNLIKELY(solid_angle == 0.0f)) {
417  return 0.0f;
418  }
419  else {
420  float area = 1.0f;
421  if (has_motion) {
422  /* get the center frame vertices, this is what the PDF was calculated from */
423  triangle_world_space_vertices(kg, sd->object, sd->prim, -1.0f, V);
424  area = triangle_area(V[0], V[1], V[2]);
425  }
426  else {
427  area = 0.5f * len(N);
428  }
429  const float pdf = area * kernel_data.integrator.pdf_triangles;
430  return pdf / solid_angle;
431  }
432  }
433  else {
434  float pdf = triangle_light_pdf_area(kg, sd->Ng, sd->I, t);
435  if (has_motion) {
436  const float area = 0.5f * len(N);
437  if (UNLIKELY(area == 0.0f)) {
438  return 0.0f;
439  }
440  /* scale the PDF.
441  * area = the area the sample was taken from
442  * area_pre = the are from which pdf_triangles was calculated from */
443  triangle_world_space_vertices(kg, sd->object, sd->prim, -1.0f, V);
444  const float area_pre = triangle_area(V[0], V[1], V[2]);
445  pdf = pdf * area_pre / area;
446  }
447  return pdf;
448  }
449 }
450 
452  int prim,
453  int object,
454  float randu,
455  float randv,
456  float time,
457  LightSample *ls,
458  const float3 P)
459 {
460  /* A naive heuristic to decide between costly solid angle sampling
461  * and simple area sampling, comparing the distance to the triangle plane
462  * to the length of the edges of the triangle. */
463 
464  float3 V[3];
465  bool has_motion = triangle_world_space_vertices(kg, object, prim, time, V);
466 
467  const float3 e0 = V[1] - V[0];
468  const float3 e1 = V[2] - V[0];
469  const float3 e2 = V[2] - V[1];
470  const float longest_edge_squared = max(len_squared(e0), max(len_squared(e1), len_squared(e2)));
471  const float3 N0 = cross(e0, e1);
472  float Nl = 0.0f;
473  ls->Ng = safe_normalize_len(N0, &Nl);
474  float area = 0.5f * Nl;
475 
476  /* flip normal if necessary */
477  const int object_flag = kernel_tex_fetch(__object_flag, object);
478  if (object_flag & SD_OBJECT_NEGATIVE_SCALE_APPLIED) {
479  ls->Ng = -ls->Ng;
480  }
481  ls->eval_fac = 1.0f;
482  ls->shader = kernel_tex_fetch(__tri_shader, prim);
483  ls->object = object;
484  ls->prim = prim;
485  ls->lamp = LAMP_NONE;
486  ls->shader |= SHADER_USE_MIS;
487  ls->type = LIGHT_TRIANGLE;
488 
489  float distance_to_plane = fabsf(dot(N0, V[0] - P) / dot(N0, N0));
490 
491  if (longest_edge_squared > distance_to_plane * distance_to_plane) {
492  /* see James Arvo, "Stratified Sampling of Spherical Triangles"
493  * http://www.graphics.cornell.edu/pubs/1995/Arv95c.pdf */
494 
495  /* project the triangle to the unit sphere
496  * and calculate its edges and angles */
497  const float3 v0_p = V[0] - P;
498  const float3 v1_p = V[1] - P;
499  const float3 v2_p = V[2] - P;
500 
501  const float3 u01 = safe_normalize(cross(v0_p, v1_p));
502  const float3 u02 = safe_normalize(cross(v0_p, v2_p));
503  const float3 u12 = safe_normalize(cross(v1_p, v2_p));
504 
505  const float3 A = safe_normalize(v0_p);
506  const float3 B = safe_normalize(v1_p);
507  const float3 C = safe_normalize(v2_p);
508 
509  const float cos_alpha = dot(u02, u01);
510  const float cos_beta = -dot(u01, u12);
511  const float cos_gamma = dot(u02, u12);
512 
513  /* calculate dihedral angles */
514  const float alpha = fast_acosf(cos_alpha);
515  const float beta = fast_acosf(cos_beta);
516  const float gamma = fast_acosf(cos_gamma);
517  /* the area of the unit spherical triangle = solid angle */
518  const float solid_angle = alpha + beta + gamma - M_PI_F;
519 
520  /* precompute a few things
521  * these could be re-used to take several samples
522  * as they are independent of randu/randv */
523  const float cos_c = dot(A, B);
524  const float sin_alpha = fast_sinf(alpha);
525  const float product = sin_alpha * cos_c;
526 
527  /* Select a random sub-area of the spherical triangle
528  * and calculate the third vertex C_ of that new triangle */
529  const float phi = randu * solid_angle - alpha;
530  float s, t;
531  fast_sincosf(phi, &s, &t);
532  const float u = t - cos_alpha;
533  const float v = s + product;
534 
535  const float3 U = safe_normalize(C - dot(C, A) * A);
536 
537  float q = 1.0f;
538  const float det = ((v * s + u * t) * sin_alpha);
539  if (det != 0.0f) {
540  q = ((v * t - u * s) * cos_alpha - v) / det;
541  }
542  const float temp = max(1.0f - q * q, 0.0f);
543 
544  const float3 C_ = safe_normalize(q * A + sqrtf(temp) * U);
545 
546  /* Finally, select a random point along the edge of the new triangle
547  * That point on the spherical triangle is the sampled ray direction */
548  const float z = 1.0f - randv * (1.0f - dot(C_, B));
549  ls->D = z * B + safe_sqrtf(1.0f - z * z) * safe_normalize(C_ - dot(C_, B) * B);
550 
551  /* calculate intersection with the planar triangle */
553  ls->D,
554  FLT_MAX,
555 #if defined(__KERNEL_SSE2__) && defined(__KERNEL_SSE__)
556  (ssef *)V,
557 #else
558  V[0],
559  V[1],
560  V[2],
561 #endif
562  &ls->u,
563  &ls->v,
564  &ls->t)) {
565  ls->pdf = 0.0f;
566  return;
567  }
568 
569  ls->P = P + ls->D * ls->t;
570 
571  /* pdf_triangles is calculated over triangle area, but we're sampling over solid angle */
572  if (UNLIKELY(solid_angle == 0.0f)) {
573  ls->pdf = 0.0f;
574  return;
575  }
576  else {
577  if (has_motion) {
578  /* get the center frame vertices, this is what the PDF was calculated from */
579  triangle_world_space_vertices(kg, object, prim, -1.0f, V);
580  area = triangle_area(V[0], V[1], V[2]);
581  }
582  const float pdf = area * kernel_data.integrator.pdf_triangles;
583  ls->pdf = pdf / solid_angle;
584  }
585  }
586  else {
587  /* compute random point in triangle. From Eric Heitz's "A Low-Distortion Map Between Triangle
588  * and Square" */
589  float u = randu;
590  float v = randv;
591  if (v > u) {
592  u *= 0.5f;
593  v -= u;
594  }
595  else {
596  v *= 0.5f;
597  u -= v;
598  }
599 
600  const float t = 1.0f - u - v;
601  ls->P = u * V[0] + v * V[1] + t * V[2];
602  /* compute incoming direction, distance and pdf */
603  ls->D = normalize_len(ls->P - P, &ls->t);
604  ls->pdf = triangle_light_pdf_area(kg, ls->Ng, -ls->D, ls->t);
605  if (has_motion && area != 0.0f) {
606  /* scale the PDF.
607  * area = the area the sample was taken from
608  * area_pre = the are from which pdf_triangles was calculated from */
609  triangle_world_space_vertices(kg, object, prim, -1.0f, V);
610  const float area_pre = triangle_area(V[0], V[1], V[2]);
611  ls->pdf = ls->pdf * area_pre / area;
612  }
613  ls->u = u;
614  ls->v = v;
615  }
616 }
617 
618 /* Light Distribution */
619 
620 ccl_device int light_distribution_sample(KernelGlobals *kg, float *randu)
621 {
622  /* This is basically std::upper_bound as used by PBRT, to find a point light or
623  * triangle to emit from, proportional to area. a good improvement would be to
624  * also sample proportional to power, though it's not so well defined with
625  * arbitrary shaders. */
626  int first = 0;
627  int len = kernel_data.integrator.num_distribution + 1;
628  float r = *randu;
629 
630  do {
631  int half_len = len >> 1;
632  int middle = first + half_len;
633 
634  if (r < kernel_tex_fetch(__light_distribution, middle).totarea) {
635  len = half_len;
636  }
637  else {
638  first = middle + 1;
639  len = len - half_len - 1;
640  }
641  } while (len > 0);
642 
643  /* Clamping should not be needed but float rounding errors seem to
644  * make this fail on rare occasions. */
645  int index = clamp(first - 1, 0, kernel_data.integrator.num_distribution - 1);
646 
647  /* Rescale to reuse random number. this helps the 2D samples within
648  * each area light be stratified as well. */
649  float distr_min = kernel_tex_fetch(__light_distribution, index).totarea;
650  float distr_max = kernel_tex_fetch(__light_distribution, index + 1).totarea;
651  *randu = (r - distr_min) / (distr_max - distr_min);
652 
653  return index;
654 }
655 
656 /* Generic Light */
657 
658 ccl_device_inline bool light_select_reached_max_bounces(KernelGlobals *kg, int index, int bounce)
659 {
660  return (bounce > kernel_tex_fetch(__lights, index).max_bounces);
661 }
662 
663 ccl_device_noinline bool light_sample(KernelGlobals *kg,
664  int lamp,
665  float randu,
666  float randv,
667  float time,
668  float3 P,
669  int bounce,
670  LightSample *ls)
671 {
672  if (lamp < 0) {
673  /* sample index */
674  int index = light_distribution_sample(kg, &randu);
675 
676  /* fetch light data */
677  const ccl_global KernelLightDistribution *kdistribution = &kernel_tex_fetch(
678  __light_distribution, index);
679  int prim = kdistribution->prim;
680 
681  if (prim >= 0) {
682  int object = kdistribution->mesh_light.object_id;
683  int shader_flag = kdistribution->mesh_light.shader_flag;
684 
685  triangle_light_sample(kg, prim, object, randu, randv, time, ls, P);
686  ls->shader |= shader_flag;
687  return (ls->pdf > 0.0f);
688  }
689 
690  lamp = -prim - 1;
691  }
692 
694  return false;
695  }
696 
697  return lamp_light_sample(kg, lamp, randu, randv, P, ls);
698 }
699 
700 ccl_device_inline int light_select_num_samples(KernelGlobals *kg, int index)
701 {
702  return kernel_tex_fetch(__lights, index).samples;
703 }
704 
MINLINE float safe_sqrtf(float a)
void map_to_sphere(float *r_u, float *r_v, const float x, const float y, const float z)
Definition: math_geom.c:5236
#define UNLIKELY(x)
_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:39
ATTR_WARN_UNUSED_RESULT const BMVert * v
#define A
unsigned int U
Definition: btGjkEpa3.h:78
double time
Light lamp
static CCL_NAMESPACE_BEGIN const double alpha
ccl_device_inline void motion_triangle_vertices(KernelGlobals *kg, int object, int prim, float time, float3 verts[3])
@ OBJECT_TRANSFORM
Definition: geom_object.h:30
ccl_device_inline Transform object_fetch_transform(KernelGlobals *kg, int object, enum ObjectTransform type)
Definition: geom_object.h:38
ccl_device_inline void triangle_vertices(KernelGlobals *kg, int prim, float3 P[3])
Definition: geom_triangle.h:70
#define kernel_data
#define kernel_tex_fetch(tex, index)
#define ccl_device_forceinline
#define ccl_device
#define ccl_device_inline
#define ccl_global
#define ccl_device_noinline
#define CCL_NAMESPACE_END
#define fabsf(x)
#define sqrtf(x)
#define make_float3(x, y, z)
ccl_device_inline bool triangle_world_space_vertices(KernelGlobals *kg, int object, int prim, float time, float3 V[3])
Definition: kernel_light.h:339
ccl_device bool lamp_light_eval(KernelGlobals *kg, int lamp, float3 P, float3 D, float t, LightSample *ls)
Definition: kernel_light.h:179
ccl_device_noinline bool light_sample(KernelGlobals *kg, int lamp, float randu, float randv, float time, float3 P, int bounce, LightSample *ls)
Definition: kernel_light.h:663
ccl_device_inline bool lamp_light_sample(KernelGlobals *kg, int lamp, float randu, float randv, float3 P, LightSample *ls)
Definition: kernel_light.h:40
ccl_device_forceinline float triangle_light_pdf(KernelGlobals *kg, ShaderData *sd, float t)
Definition: kernel_light.h:382
ccl_device_inline int light_select_num_samples(KernelGlobals *kg, int index)
Definition: kernel_light.h:700
ccl_device int light_distribution_sample(KernelGlobals *kg, float *randu)
Definition: kernel_light.h:620
CCL_NAMESPACE_BEGIN struct LightSample LightSample
ccl_device_forceinline void triangle_light_sample(KernelGlobals *kg, int prim, int object, float randu, float randv, float time, LightSample *ls, const float3 P)
Definition: kernel_light.h:451
ccl_device_inline float triangle_light_pdf_area(KernelGlobals *kg, const float3 Ng, const float3 I, float t)
Definition: kernel_light.h:368
ccl_device_inline bool light_select_reached_max_bounces(KernelGlobals *kg, int index, int bounce)
Definition: kernel_light.h:658
CCL_NAMESPACE_BEGIN ccl_device_inline float rect_light_sample(float3 P, float3 *light_p, float3 axisu, float3 axisv, float randu, float randv, bool sample_coord)
ccl_device float spot_light_attenuation(float3 dir, float spot_angle, float spot_smooth, float3 N)
ccl_device_inline float3 ellipse_sample(float3 ru, float3 rv, float randu, float randv)
ccl_device float3 distant_light_sample(float3 D, float radius, float randu, float randv)
ccl_device bool light_spread_clamp_area_light(const float3 P, const float3 lightNg, float3 *lightP, float3 *axisu, float3 *axisv, const float tan_spread)
ccl_device float light_spread_attenuation(const float3 D, const float3 lightNg, const float tan_spread, const float normalize_spread)
ccl_device float lamp_light_pdf(KernelGlobals *kg, const float3 Ng, const float3 I, float t)
ccl_device float3 sphere_light_sample(float3 P, float3 center, float radius, float randu, float randv)
#define PRIM_NONE
Definition: kernel_types.h:60
ShaderData
@ SHADER_USE_MIS
Definition: kernel_types.h:584
@ SD_OBJECT_TRANSFORM_APPLIED
Definition: kernel_types.h:908
@ SD_OBJECT_HAS_VERTEX_MOTION
Definition: kernel_types.h:916
@ SD_OBJECT_NEGATIVE_SCALE_APPLIED
Definition: kernel_types.h:910
LightType
Definition: kernel_types.h:599
@ LIGHT_AREA
Definition: kernel_types.h:603
@ LIGHT_DISTANT
Definition: kernel_types.h:601
@ LIGHT_SPOT
Definition: kernel_types.h:604
@ LIGHT_BACKGROUND
Definition: kernel_types.h:602
@ LIGHT_TRIANGLE
Definition: kernel_types.h:605
@ LIGHT_POINT
Definition: kernel_types.h:600
#define LAMP_NONE
Definition: kernel_types.h:61
static float P(float k)
Definition: math_interp.c:41
#define B
static void area(int d1, int d2, int e1, int e2, float weights[2])
#define I
params N
float eval_fac
Definition: kernel_light.h:30
LightType type
Definition: kernel_light.h:35
float max
__forceinline avxf cross(const avxf &a, const avxf &b)
Definition: util_avxf.h:119
ccl_device_inline float triangle_area(const float3 &v1, const float3 &v2, const float3 &v3)
Definition: util_math.h:467
#define M_1_PI_F
Definition: util_math.h:52
#define M_PI_F
Definition: util_math.h:43
ccl_device_inline float beta(float x, float y)
Definition: util_math.h:666
ccl_device_inline int clamp(int a, int mn, int mx)
Definition: util_math.h:283
ccl_device void fast_sincosf(float x, float *sine, float *cosine)
ccl_device float fast_acosf(float x)
ccl_device float fast_sinf(float x)
ccl_device_inline float dot(const float2 &a, const float2 &b)
ccl_device_inline float2 safe_normalize(const float2 &a)
ccl_device_inline float2 normalize_len(const float2 &a, float *t)
ccl_device_inline float3 safe_normalize_len(const float3 a, float *t)
ccl_device_inline float len_squared(const float3 a)
ccl_device bool ray_aligned_disk_intersect(float3 ray_P, float3 ray_D, float ray_t, float3 disk_P, float disk_radius, float3 *isect_P, float *isect_t)
ccl_device bool ray_quad_intersect(float3 ray_P, float3 ray_D, float ray_mint, float ray_maxt, float3 quad_P, float3 quad_u, float3 quad_v, float3 quad_n, float3 *isect_P, float *isect_t, float *isect_u, float *isect_v, bool ellipse)
ccl_device_forceinline bool ray_triangle_intersect(float3 ray_P, float3 ray_dir, float ray_t, const float3 tri_a, const float3 tri_b, const float3 tri_c, float *isect_u, float *isect_v, float *isect_t)
ccl_device_inline float3 transform_point(const Transform *t, const float3 a)
CCL_NAMESPACE_BEGIN struct View V
uint len
BLI_INLINE float D(const float *data, const int res[3], int x, int y, int z)
Definition: voxel.c:29