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