Blender V4.3
bsdf_hair.h
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2009-2010 Sony Pictures Imageworks Inc., et al. All Rights Reserved.
2 * SPDX-FileCopyrightText: 2011-2022 Blender Foundation
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 * Adapted code from Open Shading Language. */
7
8#pragma once
9
11
20
21static_assert(sizeof(ShaderClosure) >= sizeof(HairBsdf), "HairBsdf is too large!");
22
24{
26 bsdf->roughness1 = clamp(bsdf->roughness1, 0.001f, 1.0f);
27 bsdf->roughness2 = clamp(bsdf->roughness2, 0.001f, 1.0f);
29}
30
32{
34 bsdf->roughness1 = clamp(bsdf->roughness1, 0.001f, 1.0f);
35 bsdf->roughness2 = clamp(bsdf->roughness2, 0.001f, 1.0f);
37}
38
40 const float3 wi,
41 const float3 wo,
42 ccl_private float *pdf)
43{
44 ccl_private const HairBsdf *bsdf = (ccl_private const HairBsdf *)sc;
45 if (dot(bsdf->N, wo) < 0.0f) {
46 *pdf = 0.0f;
47 return zero_spectrum();
48 }
49
50 float offset = bsdf->offset;
51 float3 Tg = bsdf->T;
52 float roughness1 = bsdf->roughness1;
53 float roughness2 = bsdf->roughness2;
54
55 float Iz = dot(Tg, wi);
56 float3 locy = normalize(wi - Tg * Iz);
57
58 float theta_r = M_PI_2_F - fast_acosf(Iz);
59
60 float wo_z = dot(Tg, wo);
61 float3 wo_y = normalize(wo - Tg * wo_z);
62
63 float theta_i = M_PI_2_F - fast_acosf(wo_z);
64 float cosphi_i = dot(wo_y, locy);
65
66 if (M_PI_2_F - fabsf(theta_i) < 0.001f || cosphi_i < 0.0f) {
67 *pdf = 0.0f;
68 return zero_spectrum();
69 }
70
71 float roughness1_inv = 1.0f / roughness1;
72 float roughness2_inv = 1.0f / roughness2;
73 float phi_i = fast_acosf(cosphi_i) * roughness2_inv;
74 phi_i = fabsf(phi_i) < M_PI_F ? phi_i : M_PI_F;
75 float costheta_i = fast_cosf(theta_i);
76
77 float a_R = fast_atan2f(((M_PI_2_F + theta_r) * 0.5f - offset) * roughness1_inv, 1.0f);
78 float b_R = fast_atan2f(((-M_PI_2_F + theta_r) * 0.5f - offset) * roughness1_inv, 1.0f);
79
80 float theta_h = (theta_i + theta_r) * 0.5f;
81 float t = theta_h - offset;
82
83 float phi_pdf = fast_cosf(phi_i * 0.5f) * 0.25f * roughness2_inv;
84 float theta_pdf = roughness1 /
85 (2 * (t * t + roughness1 * roughness1) * (a_R - b_R) * costheta_i);
86 *pdf = phi_pdf * theta_pdf;
87
88 return make_spectrum(*pdf);
89}
90
92 const float3 wi,
93 const float3 wo,
94 ccl_private float *pdf)
95{
96 ccl_private const HairBsdf *bsdf = (ccl_private const HairBsdf *)sc;
97 if (dot(bsdf->N, wo) >= 0.0f) {
98 *pdf = 0.0f;
99 return zero_spectrum();
100 }
101
102 float offset = bsdf->offset;
103 float3 Tg = bsdf->T;
104 float roughness1 = bsdf->roughness1;
105 float roughness2 = bsdf->roughness2;
106 float Iz = dot(Tg, wi);
107 float3 locy = normalize(wi - Tg * Iz);
108
109 float theta_r = M_PI_2_F - fast_acosf(Iz);
110
111 float wo_z = dot(Tg, wo);
112 float3 wo_y = normalize(wo - Tg * wo_z);
113
114 float theta_i = M_PI_2_F - fast_acosf(wo_z);
115 float phi_i = fast_acosf(dot(wo_y, locy));
116
117 if (M_PI_2_F - fabsf(theta_i) < 0.001f) {
118 *pdf = 0.0f;
119 return zero_spectrum();
120 }
121
122 float costheta_i = fast_cosf(theta_i);
123
124 float roughness1_inv = 1.0f / roughness1;
125 float a_TT = fast_atan2f(((M_PI_2_F + theta_r) / 2 - offset) * roughness1_inv, 1.0f);
126 float b_TT = fast_atan2f(((-M_PI_2_F + theta_r) / 2 - offset) * roughness1_inv, 1.0f);
127 float c_TT = 2 * fast_atan2f(M_PI_2_F / roughness2, 1.0f);
128
129 float theta_h = (theta_i + theta_r) / 2;
130 float t = theta_h - offset;
131 float phi = fabsf(phi_i);
132
133 float p = M_PI_F - phi;
134 float theta_pdf = roughness1 /
135 (2 * (t * t + roughness1 * roughness1) * (a_TT - b_TT) * costheta_i);
136 float phi_pdf = roughness2 / (c_TT * (p * p + roughness2 * roughness2));
137
138 *pdf = phi_pdf * theta_pdf;
139 return make_spectrum(*pdf);
140}
141
143 float3 Ng,
144 float3 wi,
145 float2 rand,
146 ccl_private Spectrum *eval,
148 ccl_private float *pdf,
149 ccl_private float2 *sampled_roughness)
150{
151 ccl_private const HairBsdf *bsdf = (ccl_private const HairBsdf *)sc;
152 float offset = bsdf->offset;
153 float3 Tg = bsdf->T;
154 float roughness1 = bsdf->roughness1;
155 float roughness2 = bsdf->roughness2;
156 *sampled_roughness = make_float2(roughness1, roughness2);
157 float Iz = dot(Tg, wi);
158 float3 locy = normalize(wi - Tg * Iz);
159 float3 locx = cross(locy, Tg);
160 float theta_r = M_PI_2_F - fast_acosf(Iz);
161
162 float roughness1_inv = 1.0f / roughness1;
163 float a_R = fast_atan2f(((M_PI_2_F + theta_r) * 0.5f - offset) * roughness1_inv, 1.0f);
164 float b_R = fast_atan2f(((-M_PI_2_F + theta_r) * 0.5f - offset) * roughness1_inv, 1.0f);
165
166 float t = roughness1 * tanf(rand.x * (a_R - b_R) + b_R);
167
168 float theta_h = t + offset;
169 float theta_i = 2 * theta_h - theta_r;
170
171 float costheta_i, sintheta_i;
172 fast_sincosf(theta_i, &sintheta_i, &costheta_i);
173
174 float phi = 2 * safe_asinf(1 - 2 * rand.y) * roughness2;
175
176 float phi_pdf = fast_cosf(phi * 0.5f) * 0.25f / roughness2;
177
178 float theta_pdf = roughness1 /
179 (2 * (t * t + roughness1 * roughness1) * (a_R - b_R) * costheta_i);
180
181 float sinphi, cosphi;
182 fast_sincosf(phi, &sinphi, &cosphi);
183 *wo = (cosphi * costheta_i) * locy - (sinphi * costheta_i) * locx + (sintheta_i)*Tg;
184
185 *pdf = fabsf(phi_pdf * theta_pdf);
186 if (M_PI_2_F - fabsf(theta_i) < 0.001f)
187 *pdf = 0.0f;
188
189 *eval = make_spectrum(*pdf);
190
192}
193
195 float3 Ng,
196 float3 wi,
197 float2 rand,
198 ccl_private Spectrum *eval,
200 ccl_private float *pdf,
201 ccl_private float2 *sampled_roughness)
202{
203 ccl_private const HairBsdf *bsdf = (ccl_private const HairBsdf *)sc;
204 float offset = bsdf->offset;
205 float3 Tg = bsdf->T;
206 float roughness1 = bsdf->roughness1;
207 float roughness2 = bsdf->roughness2;
208 *sampled_roughness = make_float2(roughness1, roughness2);
209 float Iz = dot(Tg, wi);
210 float3 locy = normalize(wi - Tg * Iz);
211 float3 locx = cross(locy, Tg);
212 float theta_r = M_PI_2_F - fast_acosf(Iz);
213
214 float roughness1_inv = 1.0f / roughness1;
215 float a_TT = fast_atan2f(((M_PI_2_F + theta_r) / 2 - offset) * roughness1_inv, 1.0f);
216 float b_TT = fast_atan2f(((-M_PI_2_F + theta_r) / 2 - offset) * roughness1_inv, 1.0f);
217 float c_TT = 2 * fast_atan2f(M_PI_2_F / roughness2, 1.0f);
218
219 float t = roughness1 * tanf(rand.x * (a_TT - b_TT) + b_TT);
220
221 float theta_h = t + offset;
222 float theta_i = 2 * theta_h - theta_r;
223
224 float costheta_i, sintheta_i;
225 fast_sincosf(theta_i, &sintheta_i, &costheta_i);
226
227 float p = roughness2 * tanf(c_TT * (rand.y - 0.5f));
228 float phi = p + M_PI_F;
229 float theta_pdf = roughness1 /
230 (2 * (t * t + roughness1 * roughness1) * (a_TT - b_TT) * costheta_i);
231 float phi_pdf = roughness2 / (c_TT * (p * p + roughness2 * roughness2));
232
233 float sinphi, cosphi;
234 fast_sincosf(phi, &sinphi, &cosphi);
235 *wo = (cosphi * costheta_i) * locy - (sinphi * costheta_i) * locx + (sintheta_i)*Tg;
236
237 *pdf = fabsf(phi_pdf * theta_pdf);
238 if (M_PI_2_F - fabsf(theta_i) < 0.001f) {
239 *pdf = 0.0f;
240 }
241
242 *eval = make_spectrum(*pdf);
243
244 /* TODO(sergey): Should always be negative, but seems some precision issue
245 * is involved here.
246 */
247 kernel_assert(dot(locy, *wo) < 1e-4f);
248
250}
251
MINLINE float safe_asinf(float a)
ccl_device int bsdf_hair_transmission_sample(ccl_private const ShaderClosure *sc, float3 Ng, float3 wi, float2 rand, ccl_private Spectrum *eval, ccl_private float3 *wo, ccl_private float *pdf, ccl_private float2 *sampled_roughness)
Definition bsdf_hair.h:194
ccl_device Spectrum bsdf_hair_transmission_eval(ccl_private const ShaderClosure *sc, const float3 wi, const float3 wo, ccl_private float *pdf)
Definition bsdf_hair.h:91
ccl_device int bsdf_hair_reflection_setup(ccl_private HairBsdf *bsdf)
Definition bsdf_hair.h:23
ccl_device Spectrum bsdf_hair_reflection_eval(ccl_private const ShaderClosure *sc, const float3 wi, const float3 wo, ccl_private float *pdf)
Definition bsdf_hair.h:39
ccl_device int bsdf_hair_reflection_sample(ccl_private const ShaderClosure *sc, float3 Ng, float3 wi, float2 rand, ccl_private Spectrum *eval, ccl_private float3 *wo, ccl_private float *pdf, ccl_private float2 *sampled_roughness)
Definition bsdf_hair.h:142
ccl_device int bsdf_hair_transmission_setup(ccl_private HairBsdf *bsdf)
Definition bsdf_hair.h:31
CCL_NAMESPACE_BEGIN struct HairBsdf HairBsdf
SIMD_FORCE_INLINE btVector3 & normalize()
Normalize this vector x^2 + y^2 + z^2 = 1.
Definition btVector3.h:303
additional_info("compositor_sum_squared_difference_float_shared") .push_constant(Type output_img float dot(value.rgb, luminance_coefficients)") .define("LOAD(value)"
#define kernel_assert(cond)
#define ccl_device
#define ccl_private
#define tanf(x)
#define CCL_NAMESPACE_END
ccl_device_forceinline float2 make_float2(const float x, const float y)
#define fabsf(x)
@ CLOSURE_BSDF_HAIR_TRANSMISSION_ID
@ CLOSURE_BSDF_HAIR_REFLECTION_ID
@ SD_BSDF_HAS_EVAL
@ SD_BSDF
@ SD_BSDF_HAS_TRANSMISSION
@ LABEL_TRANSMIT
@ LABEL_GLOSSY
@ LABEL_REFLECT
ShaderClosure
ccl_device void fast_sincosf(float x, ccl_private float *sine, ccl_private float *cosine)
Definition math_fast.h:141
ccl_device float fast_acosf(float x)
Definition math_fast.h:260
ccl_device float fast_atan2f(float y, float x)
Definition math_fast.h:310
ccl_device float fast_cosf(float x)
Definition math_fast.h:113
ccl_device_inline float cross(const float2 a, const float2 b)
#define M_PI_F
Definition mikk_util.hh:15
#define M_PI_2_F
Definition sky_float3.h:20
float roughness1
Definition bsdf_hair.h:16
float offset
Definition bsdf_hair.h:18
float roughness2
Definition bsdf_hair.h:17
SHADER_CLOSURE_BASE
Definition bsdf_hair.h:13
float3 T
Definition bsdf_hair.h:15
float x
float y
#define zero_spectrum
#define make_spectrum(f)
SPECTRUM_DATA_TYPE Spectrum
ccl_device_inline int clamp(int a, int mn, int mx)
Definition util/math.h:379