Blender  V3.3
bsdf_hair_principled.h
Go to the documentation of this file.
1 /* SPDX-License-Identifier: Apache-2.0
2  * Copyright 2018-2022 Blender Foundation */
3 
4 #pragma once
5 
6 #ifndef __KERNEL_GPU__
7 # include <fenv.h>
8 #endif
9 
10 #include "kernel/util/color.h"
11 
13 
14 typedef struct PrincipledHairExtra {
15  /* Geometry data. */
18 
19 typedef struct PrincipledHairBSDF {
21 
22  /* Absorption coefficient. */
24  /* Variance of the underlying logistic distribution. */
25  float v;
26  /* Scale factor of the underlying logistic distribution. */
27  float s;
28  /* Cuticle tilt angle. */
29  float alpha;
30  /* IOR. */
31  float eta;
32  /* Effective variance for the diffuse bounce only. */
33  float m0_roughness;
34 
35  /* Extra closure. */
38 
39 static_assert(sizeof(ShaderClosure) >= sizeof(PrincipledHairBSDF),
40  "PrincipledHairBSDF is too large!");
41 static_assert(sizeof(ShaderClosure) >= sizeof(PrincipledHairExtra),
42  "PrincipledHairExtra is too large!");
43 
44 ccl_device_inline float cos_from_sin(const float s)
45 {
46  return safe_sqrtf(1.0f - s * s);
47 }
48 
49 /* Gives the change in direction in the normal plane for the given angles and p-th-order
50  * scattering. */
51 ccl_device_inline float delta_phi(int p, float gamma_o, float gamma_t)
52 {
53  return 2.0f * p * gamma_t - 2.0f * gamma_o + p * M_PI_F;
54 }
55 
56 /* Remaps the given angle to [-pi, pi]. */
58 {
59  while (a > M_PI_F) {
60  a -= M_2PI_F;
61  }
62  while (a < -M_PI_F) {
63  a += M_2PI_F;
64  }
65  return a;
66 }
67 
68 /* Logistic distribution function. */
69 ccl_device_inline float logistic(float x, float s)
70 {
71  float v = expf(-fabsf(x) / s);
72  return v / (s * sqr(1.0f + v));
73 }
74 
75 /* Logistic cumulative density function. */
76 ccl_device_inline float logistic_cdf(float x, float s)
77 {
78  float arg = -x / s;
79  /* expf() overflows if arg >= 89.0. */
80  if (arg > 88.0f) {
81  return 0.0f;
82  }
83  else {
84  return 1.0f / (1.0f + expf(arg));
85  }
86 }
87 
88 /* Numerical approximation to the Bessel function of the first kind. */
90 {
91  x = sqr(x);
92  float val = 1.0f + 0.25f * x;
93  float pow_x_2i = sqr(x);
94  uint64_t i_fac_2 = 1;
95  int pow_4_i = 16;
96  for (int i = 2; i < 10; i++) {
97  i_fac_2 *= i * i;
98  float newval = val + pow_x_2i / (pow_4_i * i_fac_2);
99  if (val == newval) {
100  return val;
101  }
102  val = newval;
103  pow_x_2i *= x;
104  pow_4_i *= 4;
105  }
106  return val;
107 }
108 
109 /* Logarithm of the Bessel function of the first kind. */
111 {
112  if (x > 12.0f) {
113  /* log(1/x) == -log(x) if x > 0.
114  * This is only used with positive cosines. */
115  return x + 0.5f * (1.f / (8.0f * x) - M_LN_2PI_F - logf(x));
116  }
117  else {
118  return logf(bessel_I0(x));
119  }
120 }
121 
122 /* Logistic distribution limited to the interval [-pi, pi]. */
123 ccl_device_inline float trimmed_logistic(float x, float s)
124 {
125  /* The logistic distribution is symmetric and centered around zero,
126  * so logistic_cdf(x, s) = 1 - logistic_cdf(-x, s).
127  * Therefore, logistic_cdf(x, s)-logistic_cdf(-x, s) = 1 - 2*logistic_cdf(-x, s) */
128  float scaling_fac = 1.0f - 2.0f * logistic_cdf(-M_PI_F, s);
129  float val = logistic(x, s);
130  return safe_divide(val, scaling_fac);
131 }
132 
133 /* Sampling function for the trimmed logistic function. */
135 {
136  float cdf_minuspi = logistic_cdf(-M_PI_F, s);
137  float x = -s * logf(1.0f / (u * (1.0f - 2.0f * cdf_minuspi) + cdf_minuspi) - 1.0f);
138  return clamp(x, -M_PI_F, M_PI_F);
139 }
140 
141 /* Azimuthal scattering function Np. */
143  float phi, int p, float s, float gamma_o, float gamma_t)
144 {
145  float phi_o = wrap_angle(phi - delta_phi(p, gamma_o, gamma_t));
146  float val = trimmed_logistic(phi_o, s);
147  return val;
148 }
149 
150 /* Longitudinal scattering function Mp. */
152  float sin_theta_i, float cos_theta_i, float sin_theta_o, float cos_theta_o, float v)
153 {
154  float inv_v = 1.0f / v;
155  float cos_arg = cos_theta_i * cos_theta_o * inv_v;
156  float sin_arg = sin_theta_i * sin_theta_o * inv_v;
157  if (v <= 0.1f) {
158  float i0 = log_bessel_I0(cos_arg);
159  float val = expf(i0 - sin_arg - inv_v + 0.6931f + logf(0.5f * inv_v));
160  return val;
161  }
162  else {
163  float i0 = bessel_I0(cos_arg);
164  float val = (expf(-sin_arg) * i0) / (sinhf(inv_v) * 2.0f * v);
165  return val;
166  }
167 }
168 
169 /* Combine the three values using their luminances. */
171 {
172  return make_float4(c.x, c.y, c.z, linear_rgb_to_gray(kg, c));
173 }
174 
175 #ifdef __HAIR__
176 /* Set up the hair closure. */
177 ccl_device int bsdf_principled_hair_setup(ccl_private ShaderData *sd,
179 {
180  bsdf->type = CLOSURE_BSDF_HAIR_PRINCIPLED_ID;
181  bsdf->v = clamp(bsdf->v, 0.001f, 1.0f);
182  bsdf->s = clamp(bsdf->s, 0.001f, 1.0f);
183  /* Apply Primary Reflection Roughness modifier. */
184  bsdf->m0_roughness = clamp(bsdf->m0_roughness * bsdf->v, 0.001f, 1.0f);
185 
186  /* Map from roughness_u and roughness_v to variance and scale factor. */
187  bsdf->v = sqr(0.726f * bsdf->v + 0.812f * sqr(bsdf->v) + 3.700f * pow20(bsdf->v));
188  bsdf->s = (0.265f * bsdf->s + 1.194f * sqr(bsdf->s) + 5.372f * pow22(bsdf->s)) * M_SQRT_PI_8_F;
189  bsdf->m0_roughness = sqr(0.726f * bsdf->m0_roughness + 0.812f * sqr(bsdf->m0_roughness) +
190  3.700f * pow20(bsdf->m0_roughness));
191 
192  /* Compute local frame, aligned to curve tangent and ray direction. */
193  float3 X = safe_normalize(sd->dPdu);
194  float3 Y = safe_normalize(cross(X, sd->I));
196 
197  /* h -1..0..1 means the rays goes from grazing the hair, to hitting it at
198  * the center, to grazing the other edge. This is the sine of the angle
199  * between sd->Ng and Z, as seen from the tangent X. */
200 
201  /* TODO: we convert this value to a cosine later and discard the sign, so
202  * we could probably save some operations. */
203  float h = (sd->type & PRIMITIVE_CURVE_RIBBON) ? -sd->v : dot(cross(sd->Ng, X), Z);
204 
205  kernel_assert(fabsf(h) < 1.0f + 1e-4f);
208 
209  bsdf->extra->geom = make_float4(Y.x, Y.y, Y.z, h);
210 
212 }
213 
214 #endif /* __HAIR__ */
215 
216 /* Given the Fresnel term and transmittance, generate the attenuation terms for each bounce. */
218  float f,
219  float3 T,
220  ccl_private float4 *Ap)
221 {
222  /* Primary specular (R). */
223  Ap[0] = make_float4(f, f, f, f);
224 
225  /* Transmission (TT). */
226  float3 col = sqr(1.0f - f) * T;
227  Ap[1] = combine_with_energy(kg, col);
228 
229  /* Secondary specular (TRT). */
230  col *= T * f;
231  Ap[2] = combine_with_energy(kg, col);
232 
233  /* Residual component (TRRT+). */
234  col *= safe_divide_color(T * f, make_float3(1.0f, 1.0f, 1.0f) - T * f);
235  Ap[3] = combine_with_energy(kg, col);
236 
237  /* Normalize sampling weights. */
238  float totweight = Ap[0].w + Ap[1].w + Ap[2].w + Ap[3].w;
239  float fac = safe_divide(1.0f, totweight);
240 
241  Ap[0].w *= fac;
242  Ap[1].w *= fac;
243  Ap[2].w *= fac;
244  Ap[3].w *= fac;
245 }
246 
247 /* Given the tilt angle, generate the rotated theta_i for the different bounces. */
248 ccl_device_inline void hair_alpha_angles(float sin_theta_i,
249  float cos_theta_i,
250  float alpha,
251  ccl_private float *angles)
252 {
253  float sin_1alpha = sinf(alpha);
254  float cos_1alpha = cos_from_sin(sin_1alpha);
255  float sin_2alpha = 2.0f * sin_1alpha * cos_1alpha;
256  float cos_2alpha = sqr(cos_1alpha) - sqr(sin_1alpha);
257  float sin_4alpha = 2.0f * sin_2alpha * cos_2alpha;
258  float cos_4alpha = sqr(cos_2alpha) - sqr(sin_2alpha);
259 
260  angles[0] = sin_theta_i * cos_2alpha + cos_theta_i * sin_2alpha;
261  angles[1] = fabsf(cos_theta_i * cos_2alpha - sin_theta_i * sin_2alpha);
262  angles[2] = sin_theta_i * cos_1alpha - cos_theta_i * sin_1alpha;
263  angles[3] = fabsf(cos_theta_i * cos_1alpha + sin_theta_i * sin_1alpha);
264  angles[4] = sin_theta_i * cos_4alpha - cos_theta_i * sin_4alpha;
265  angles[5] = fabsf(cos_theta_i * cos_4alpha + sin_theta_i * sin_4alpha);
266 }
267 
268 /* Evaluation function for our shader. */
270  ccl_private const ShaderData *sd,
271  ccl_private const ShaderClosure *sc,
272  const float3 omega_in,
273  ccl_private float *pdf)
274 {
275  kernel_assert(isfinite_safe(sd->P) && isfinite_safe(sd->ray_length));
276 
278  float3 Y = float4_to_float3(bsdf->extra->geom);
279 
280  float3 X = safe_normalize(sd->dPdu);
281  kernel_assert(fabsf(dot(X, Y)) < 1e-3f);
283 
284  float3 wo = make_float3(dot(sd->I, X), dot(sd->I, Y), dot(sd->I, Z));
285  float3 wi = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z));
286 
287  float sin_theta_o = wo.x;
288  float cos_theta_o = cos_from_sin(sin_theta_o);
289  float phi_o = atan2f(wo.z, wo.y);
290 
291  float sin_theta_t = sin_theta_o / bsdf->eta;
292  float cos_theta_t = cos_from_sin(sin_theta_t);
293 
294  float sin_gamma_o = bsdf->extra->geom.w;
295  float cos_gamma_o = cos_from_sin(sin_gamma_o);
296  float gamma_o = safe_asinf(sin_gamma_o);
297 
298  float sin_gamma_t = sin_gamma_o * cos_theta_o / sqrtf(sqr(bsdf->eta) - sqr(sin_theta_o));
299  float cos_gamma_t = cos_from_sin(sin_gamma_t);
300  float gamma_t = safe_asinf(sin_gamma_t);
301 
302  float3 T = exp(-bsdf->sigma * (2.0f * cos_gamma_t / cos_theta_t));
303  float4 Ap[4];
304  hair_attenuation(kg, fresnel_dielectric_cos(cos_theta_o * cos_gamma_o, bsdf->eta), T, Ap);
305 
306  float sin_theta_i = wi.x;
307  float cos_theta_i = cos_from_sin(sin_theta_i);
308  float phi_i = atan2f(wi.z, wi.y);
309 
310  float phi = phi_i - phi_o;
311 
312  float angles[6];
313  hair_alpha_angles(sin_theta_i, cos_theta_i, bsdf->alpha, angles);
314 
315  float4 F;
316  float Mp, Np;
317 
318  /* Primary specular (R). */
319  Mp = longitudinal_scattering(angles[0], angles[1], sin_theta_o, cos_theta_o, bsdf->m0_roughness);
320  Np = azimuthal_scattering(phi, 0, bsdf->s, gamma_o, gamma_t);
321  F = Ap[0] * Mp * Np;
323 
324  /* Transmission (TT). */
325  Mp = longitudinal_scattering(angles[2], angles[3], sin_theta_o, cos_theta_o, 0.25f * bsdf->v);
326  Np = azimuthal_scattering(phi, 1, bsdf->s, gamma_o, gamma_t);
327  F += Ap[1] * Mp * Np;
329 
330  /* Secondary specular (TRT). */
331  Mp = longitudinal_scattering(angles[4], angles[5], sin_theta_o, cos_theta_o, 4.0f * bsdf->v);
332  Np = azimuthal_scattering(phi, 2, bsdf->s, gamma_o, gamma_t);
333  F += Ap[2] * Mp * Np;
335 
336  /* Residual component (TRRT+). */
337  Mp = longitudinal_scattering(sin_theta_i, cos_theta_i, sin_theta_o, cos_theta_o, 4.0f * bsdf->v);
338  Np = M_1_2PI_F;
339  F += Ap[3] * Mp * Np;
341 
342  *pdf = F.w;
343  return float4_to_float3(F);
344 }
345 
346 /* Sampling function for the hair shader. */
348  ccl_private const ShaderClosure *sc,
350  float randu,
351  float randv,
352  ccl_private float3 *eval,
353  ccl_private float3 *omega_in,
354  ccl_private float3 *domega_in_dx,
355  ccl_private float3 *domega_in_dy,
356  ccl_private float *pdf)
357 {
359 
360  float3 Y = float4_to_float3(bsdf->extra->geom);
361 
362  float3 X = safe_normalize(sd->dPdu);
363  kernel_assert(fabsf(dot(X, Y)) < 1e-3f);
365 
366  float3 wo = make_float3(dot(sd->I, X), dot(sd->I, Y), dot(sd->I, Z));
367 
368  float2 u[2];
369  u[0] = make_float2(randu, randv);
370  u[1].x = lcg_step_float(&sd->lcg_state);
371  u[1].y = lcg_step_float(&sd->lcg_state);
372 
373  float sin_theta_o = wo.x;
374  float cos_theta_o = cos_from_sin(sin_theta_o);
375  float phi_o = atan2f(wo.z, wo.y);
376 
377  float sin_theta_t = sin_theta_o / bsdf->eta;
378  float cos_theta_t = cos_from_sin(sin_theta_t);
379 
380  float sin_gamma_o = bsdf->extra->geom.w;
381  float cos_gamma_o = cos_from_sin(sin_gamma_o);
382  float gamma_o = safe_asinf(sin_gamma_o);
383 
384  float sin_gamma_t = sin_gamma_o * cos_theta_o / sqrtf(sqr(bsdf->eta) - sqr(sin_theta_o));
385  float cos_gamma_t = cos_from_sin(sin_gamma_t);
386  float gamma_t = safe_asinf(sin_gamma_t);
387 
388  float3 T = exp(-bsdf->sigma * (2.0f * cos_gamma_t / cos_theta_t));
389  float4 Ap[4];
390  hair_attenuation(kg, fresnel_dielectric_cos(cos_theta_o * cos_gamma_o, bsdf->eta), T, Ap);
391 
392  int p = 0;
393  for (; p < 3; p++) {
394  if (u[0].x < Ap[p].w) {
395  break;
396  }
397  u[0].x -= Ap[p].w;
398  }
399 
400  float v = bsdf->v;
401  if (p == 1) {
402  v *= 0.25f;
403  }
404  if (p >= 2) {
405  v *= 4.0f;
406  }
407 
408  u[1].x = max(u[1].x, 1e-5f);
409  float fac = 1.0f + v * logf(u[1].x + (1.0f - u[1].x) * expf(-2.0f / v));
410  float sin_theta_i = -fac * sin_theta_o +
411  cos_from_sin(fac) * cosf(M_2PI_F * u[1].y) * cos_theta_o;
412  float cos_theta_i = cos_from_sin(sin_theta_i);
413 
414  float angles[6];
415  if (p < 3) {
416  hair_alpha_angles(sin_theta_i, cos_theta_i, -bsdf->alpha, angles);
417  sin_theta_i = angles[2 * p];
418  cos_theta_i = angles[2 * p + 1];
419  }
420 
421  float phi;
422  if (p < 3) {
423  phi = delta_phi(p, gamma_o, gamma_t) + sample_trimmed_logistic(u[0].y, bsdf->s);
424  }
425  else {
426  phi = M_2PI_F * u[0].y;
427  }
428  float phi_i = phi_o + phi;
429 
430  hair_alpha_angles(sin_theta_i, cos_theta_i, bsdf->alpha, angles);
431 
432  float4 F;
433  float Mp, Np;
434 
435  /* Primary specular (R). */
436  Mp = longitudinal_scattering(angles[0], angles[1], sin_theta_o, cos_theta_o, bsdf->m0_roughness);
437  Np = azimuthal_scattering(phi, 0, bsdf->s, gamma_o, gamma_t);
438  F = Ap[0] * Mp * Np;
440 
441  /* Transmission (TT). */
442  Mp = longitudinal_scattering(angles[2], angles[3], sin_theta_o, cos_theta_o, 0.25f * bsdf->v);
443  Np = azimuthal_scattering(phi, 1, bsdf->s, gamma_o, gamma_t);
444  F += Ap[1] * Mp * Np;
446 
447  /* Secondary specular (TRT). */
448  Mp = longitudinal_scattering(angles[4], angles[5], sin_theta_o, cos_theta_o, 4.0f * bsdf->v);
449  Np = azimuthal_scattering(phi, 2, bsdf->s, gamma_o, gamma_t);
450  F += Ap[2] * Mp * Np;
452 
453  /* Residual component (TRRT+). */
454  Mp = longitudinal_scattering(sin_theta_i, cos_theta_i, sin_theta_o, cos_theta_o, 4.0f * bsdf->v);
455  Np = M_1_2PI_F;
456  F += Ap[3] * Mp * Np;
458 
459  *eval = float4_to_float3(F);
460  *pdf = F.w;
461 
462  *omega_in = X * sin_theta_i + Y * cos_theta_i * cosf(phi_i) + Z * cos_theta_i * sinf(phi_i);
463 
464 #ifdef __RAY_DIFFERENTIALS__
465  float3 N = safe_normalize(sd->I + *omega_in);
466  *domega_in_dx = (2 * dot(N, sd->dI.dx)) * N - sd->dI.dx;
467  *domega_in_dy = (2 * dot(N, sd->dI.dy)) * N - sd->dI.dy;
468 #endif
469 
470  return LABEL_GLOSSY | ((p == 0) ? LABEL_REFLECT : LABEL_TRANSMIT);
471 }
472 
473 /* Implements Filter Glossy by capping the effective roughness. */
475 {
477 
478  bsdf->v = fmaxf(roughness, bsdf->v);
479  bsdf->s = fmaxf(roughness, bsdf->s);
480  bsdf->m0_roughness = fmaxf(roughness, bsdf->m0_roughness);
481 }
482 
483 /* Hair Albedo */
484 
486  const float azimuthal_roughness)
487 {
488  const float x = azimuthal_roughness;
489  return (((((0.245f * x) + 5.574f) * x - 10.73f) * x + 2.532f) * x - 0.215f) * x + 5.969f;
490 }
491 
493 {
495  return exp(-sqrt(bsdf->sigma) * bsdf_principled_hair_albedo_roughness_scale(bsdf->v));
496 }
497 
499 bsdf_principled_hair_sigma_from_reflectance(const float3 color, const float azimuthal_roughness)
500 {
501  const float3 sigma = log(color) /
502  bsdf_principled_hair_albedo_roughness_scale(azimuthal_roughness);
503  return sigma * sigma;
504 }
505 
507  const float pheomelanin)
508 {
509  return eumelanin * make_float3(0.506f, 0.841f, 1.653f) +
510  pheomelanin * make_float3(0.343f, 0.733f, 1.924f);
511 }
512 
sqrt(x)+1/max(0
MINLINE float safe_sqrtf(float a)
MINLINE float safe_asinf(float a)
_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
float float4[4]
#define Z
Definition: GeomUtils.cpp:201
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Sky Generate a procedural sky texture Noise Generate fractal Perlin noise Wave Generate procedural bands or rings with noise Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a or normal between and object coordinate space Combine Create a color from its and value channels Color Retrieve a color or the default fallback if none is specified Separate Split a vector into its X
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Sky Generate a procedural sky texture Noise Generate fractal Perlin noise Wave Generate procedural bands or rings with noise Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a or normal between and object coordinate space Combine Create a color from its and value channels Color Retrieve a color or the default fallback if none is specified Separate Split a vector into its Y
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert a color
ATTR_WARN_UNUSED_RESULT const BMVert * v
ccl_device_inline float logistic_cdf(float x, float s)
ccl_device void bsdf_principled_hair_blur(ccl_private ShaderClosure *sc, float roughness)
ccl_device_inline float logistic(float x, float s)
ccl_device_inline void hair_attenuation(KernelGlobals kg, float f, float3 T, ccl_private float4 *Ap)
ccl_device_inline float delta_phi(int p, float gamma_o, float gamma_t)
ccl_device_inline float log_bessel_I0(float x)
ccl_device_inline float longitudinal_scattering(float sin_theta_i, float cos_theta_i, float sin_theta_o, float cos_theta_o, float v)
ccl_device_inline float3 bsdf_principled_hair_sigma_from_concentration(const float eumelanin, const float pheomelanin)
ccl_device_inline float bsdf_principled_hair_albedo_roughness_scale(const float azimuthal_roughness)
ccl_device_inline float sample_trimmed_logistic(float u, float s)
ccl_device float3 bsdf_principled_hair_albedo(ccl_private const ShaderClosure *sc)
CCL_NAMESPACE_BEGIN struct PrincipledHairExtra PrincipledHairExtra
ccl_device int bsdf_principled_hair_sample(KernelGlobals kg, ccl_private const ShaderClosure *sc, ccl_private ShaderData *sd, float randu, float randv, ccl_private float3 *eval, ccl_private float3 *omega_in, ccl_private float3 *domega_in_dx, ccl_private float3 *domega_in_dy, ccl_private float *pdf)
ccl_device_inline float wrap_angle(float a)
ccl_device_inline void hair_alpha_angles(float sin_theta_i, float cos_theta_i, float alpha, ccl_private float *angles)
ccl_device_inline float azimuthal_scattering(float phi, int p, float s, float gamma_o, float gamma_t)
ccl_device_inline float bessel_I0(float x)
ccl_device float3 bsdf_principled_hair_eval(KernelGlobals kg, ccl_private const ShaderData *sd, ccl_private const ShaderClosure *sc, const float3 omega_in, ccl_private float *pdf)
ccl_device_inline float trimmed_logistic(float x, float s)
struct PrincipledHairBSDF PrincipledHairBSDF
ccl_device_inline float4 combine_with_energy(KernelGlobals kg, float3 c)
ccl_device_inline float3 bsdf_principled_hair_sigma_from_reflectance(const float3 color, const float azimuthal_roughness)
ccl_device_inline float cos_from_sin(const float s)
ccl_device float fresnel_dielectric_cos(float cosi, float eta)
Definition: bsdf_util.h:79
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition: btQuadWord.h:119
#define kernel_assert(cond)
Definition: cpu/compat.h:34
#define logf(x)
Definition: cuda/compat.h:105
#define sinf(x)
Definition: cuda/compat.h:102
#define cosf(x)
Definition: cuda/compat.h:101
#define ccl_device
Definition: cuda/compat.h:32
#define expf(x)
Definition: cuda/compat.h:106
#define ccl_private
Definition: cuda/compat.h:48
#define ccl_device_inline
Definition: cuda/compat.h:34
#define CCL_NAMESPACE_END
Definition: cuda/compat.h:9
const KernelGlobalsCPU *ccl_restrict KernelGlobals
uint col
@ CLOSURE_BSDF_HAIR_PRINCIPLED_ID
@ SD_BSDF_HAS_EVAL
Definition: kernel/types.h:744
@ SD_BSDF_NEEDS_LCG
Definition: kernel/types.h:756
@ SD_BSDF
Definition: kernel/types.h:742
@ PRIMITIVE_CURVE_RIBBON
Definition: kernel/types.h:553
ShaderData
Definition: kernel/types.h:925
@ LABEL_TRANSMIT
Definition: kernel/types.h:317
@ LABEL_GLOSSY
Definition: kernel/types.h:320
@ LABEL_REFLECT
Definition: kernel/types.h:318
ShaderClosure
Definition: kernel/types.h:726
ccl_device float linear_rgb_to_gray(KernelGlobals kg, float3 c)
ccl_device float lcg_step_float(T rng)
Definition: lcg.h:19
ccl_device_inline float2 safe_normalize(const float2 &a)
Definition: math_float2.h:201
ccl_device_inline float3 exp(float3 v)
Definition: math_float3.h:392
ccl_device_inline float3 log(float3 v)
Definition: math_float3.h:397
#define N
#define T
#define F
#define atan2f(x, y)
Definition: metal/compat.h:227
#define fmaxf(x, y)
Definition: metal/compat.h:228
#define make_float2(x, y)
Definition: metal/compat.h:203
#define make_float4(x, y, z, w)
Definition: metal/compat.h:205
#define sinhf(x)
Definition: metal/compat.h:231
#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
static unsigned c
Definition: RandGen.cpp:83
static unsigned a[3]
Definition: RandGen.cpp:78
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)
T safe_divide(const T &a, const T &b)
static const pxr::TfToken roughness("roughness", pxr::TfToken::Immortal)
unsigned __int64 uint64_t
Definition: stdint.h:90
ccl_private PrincipledHairExtra * extra
float x
Definition: types_float2.h:15
float y
Definition: types_float2.h:15
float z
float y
float x
float max
#define M_SQRT_PI_8_F
Definition: util/math.h:52
ccl_device_inline float pow22(float a)
Definition: util/math.h:756
ccl_device_inline float pow20(float a)
Definition: util/math.h:751
ccl_device_inline float sqr(float a)
Definition: util/math.h:746
#define M_2PI_F
Definition: util/math.h:60
#define M_LN_2PI_F
Definition: util/math.h:55
ccl_device_inline float3 safe_divide_color(float3 a, float3 b)
Definition: util/math.h:605
ccl_device_inline bool isfinite_safe(float f)
Definition: util/math.h:353
#define M_1_2PI_F
Definition: util/math.h:49
#define M_PI_F
Definition: util/math.h:34
ccl_device_inline float3 float4_to_float3(const float4 a)
Definition: util/math.h:500