5
5
#define _NBL_BUILTIN_HLSL_BXDF_COMMON_INCLUDED_
6
6
7
7
#include <nbl/builtin/hlsl/limits.hlsl>
8
+ #include <nbl/builtin/hlsl/numbers.hlsl>
9
+ #include <nbl/builtin/hlsl/math/functions.glsl>
8
10
9
11
namespace nbl
10
12
{
@@ -186,11 +188,13 @@ struct LightSample
186
188
float NdotL2;
187
189
};
188
190
191
+
189
192
//
190
193
struct IsotropicMicrofacetCache
191
194
{
195
+ // always valid by construction
192
196
// always valid because its specialized for the reflective case
193
- static IsotropicMicrofacetCache create (const float NdotV, const float NdotL, const float VdotL, out float LplusV_rcpLen)
197
+ static IsotropicMicrofacetCache createForReflection (const float NdotV, const float NdotL, const float VdotL, out float LplusV_rcpLen)
194
198
{
195
199
LplusV_rcpLen = inversesqrt (2.0 +2.0 *VdotL);
196
200
@@ -203,10 +207,73 @@ struct IsotropicMicrofacetCache
203
207
204
208
return retval;
205
209
}
206
- static IsotropicMicrofacetCache create (const float NdotV, const float NdotL, const float VdotL)
210
+ static IsotropicMicrofacetCache createForReflection (const float NdotV, const float NdotL, const float VdotL)
207
211
{
208
212
float dummy;
209
- return create (NdotV,NdotL,VdotL,dummy);
213
+ return createForReflection (NdotV,NdotL,VdotL,dummy);
214
+ }
215
+ template<class ObserverRayDirInfo, class IncomingRayDirInfo>
216
+ static IsotropicMicrofacetCache createForReflection (
217
+ const surface_interactions::Isotropic<ObserverRayDirInfo> interaction,
218
+ const LightSample<IncomingRayDirInfo> _sample)
219
+ {
220
+ return createForReflection (interaction.NdotV,_sample.NdotL,_sample.VdotL);
221
+ }
222
+ // transmissive cases need to be checked if the path is valid before usage
223
+ static bool compute (
224
+ out IsotropicMicrofacetCache retval,
225
+ const bool transmitted, const float3 V, const float3 L,
226
+ const float3 N, const float NdotL, const float VdotL,
227
+ const float orientedEta, const float rcpOrientedEta, out float3 H
228
+ )
229
+ {
230
+ // TODO: can we optimize?
231
+ H = computeMicrofacetNormal (transmitted,V,L,orientedEta);
232
+ retval.NdotH = dot (N,H);
233
+
234
+ // not coming from the medium (reflected) OR
235
+ // exiting at the macro scale AND ( (not L outside the cone of possible directions given IoR with constraint VdotH*LdotH<0.0) OR (microfacet not facing toward the macrosurface, i.e. non heightfield profile of microsurface) )
236
+ const bool valid = !transmitted || (VdotL<=-min (orientedEta,rcpOrientedEta) && _cache.NdotH>nbl::hlsl::numeric_limits::min ());
237
+ if (valid)
238
+ {
239
+ // TODO: can we optimize?
240
+ retval.VdotH = dot (V,H);
241
+ retval.LdotH = dot (L,H);
242
+ retval.NdotH2 = retval.NdotH*retval.NdotH;
243
+ return true ;
244
+ }
245
+ return false ;
246
+ }
247
+ template<class ObserverRayDirInfo, class IncomingRayDirInfo>
248
+ static bool compute (
249
+ out IsotropicMicrofacetCache retval,
250
+ const surface_interactions::Isotropic<ObserverRayDirInfo> interaction,
251
+ const LightSample<IncomingRayDirInfo> _sample,
252
+ const float eta, out float3 H
253
+ )
254
+ {
255
+ const float NdotV = interaction.NdotV;
256
+ const float NdotL = _sample.NdotL;
257
+ const bool transmitted = nbl_glsl_isTransmissionPath (NdotV,NdotL);
258
+
259
+ float orientedEta, rcpOrientedEta;
260
+ const bool backside = nbl_glsl_getOrientedEtas (orientedEta,rcpOrientedEta,NdotV,eta);
261
+
262
+ const vec3 V = interaction.V.getDirection ();
263
+ const vec3 L = _sample.L;
264
+ const float VdotL = dot (V,L);
265
+ return nbl_glsl_calcIsotropicMicrofacetCache (_cache,transmitted,V,L,interaction.N,NdotL,VdotL,orientedEta,rcpOrientedEta,H);
266
+ }
267
+ template<class ObserverRayDirInfo, class IncomingRayDirInfo>
268
+ static bool compute (
269
+ out IsotropicMicrofacetCache retval,
270
+ const surface_interactions::Isotropic<ObserverRayDirInfo> interaction,
271
+ const LightSample<IncomingRayDirInfo> _sample,
272
+ const float eta
273
+ )
274
+ {
275
+ float3 dummy;
276
+ return nbl_glsl_calcIsotropicMicrofacetCache (_cache,transmitted,V,L,interaction.N,NdotL,VdotL,orientedEta,rcpOrientedEta,dummy);
210
277
}
211
278
212
279
bool isValidVNDFMicrofacet (const bool is_bsdf, const bool transmission, const float VdotL, const float eta, const float rcp_eta)
@@ -219,10 +286,67 @@ struct IsotropicMicrofacetCache
219
286
float NdotH;
220
287
float NdotH2;
221
288
};
289
+
222
290
struct AnisotropicMicrofacetCache : IsotropicMicrofacetCache
223
291
{
224
- float TdotH;
225
- float BdotH;
292
+ // always valid by construction
293
+ // always valid because its specialized for the reflective case
294
+ static AnisotropicMicrofacetCache createForReflection (const float3 tangentSpaceV, const float3 tangentSpaceL, const float VdotL)
295
+ {
296
+ AnisotropicMicrofacetCache retval;
297
+
298
+ float LplusV_rcpLen;
299
+ retval = createForReflection (tangentSpaceV.z,tangentSpaceL.z,VdotL,LplusV_rcpLen);
300
+ retval.TdotH = (tangentSpaceV.x+tangentSpaceL.x)*LplusV_rcpLen;
301
+ retval.BdotH = (tangentSpaceV.y+tangentSpaceL.y)*LplusV_rcpLen;
302
+
303
+ return retval;
304
+ }
305
+ template<class ObserverRayDirInfo, class IncomingRayDirInfo>
306
+ static AnisotropicMicrofacetCache createForReflection (
307
+ const surface_interactions::Anisotropic <ObserverRayDirInfo> interaction,
308
+ const LightSample<IncomingRayDirInfo> _sample)
309
+ {
310
+ return createForReflection (interaction.getTangentSpaceV (),_sample.getTangentSpaceL (),_sample.VdotL);
311
+ }
312
+ // transmissive cases need to be checked if the path is valid before usage
313
+ static bool compute (
314
+ out AnisotropicMicrofacetCache retval,
315
+ const bool transmitted, const float3 V, const float3 L,
316
+ const float3 T, const float3 B, const float3 N,
317
+ const float NdotL, const float VdotL,
318
+ const float orientedEta, const float rcpOrientedEta, out float3 H
319
+ )
320
+ {
321
+ float3 H;
322
+ const bool valid = IsotropicMicrofacetCache::compute (retval,transmitted,V,L,N,NdotL,VdotL,orientedEta,rcpOrientedEta,H);
323
+ if (valid)
324
+ {
325
+ retval.TdotH = dot (T,H);
326
+ retval.BdotH = dot (B,H);
327
+ }
328
+ return valid;
329
+ }
330
+ template<class ObserverRayDirInfo, class IncomingRayDirInfo>
331
+ static bool compute (
332
+ out AnisotropicMicrofacetCache retval,
333
+ const surface_interactions::Anisotropic <ObserverRayDirInfo> interaction,
334
+ const LightSample<IncomingRayDirInfo> _sample,
335
+ const float eta
336
+ )
337
+ {
338
+ float3 H;
339
+ const bool valid = IsotropicMicrofacetCache::compute (retval,interaction,_sample,eta,H);
340
+ if (valid)
341
+ {
342
+ retval.TdotH = dot (interaction.T,H);
343
+ retval.BdotH = dot (interaction.B,H);
344
+ }
345
+ return valid;
346
+ }
347
+
348
+ float TdotH;
349
+ float BdotH;
226
350
};
227
351
228
352
0 commit comments