Skip to content

Commit de66abf

Browse files
Implement some of Microfacet Caches, missing valid by construction
and add missing header includes
1 parent 6ac724b commit de66abf

File tree

1 file changed

+129
-5
lines changed

1 file changed

+129
-5
lines changed

include/nbl/builtin/hlsl/bxdf/common.hlsl

Lines changed: 129 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
#define _NBL_BUILTIN_HLSL_BXDF_COMMON_INCLUDED_
66

77
#include <nbl/builtin/hlsl/limits.hlsl>
8+
#include <nbl/builtin/hlsl/numbers.hlsl>
9+
#include <nbl/builtin/hlsl/math/functions.glsl>
810

911
namespace nbl
1012
{
@@ -186,11 +188,13 @@ struct LightSample
186188
float NdotL2;
187189
};
188190

191+
189192
//
190193
struct IsotropicMicrofacetCache
191194
{
195+
// always valid by construction
192196
// 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)
194198
{
195199
LplusV_rcpLen = inversesqrt(2.0+2.0*VdotL);
196200

@@ -203,10 +207,73 @@ struct IsotropicMicrofacetCache
203207

204208
return retval;
205209
}
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)
207211
{
208212
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);
210277
}
211278

212279
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
219286
float NdotH;
220287
float NdotH2;
221288
};
289+
222290
struct AnisotropicMicrofacetCache : IsotropicMicrofacetCache
223291
{
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;
226350
};
227351

228352

0 commit comments

Comments
 (0)