Blender  V3.3
kernel/light/background.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/light/common.h"
7 
9 
10 /* Background Light */
11 
12 #ifdef __BACKGROUND_MIS__
13 
14 ccl_device float3 background_map_sample(KernelGlobals kg,
15  float randu,
16  float randv,
17  ccl_private float *pdf)
18 {
19  /* for the following, the CDF values are actually a pair of floats, with the
20  * function value as X and the actual CDF as Y. The last entry's function
21  * value is the CDF total. */
22  int res_x = kernel_data.background.map_res_x;
23  int res_y = kernel_data.background.map_res_y;
24  int cdf_width = res_x + 1;
25 
26  /* This is basically std::lower_bound as used by PBRT. */
27  int first = 0;
28  int count = res_y;
29 
30  while (count > 0) {
31  int step = count >> 1;
32  int middle = first + step;
33 
34  if (kernel_data_fetch(light_background_marginal_cdf, middle).y < randv) {
35  first = middle + 1;
36  count -= step + 1;
37  }
38  else
39  count = step;
40  }
41 
42  int index_v = max(0, first - 1);
43  kernel_assert(index_v >= 0 && index_v < res_y);
44 
45  float2 cdf_v = kernel_data_fetch(light_background_marginal_cdf, index_v);
46  float2 cdf_next_v = kernel_data_fetch(light_background_marginal_cdf, index_v + 1);
47  float2 cdf_last_v = kernel_data_fetch(light_background_marginal_cdf, res_y);
48 
49  /* importance-sampled V direction */
50  float dv = inverse_lerp(cdf_v.y, cdf_next_v.y, randv);
51  float v = (index_v + dv) / res_y;
52 
53  /* This is basically std::lower_bound as used by PBRT. */
54  first = 0;
55  count = res_x;
56  while (count > 0) {
57  int step = count >> 1;
58  int middle = first + step;
59 
60  if (kernel_data_fetch(light_background_conditional_cdf, index_v * cdf_width + middle).y <
61  randu) {
62  first = middle + 1;
63  count -= step + 1;
64  }
65  else
66  count = step;
67  }
68 
69  int index_u = max(0, first - 1);
70  kernel_assert(index_u >= 0 && index_u < res_x);
71 
72  float2 cdf_u = kernel_data_fetch(light_background_conditional_cdf,
73  index_v * cdf_width + index_u);
74  float2 cdf_next_u = kernel_data_fetch(light_background_conditional_cdf,
75  index_v * cdf_width + index_u + 1);
76  float2 cdf_last_u = kernel_data_fetch(light_background_conditional_cdf,
77  index_v * cdf_width + res_x);
78 
79  /* importance-sampled U direction */
80  float du = inverse_lerp(cdf_u.y, cdf_next_u.y, randu);
81  float u = (index_u + du) / res_x;
82 
83  /* compute pdf */
84  float sin_theta = sinf(M_PI_F * v);
85  float denom = (M_2PI_F * M_PI_F * sin_theta) * cdf_last_u.x * cdf_last_v.x;
86 
87  if (sin_theta == 0.0f || denom == 0.0f)
88  *pdf = 0.0f;
89  else
90  *pdf = (cdf_u.x * cdf_v.x) / denom;
91 
92  /* compute direction */
94 }
95 
96 /* TODO(sergey): Same as above, after the release we should consider using
97  * 'noinline' for all devices.
98  */
99 ccl_device float background_map_pdf(KernelGlobals kg, float3 direction)
100 {
101  float2 uv = direction_to_equirectangular(direction);
102  int res_x = kernel_data.background.map_res_x;
103  int res_y = kernel_data.background.map_res_y;
104  int cdf_width = res_x + 1;
105 
106  float sin_theta = sinf(uv.y * M_PI_F);
107 
108  if (sin_theta == 0.0f)
109  return 0.0f;
110 
111  int index_u = clamp(float_to_int(uv.x * res_x), 0, res_x - 1);
112  int index_v = clamp(float_to_int(uv.y * res_y), 0, res_y - 1);
113 
114  /* pdfs in V direction */
115  float2 cdf_last_u = kernel_data_fetch(light_background_conditional_cdf,
116  index_v * cdf_width + res_x);
117  float2 cdf_last_v = kernel_data_fetch(light_background_marginal_cdf, res_y);
118 
119  float denom = (M_2PI_F * M_PI_F * sin_theta) * cdf_last_u.x * cdf_last_v.x;
120 
121  if (denom == 0.0f)
122  return 0.0f;
123 
124  /* pdfs in U direction */
125  float2 cdf_u = kernel_data_fetch(light_background_conditional_cdf,
126  index_v * cdf_width + index_u);
127  float2 cdf_v = kernel_data_fetch(light_background_marginal_cdf, index_v);
128 
129  return (cdf_u.x * cdf_v.x) / denom;
130 }
131 
132 ccl_device_inline bool background_portal_data_fetch_and_check_side(
133  KernelGlobals kg, float3 P, int index, ccl_private float3 *lightpos, ccl_private float3 *dir)
134 {
135  int portal = kernel_data.background.portal_offset + index;
136  const ccl_global KernelLight *klight = &kernel_data_fetch(lights, portal);
137 
138  *lightpos = make_float3(klight->co[0], klight->co[1], klight->co[2]);
139  *dir = make_float3(klight->area.dir[0], klight->area.dir[1], klight->area.dir[2]);
140 
141  /* Check whether portal is on the right side. */
142  if (dot(*dir, P - *lightpos) > 1e-4f)
143  return true;
144 
145  return false;
146 }
147 
148 ccl_device_inline float background_portal_pdf(
149  KernelGlobals kg, float3 P, float3 direction, int ignore_portal, ccl_private bool *is_possible)
150 {
151  float portal_pdf = 0.0f;
152 
153  int num_possible = 0;
154  for (int p = 0; p < kernel_data.background.num_portals; p++) {
155  if (p == ignore_portal)
156  continue;
157 
158  float3 lightpos, dir;
159  if (!background_portal_data_fetch_and_check_side(kg, P, p, &lightpos, &dir))
160  continue;
161 
162  /* There's a portal that could be sampled from this position. */
163  if (is_possible) {
164  *is_possible = true;
165  }
166  num_possible++;
167 
168  int portal = kernel_data.background.portal_offset + p;
169  const ccl_global KernelLight *klight = &kernel_data_fetch(lights, portal);
170  float3 axisu = make_float3(
171  klight->area.axisu[0], klight->area.axisu[1], klight->area.axisu[2]);
172  float3 axisv = make_float3(
173  klight->area.axisv[0], klight->area.axisv[1], klight->area.axisv[2]);
174  bool is_round = (klight->area.invarea < 0.0f);
175 
176  if (!ray_quad_intersect(P,
177  direction,
178  1e-4f,
179  FLT_MAX,
180  lightpos,
181  axisu,
182  axisv,
183  dir,
184  NULL,
185  NULL,
186  NULL,
187  NULL,
188  is_round))
189  continue;
190 
191  if (is_round) {
192  float t;
193  float3 D = normalize_len(lightpos - P, &t);
194  portal_pdf += fabsf(klight->area.invarea) * lamp_light_pdf(kg, dir, -D, t);
195  }
196  else {
197  portal_pdf += rect_light_sample(P, &lightpos, axisu, axisv, 0.0f, 0.0f, false);
198  }
199  }
200 
201  if (ignore_portal >= 0) {
202  /* We have skipped a portal that could be sampled as well. */
203  num_possible++;
204  }
205 
206  return (num_possible > 0) ? portal_pdf / num_possible : 0.0f;
207 }
208 
209 ccl_device int background_num_possible_portals(KernelGlobals kg, float3 P)
210 {
211  int num_possible_portals = 0;
212  for (int p = 0; p < kernel_data.background.num_portals; p++) {
213  float3 lightpos, dir;
214  if (background_portal_data_fetch_and_check_side(kg, P, p, &lightpos, &dir))
215  num_possible_portals++;
216  }
217  return num_possible_portals;
218 }
219 
220 ccl_device float3 background_portal_sample(KernelGlobals kg,
221  float3 P,
222  float randu,
223  float randv,
224  int num_possible,
225  ccl_private int *sampled_portal,
226  ccl_private float *pdf)
227 {
228  /* Pick a portal, then re-normalize randv. */
229  randv *= num_possible;
230  int portal = (int)randv;
231  randv -= portal;
232 
233  /* TODO(sergey): Some smarter way of finding portal to sample
234  * is welcome.
235  */
236  for (int p = 0; p < kernel_data.background.num_portals; p++) {
237  /* Search for the sampled portal. */
238  float3 lightpos, dir;
239  if (!background_portal_data_fetch_and_check_side(kg, P, p, &lightpos, &dir))
240  continue;
241 
242  if (portal == 0) {
243  /* p is the portal to be sampled. */
244  int portal = kernel_data.background.portal_offset + p;
245  const ccl_global KernelLight *klight = &kernel_data_fetch(lights, portal);
246  float3 axisu = make_float3(
247  klight->area.axisu[0], klight->area.axisu[1], klight->area.axisu[2]);
248  float3 axisv = make_float3(
249  klight->area.axisv[0], klight->area.axisv[1], klight->area.axisv[2]);
250  bool is_round = (klight->area.invarea < 0.0f);
251 
252  float3 D;
253  if (is_round) {
254  lightpos += ellipse_sample(axisu * 0.5f, axisv * 0.5f, randu, randv);
255  float t;
256  D = normalize_len(lightpos - P, &t);
257  *pdf = fabsf(klight->area.invarea) * lamp_light_pdf(kg, dir, -D, t);
258  }
259  else {
260  *pdf = rect_light_sample(P, &lightpos, axisu, axisv, randu, randv, true);
261  D = normalize(lightpos - P);
262  }
263 
264  *pdf /= num_possible;
265  *sampled_portal = p;
266  return D;
267  }
268 
269  portal--;
270  }
271 
272  return zero_float3();
273 }
274 
275 ccl_device_inline float3 background_sun_sample(KernelGlobals kg,
276  float randu,
277  float randv,
278  ccl_private float *pdf)
279 {
280  float3 D;
281  const float3 N = float4_to_float3(kernel_data.background.sun);
282  const float angle = kernel_data.background.sun.w;
283  sample_uniform_cone(N, angle, randu, randv, &D, pdf);
284  return D;
285 }
286 
287 ccl_device_inline float background_sun_pdf(KernelGlobals kg, float3 D)
288 {
289  const float3 N = float4_to_float3(kernel_data.background.sun);
290  const float angle = kernel_data.background.sun.w;
291  return pdf_uniform_cone(N, D, angle);
292 }
293 
294 ccl_device_inline float3 background_light_sample(
295  KernelGlobals kg, float3 P, float randu, float randv, ccl_private float *pdf)
296 {
297  float portal_method_pdf = kernel_data.background.portal_weight;
298  float sun_method_pdf = kernel_data.background.sun_weight;
299  float map_method_pdf = kernel_data.background.map_weight;
300 
301  int num_portals = 0;
302  if (portal_method_pdf > 0.0f) {
303  /* Check if there are portals in the scene which we can sample. */
304  num_portals = background_num_possible_portals(kg, P);
305  if (num_portals == 0) {
306  portal_method_pdf = 0.0f;
307  }
308  }
309 
310  float pdf_fac = (portal_method_pdf + sun_method_pdf + map_method_pdf);
311  if (pdf_fac == 0.0f) {
312  /* Use uniform as a fallback if we can't use any strategy. */
313  *pdf = 1.0f / M_4PI_F;
314  return sample_uniform_sphere(randu, randv);
315  }
316 
317  pdf_fac = 1.0f / pdf_fac;
318  portal_method_pdf *= pdf_fac;
319  sun_method_pdf *= pdf_fac;
320  map_method_pdf *= pdf_fac;
321 
322  /* We have 100% in total and split it between the three categories.
323  * Therefore, we pick portals if randu is between 0 and portal_method_pdf,
324  * sun if randu is between portal_method_pdf and (portal_method_pdf + sun_method_pdf)
325  * and map if randu is between (portal_method_pdf + sun_method_pdf) and 1. */
326  float sun_method_cdf = portal_method_pdf + sun_method_pdf;
327 
328  int method = 0;
329  float3 D;
330  if (randu < portal_method_pdf) {
331  method = 0;
332  /* Rescale randu. */
333  if (portal_method_pdf != 1.0f) {
334  randu /= portal_method_pdf;
335  }
336 
337  /* Sample a portal. */
338  int portal;
339  D = background_portal_sample(kg, P, randu, randv, num_portals, &portal, pdf);
340  if (num_portals > 1) {
341  /* Ignore the chosen portal, its pdf is already included. */
342  *pdf += background_portal_pdf(kg, P, D, portal, NULL);
343  }
344 
345  /* Skip MIS if this is the only method. */
346  if (portal_method_pdf == 1.0f) {
347  return D;
348  }
349  *pdf *= portal_method_pdf;
350  }
351  else if (randu < sun_method_cdf) {
352  method = 1;
353  /* Rescale randu. */
354  if (sun_method_pdf != 1.0f) {
355  randu = (randu - portal_method_pdf) / sun_method_pdf;
356  }
357 
358  D = background_sun_sample(kg, randu, randv, pdf);
359 
360  /* Skip MIS if this is the only method. */
361  if (sun_method_pdf == 1.0f) {
362  return D;
363  }
364  *pdf *= sun_method_pdf;
365  }
366  else {
367  method = 2;
368  /* Rescale randu. */
369  if (map_method_pdf != 1.0f) {
370  randu = (randu - sun_method_cdf) / map_method_pdf;
371  }
372 
373  D = background_map_sample(kg, randu, randv, pdf);
374 
375  /* Skip MIS if this is the only method. */
376  if (map_method_pdf == 1.0f) {
377  return D;
378  }
379  *pdf *= map_method_pdf;
380  }
381 
382  /* MIS weighting. */
383  if (method != 0 && portal_method_pdf != 0.0f) {
384  *pdf += portal_method_pdf * background_portal_pdf(kg, P, D, -1, NULL);
385  }
386  if (method != 1 && sun_method_pdf != 0.0f) {
387  *pdf += sun_method_pdf * background_sun_pdf(kg, D);
388  }
389  if (method != 2 && map_method_pdf != 0.0f) {
390  *pdf += map_method_pdf * background_map_pdf(kg, D);
391  }
392  return D;
393 }
394 
395 ccl_device float background_light_pdf(KernelGlobals kg, float3 P, float3 direction)
396 {
397  float portal_method_pdf = kernel_data.background.portal_weight;
398  float sun_method_pdf = kernel_data.background.sun_weight;
399  float map_method_pdf = kernel_data.background.map_weight;
400 
401  float portal_pdf = 0.0f;
402  /* Portals are a special case here since we need to compute their pdf in order
403  * to find out if we can sample them. */
404  if (portal_method_pdf > 0.0f) {
405  /* Evaluate PDF of sampling this direction by portal sampling. */
406  bool is_possible = false;
407  portal_pdf = background_portal_pdf(kg, P, direction, -1, &is_possible);
408  if (!is_possible) {
409  /* Portal sampling is not possible here because all portals point to the wrong side.
410  * If other methods can be used instead, do so, otherwise uniform sampling is used as a
411  * fallback. */
412  portal_method_pdf = 0.0f;
413  }
414  }
415 
416  float pdf_fac = (portal_method_pdf + sun_method_pdf + map_method_pdf);
417  if (pdf_fac == 0.0f) {
418  /* Use uniform as a fallback if we can't use any strategy. */
419  return kernel_data.integrator.pdf_lights / M_4PI_F;
420  }
421 
422  pdf_fac = 1.0f / pdf_fac;
423  portal_method_pdf *= pdf_fac;
424  sun_method_pdf *= pdf_fac;
425  map_method_pdf *= pdf_fac;
426 
427  float pdf = portal_pdf * portal_method_pdf;
428  if (sun_method_pdf != 0.0f) {
429  pdf += background_sun_pdf(kg, direction) * sun_method_pdf;
430  }
431  if (map_method_pdf != 0.0f) {
432  pdf += background_map_pdf(kg, direction) * map_method_pdf;
433  }
434 
435  return pdf * kernel_data.integrator.pdf_lights;
436 }
437 
438 #endif
439 
_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 y
_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
ATTR_WARN_UNUSED_RESULT const BMVert * v
SIMD_FORCE_INLINE btScalar angle(const btVector3 &v) const
Return the angle between this and another vector.
Definition: btVector3.h:356
ccl_device_inline float3 ellipse_sample(float3 ru, float3 rv, float randu, float randv)
Definition: common.h:97
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 sinf(x)
Definition: cuda/compat.h:102
#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_NAMESPACE_END
Definition: cuda/compat.h:9
ccl_device float3 equirectangular_to_direction(float u, float v)
ccl_device float2 direction_to_equirectangular(float3 dir)
#define kernel_data
const KernelGlobalsCPU *ccl_restrict KernelGlobals
#define kernel_data_fetch(name, index)
int count
ccl_device_inline float2 normalize_len(const float2 &a, float *t)
ccl_device_inline float3 zero_float3()
Definition: math_float3.h:80
static float P(float k)
Definition: math_interp.c:25
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)
#define N
#define fabsf(x)
Definition: metal/compat.h:219
#define make_float3(x, y, z)
Definition: metal/compat.h:204
T dot(const vec_base< T, Size > &a, const vec_base< T, Size > &b)
T clamp(const T &a, const T &min, const T &max)
vec_base< T, Size > normalize(const vec_base< T, Size > &v)
ccl_device float3 sample_uniform_sphere(float u1, float u2)
ccl_device_inline void sample_uniform_cone(const float3 N, float angle, float randu, float randv, ccl_private float3 *omega_in, ccl_private float *pdf)
ccl_device_inline float pdf_uniform_cone(const float3 N, float3 D, float angle)
float x
Definition: types_float2.h:15
float y
Definition: types_float2.h:15
float max
ccl_device_inline float inverse_lerp(float a, float b, float x)
Definition: util/math.h:515
ccl_device_inline int float_to_int(float f)
Definition: util/math.h:410
#define M_2PI_F
Definition: util/math.h:60
#define M_4PI_F
Definition: util/math.h:63
#define M_PI_F
Definition: util/math.h:34
ccl_device_inline float3 float4_to_float3(const float4 a)
Definition: util/math.h:500
BLI_INLINE float D(const float *data, const int res[3], int x, int y, int z)
Definition: voxel.c:13