Skip to content

Commit c66a184

Browse files
committed
material compiler: Precomputed V and H squared dots with tangents
Known bug: some of the emitters in staircase scene are black because they have normals wrong way around or vertex order inverted (so they are recognized as backfacing) and so NdotV is negative in irr_bsdf_cos_generate()
1 parent dbb6b93 commit c66a184

File tree

3 files changed

+102
-69
lines changed

3 files changed

+102
-69
lines changed

include/irr/builtin/material_compiler/glsl/common.glsl

Lines changed: 57 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
#error "You need to define 'vec3 irr_glsl_MC_getNormalizedWorldSpaceV()', 'vec3 irr_glsl_MC_getNormalizedWorldSpaceN()' , 'irr_glsl_MC_getWorldSpacePosition()', 'instr_t irr_glsl_MC_fetchInstr(in uint)', 'prefetch_instr_t irr_glsl_MC_fetchPrefetchInstr(in uint)', 'bsdf_data_t irr_glsl_MC_fetchBSDFData(in uint)' functions above"
88
#endif
99

10-
#include <irr/builtin/glsl/bxdf/common.glsl>
1110
#include <irr/builtin/glsl/math/functions.glsl>
1211
#include <irr/builtin/glsl/format/decode.glsl>
1312

@@ -201,28 +200,30 @@ bool op_isDiffuse(in uint op)
201200
#include <irr/builtin/glsl/bump_mapping/utils.glsl>
202201

203202
//irr_glsl_BSDFAnisotropicParams currBSDFParams;
204-
irr_glsl_AnisotropicViewSurfaceInteraction currInteraction;
203+
MC_interaction_t currInteraction;
205204
reg_t registers[REG_COUNT];
206205

207206
void updateLightSampleAfterNormalChange(inout irr_glsl_LightSample out_s)
208207
{
209-
out_s.TdotL = dot(currInteraction.T, out_s.L);
210-
out_s.BdotL = dot(currInteraction.B, out_s.L);
211-
out_s.NdotL = dot(currInteraction.isotropic.N, out_s.L);
208+
out_s.TdotL = dot(currInteraction.inner.T, out_s.L);
209+
out_s.BdotL = dot(currInteraction.inner.B, out_s.L);
210+
out_s.NdotL = dot(currInteraction.inner.isotropic.N, out_s.L);
212211
out_s.NdotL2 = out_s.NdotL*out_s.NdotL;
213212
}
214-
void updateMicrofacetCacheAfterNormalChange(in irr_glsl_LightSample s, inout irr_glsl_AnisotropicMicrofacetCache out_microfacet)
213+
void updateMicrofacetCacheAfterNormalChange(in irr_glsl_LightSample s, inout MC_microfacet_t out_microfacet)
215214
{
216215
const float NdotL = s.NdotL;
217-
const float NdotV = currInteraction.isotropic.NdotV;
216+
const float NdotV = currInteraction.inner.isotropic.NdotV;
218217

219218
const float LplusV_rcplen = inversesqrt(2.0 + 2.0 * s.VdotL);
220219

221-
out_microfacet.isotropic.NdotH = (NdotL + NdotV) * LplusV_rcplen;
222-
out_microfacet.isotropic.NdotH2 = out_microfacet.isotropic.NdotH * out_microfacet.isotropic.NdotH;
220+
out_microfacet.inner.isotropic.NdotH = (NdotL + NdotV) * LplusV_rcplen;
221+
out_microfacet.inner.isotropic.NdotH2 = out_microfacet.inner.isotropic.NdotH * out_microfacet.inner.isotropic.NdotH;
222+
223+
out_microfacet.inner.TdotH = (currInteraction.inner.TdotV + s.TdotL) * LplusV_rcplen;
224+
out_microfacet.inner.BdotH = (currInteraction.inner.BdotV + s.BdotL) * LplusV_rcplen;
223225

224-
out_microfacet.TdotH = (currInteraction.TdotV + s.TdotL) * LplusV_rcplen;
225-
out_microfacet.BdotH = (currInteraction.BdotV + s.BdotL) * LplusV_rcplen;
226+
finalizeMicrofacet(out_microfacet);
226227
}
227228

228229
vec3 textureOrRGBconst(in uvec2 data, in bool texPresenceFlag)
@@ -341,7 +342,8 @@ mat2x4 instr_fetchSrcRegs(in instr_t i)
341342
void setCurrInteraction(in vec3 N, in vec3 V, in vec3 pos)
342343
{
343344
irr_glsl_IsotropicViewSurfaceInteraction interaction = irr_glsl_calcFragmentShaderSurfaceInteractionFromViewVector(V, pos, N);
344-
currInteraction = irr_glsl_calcAnisotropicInteraction(interaction);
345+
currInteraction.inner = irr_glsl_calcAnisotropicInteraction(interaction);
346+
finalizeInteraction(currInteraction);
345347
}
346348
void setCurrInteraction(in MC_precomputed_t precomp)
347349
{
@@ -387,7 +389,7 @@ bxdf_eval_t instr_execute_cos_eval_COATING(in instr_t instr, in mat2x4 srcs, in
387389

388390
// TODO include thickness_sigma in diffuse weight computation: exp(sigma_thickness * freePath)
389391
// freePath = ( sqrt(refract_compute_NdotT2(NdotL2, rcpOrientedEta2)) + sqrt(refract_compute_NdotT2(NdotV2, rcpOrientedEta2)) )
390-
vec3 fresnelNdotV = irr_glsl_fresnel_dielectric_frontface_only(eta, max(currInteraction.isotropic.NdotV, 0.0));
392+
vec3 fresnelNdotV = irr_glsl_fresnel_dielectric_frontface_only(eta, max(currInteraction.inner.isotropic.NdotV, 0.0));
391393
vec3 wd = irr_glsl_diffuseFresnelCorrectionFactor(eta, eta2) * (vec3(1.0) - fresnelNdotV) * (vec3(1.0) - irr_glsl_fresnel_dielectric_frontface_only(eta, s.NdotL));
392394

393395
bxdf_eval_t coat = srcs[0].xyz;
@@ -513,13 +515,13 @@ void runNormalPrecompStream(in instr_stream_t stream, in mat2 dUV, in MC_precomp
513515
vec2 dh = readReg2(srcreg);
514516

515517
writeReg(dstreg,
516-
irr_glsl_perturbNormal_derivativeMap(currInteraction.isotropic.N, dh, currInteraction.isotropic.V.dPosdScreen, dUV)
518+
irr_glsl_perturbNormal_derivativeMap(currInteraction.inner.isotropic.N, dh, currInteraction.inner.isotropic.V.dPosdScreen, dUV)
517519
);
518520
}
519521
}
520522

521523
#ifdef GEN_CHOICE_STREAM
522-
void instr_eval_and_pdf_execute(in instr_t instr, in MC_precomputed_t precomp, in irr_glsl_LightSample s, in irr_glsl_AnisotropicMicrofacetCache _microfacet, in bool skip)
524+
void instr_eval_and_pdf_execute(in instr_t instr, in MC_precomputed_t precomp, in irr_glsl_LightSample s, in MC_microfacet_t _microfacet, in bool skip)
523525
{
524526
const uint op = instr_getOpcode(instr);
525527
const bool is_bxdf = op_isBXDF(op);
@@ -533,7 +535,7 @@ void instr_eval_and_pdf_execute(in instr_t instr, in MC_precomputed_t precomp, i
533535
bsdf_data_t bsdf_data;
534536
mat2x3 ior;
535537
mat2x3 ior2;
536-
irr_glsl_AnisotropicMicrofacetCache microfacet;
538+
MC_microfacet_t microfacet;
537539

538540
const bool run = !skip;
539541

@@ -545,7 +547,7 @@ void instr_eval_and_pdf_execute(in instr_t instr, in MC_precomputed_t precomp, i
545547
params = instr_getParameters(instr, bsdf_data);
546548
}
547549

548-
const float NdotV = irr_glsl_conditionalAbsOrMax(is_bsdf, currInteraction.isotropic.NdotV, 0.0);
550+
const float NdotV = irr_glsl_conditionalAbsOrMax(is_bsdf, currInteraction.inner.isotropic.NdotV, 0.0);
549551

550552
vec3 eval = vec3(0.0);
551553
float pdf = 0.0;
@@ -584,29 +586,30 @@ void instr_eval_and_pdf_execute(in instr_t instr, in MC_precomputed_t precomp, i
584586
bool is_valid = true;
585587
bool refraction = false;
586588
#ifdef OP_DIELECTRIC
587-
if (op == OP_DIELECTRIC && irr_glsl_isTransmissionPath(currInteraction.isotropic.NdotV, s.NdotL))
589+
if (op == OP_DIELECTRIC && irr_glsl_isTransmissionPath(currInteraction.inner.isotropic.NdotV, s.NdotL))
588590
{
589-
irr_glsl_calcAnisotropicMicrofacetCache(microfacet, true, currInteraction.isotropic.V.dir, s.L, currInteraction.T, currInteraction.B, currInteraction.isotropic.N, s.NdotL, s.VdotL, eta, rcp_eta);
591+
irr_glsl_calcAnisotropicMicrofacetCache(microfacet.inner, true, currInteraction.inner.isotropic.V.dir, s.L, currInteraction.inner.T, currInteraction.inner.B, currInteraction.inner.isotropic.N, s.NdotL, s.VdotL, eta, rcp_eta);
592+
finalizeMicrofacet(microfacet);
590593
refraction = true;
591594
}
592595
else
593596
#endif
594597
microfacet = _microfacet;
595598

596599
#if defined(OP_DIELECTRIC) || defined(OP_CONDUCTOR)
597-
is_valid = irr_glsl_isValidVNDFMicrofacet(microfacet.isotropic, is_bsdf, refraction, s.VdotL, eta, rcp_eta);
600+
is_valid = irr_glsl_isValidVNDFMicrofacet(microfacet.inner.isotropic, is_bsdf, refraction, s.VdotL, eta, rcp_eta);
598601
#endif
599602

600603
if (is_valid && a > ALPHA_EPSILON)
601604
{
602-
const float TdotV2 = currInteraction.TdotV * currInteraction.TdotV;
603-
const float BdotV2 = currInteraction.BdotV * currInteraction.BdotV;
604-
const float NdotV2 = currInteraction.isotropic.NdotV_squared;
605+
const float TdotV2 = currInteraction.TdotV2;
606+
const float BdotV2 = currInteraction.BdotV2;
607+
const float NdotV2 = currInteraction.inner.isotropic.NdotV_squared;
605608
const float NdotL2 = s.NdotL2;
606609

607-
const float TdotH2 = microfacet.TdotH * microfacet.TdotH;
608-
const float BdotH2 = microfacet.BdotH * microfacet.BdotH;
609-
const float NdotH2 = microfacet.isotropic.NdotH2;
610+
const float TdotH2 = microfacet.TdotH2;
611+
const float BdotH2 = microfacet.BdotH2;
612+
const float NdotH2 = microfacet.inner.isotropic.NdotH2;
610613

611614
float G1_over_2NdotV = 0.0;
612615
float G2_over_G1 = 0.0;
@@ -665,7 +668,7 @@ void instr_eval_and_pdf_execute(in instr_t instr, in MC_precomputed_t precomp, i
665668
pdf = irr_glsl_smith_VNDF_pdf_wo_clamps(ndf_val, G1_over_2NdotV);
666669
float remainder_scalar_part = G2_over_G1;
667670

668-
const float VdotH = is_bsdf ? microfacet.isotropic.VdotH : max(microfacet.isotropic.VdotH, 0.0);
671+
const float VdotH = is_bsdf ? microfacet.inner.isotropic.VdotH : max(microfacet.inner.isotropic.VdotH, 0.0);
669672
vec3 fr;
670673
#ifdef OP_CONDUCTOR
671674
if (op == OP_CONDUCTOR)
@@ -679,8 +682,8 @@ void instr_eval_and_pdf_execute(in instr_t instr, in MC_precomputed_t precomp, i
679682
#ifndef NO_BSDF
680683
if (is_bsdf)
681684
{
682-
float LdotH = microfacet.isotropic.LdotH;
683-
float VdotHLdotH = microfacet.isotropic.VdotH * LdotH;
685+
float LdotH = microfacet.inner.isotropic.LdotH;
686+
float VdotHLdotH = microfacet.inner.isotropic.VdotH * LdotH;
684687
LdotH = abs(LdotH);
685688
#ifdef NDF_GGX
686689
if (ndf == NDF_GGX)
@@ -734,7 +737,7 @@ void instr_eval_and_pdf_execute(in instr_t instr, in MC_precomputed_t precomp, i
734737
writeReg(REG_DST(regs), result);
735738
}
736739

737-
eval_and_pdf_t irr_bsdf_eval_and_pdf(in MC_precomputed_t precomp, in instr_stream_t stream, in uint generator_offset, inout irr_glsl_LightSample s, inout irr_glsl_AnisotropicMicrofacetCache microfacet)
740+
eval_and_pdf_t irr_bsdf_eval_and_pdf(in MC_precomputed_t precomp, in instr_stream_t stream, in uint generator_offset, inout irr_glsl_LightSample s, inout MC_microfacet_t microfacet)
738741
{
739742
setCurrInteraction(precomp);
740743
for (uint i = 0u; i < stream.count; ++i)
@@ -775,7 +778,7 @@ eval_and_pdf_t irr_bsdf_eval_and_pdf(in MC_precomputed_t precomp, in instr_strea
775778
return eval_and_pdf;
776779
}
777780

778-
irr_glsl_LightSample irr_bsdf_cos_generate(in MC_precomputed_t precomp, in instr_stream_t stream, in vec3 rand, out vec3 out_remainder, out float out_pdf, out irr_glsl_AnisotropicMicrofacetCache out_microfacet, out uint out_gen_rnpOffset)
781+
irr_glsl_LightSample irr_bsdf_cos_generate(in MC_precomputed_t precomp, in instr_stream_t stream, in vec3 rand, out vec3 out_remainder, out float out_pdf, out MC_microfacet_t out_microfacet, out uint out_gen_rnpOffset)
779782
{
780783
uint ix = 0u;
781784
instr_t instr = irr_glsl_MC_fetchInstr(stream.offset);
@@ -803,7 +806,7 @@ irr_glsl_LightSample irr_bsdf_cos_generate(in MC_precomputed_t precomp, in instr
803806
#endif
804807
{
805808
vec3 eta = bsdf_data_decodeIoR(bsdf_data, OP_COATING)[0];
806-
w_ = irr_glsl_fresnel_dielectric_frontface_only(eta, max(currInteraction.isotropic.NdotV, 0.0));
809+
w_ = irr_glsl_fresnel_dielectric_frontface_only(eta, max(currInteraction.inner.isotropic.NdotV, 0.0));
807810
}
808811

809812
float w = colorToScalar(w_);
@@ -854,22 +857,22 @@ irr_glsl_LightSample irr_bsdf_cos_generate(in MC_precomputed_t precomp, in instr
854857
const bool is_bsdf = !op_isBRDF(op) && !is_coat;
855858
const vec3 albedo = params_getReflectance(params);
856859

857-
const float NdotV = irr_glsl_conditionalAbsOrMax(is_bsdf, currInteraction.isotropic.NdotV, 0.0);
860+
const float NdotV = irr_glsl_conditionalAbsOrMax(is_bsdf, currInteraction.inner.isotropic.NdotV, 0.0);
858861
const bool positiveNdotV = (NdotV > FLT_MIN);
859862

860863
float localPdf = positiveNdotV ? 1.0 : 0.0;
861864
vec3 rem = positiveNdotV ? vec3(1.0) : vec3(0.0);
862865
uint ndf = instr_getNDF(instr);
863866
irr_glsl_LightSample s;
864867

865-
const vec3 localV = irr_glsl_getTangentSpaceV(currInteraction);
866-
const mat3 tangentFrame = irr_glsl_getTangentFrame(currInteraction);
868+
const vec3 localV = irr_glsl_getTangentSpaceV(currInteraction.inner);
869+
const mat3 tangentFrame = irr_glsl_getTangentFrame(currInteraction.inner);
867870

868871

869872
#ifdef OP_DELTATRANS
870873
if (op == OP_DELTATRANS)
871874
{
872-
s = irr_glsl_createLightSample(-precomp.V, -1.0, currInteraction.T, currInteraction.B, currInteraction.isotropic.N);
875+
s = irr_glsl_createLightSample(-precomp.V, -1.0, currInteraction.inner.T, currInteraction.inner.B, currInteraction.inner.isotropic.N);
873876
// not computing microfacet cache since it's always transmission and it will be recomputed anyway
874877
rem = vec3(1.0);
875878
localPdf = irr_glsl_FLT_INF;
@@ -881,10 +884,11 @@ irr_glsl_LightSample irr_bsdf_cos_generate(in MC_precomputed_t precomp, in instr
881884
const vec3 luminosityContributionHint = CIE_XYZ_Luma_Y_coeffs;
882885
vec3 remMetadata;
883886
s = irr_glsl_thin_smooth_dielectric_cos_generate_wo_clamps(
884-
currInteraction.isotropic.V.dir, currInteraction.T, currInteraction.B, currInteraction.isotropic.N,
885-
currInteraction.isotropic.NdotV, NdotV, u, ior2[0], luminosityContributionHint, remMetadata
887+
currInteraction.inner.isotropic.V.dir, currInteraction.inner.T, currInteraction.inner.B, currInteraction.inner.isotropic.N,
888+
currInteraction.inner.isotropic.NdotV, NdotV, u, ior2[0], luminosityContributionHint, remMetadata
886889
);
887-
out_microfacet = irr_glsl_calcAnisotropicMicrofacetCache(currInteraction, s);
890+
out_microfacet.inner = irr_glsl_calcAnisotropicMicrofacetCache(currInteraction.inner, s);
891+
finalizeMicrofacet(out_microfacet);
888892
rem = irr_glsl_thin_smooth_dielectric_cos_remainder_and_pdf_wo_clamps(localPdf, remMetadata);
889893
} else
890894
#endif
@@ -903,20 +907,21 @@ irr_glsl_LightSample irr_bsdf_cos_generate(in MC_precomputed_t precomp, in instr
903907
}
904908
#endif
905909
s = irr_glsl_createLightSampleTangentSpace(localV, localL, tangentFrame);
906-
out_microfacet = irr_glsl_calcAnisotropicMicrofacetCache(currInteraction, s);
910+
out_microfacet.inner = irr_glsl_calcAnisotropicMicrofacetCache(currInteraction.inner, s);
911+
finalizeMicrofacet(out_microfacet);
907912

908-
rem *= albedo*irr_glsl_oren_nayar_cos_remainder_and_pdf(localPdf, s, currInteraction.isotropic, ax2);
913+
rem *= albedo*irr_glsl_oren_nayar_cos_remainder_and_pdf(localPdf, s, currInteraction.inner.isotropic, ax2);
909914
localPdf *= is_bsdf ? 0.5 : 1.0;
910915
} else
911916
#endif
912917
#if defined(OP_CONDUCTOR) || defined(OP_DIELECTRIC)
913918
if (op_hasSpecular(op))
914919
{
915-
const float TdotV2 = currInteraction.TdotV * currInteraction.TdotV;
916-
const float BdotV2 = currInteraction.BdotV * currInteraction.BdotV;
917-
const float NdotV2 = currInteraction.isotropic.NdotV_squared;
920+
const float TdotV2 = currInteraction.inner.TdotV * currInteraction.inner.TdotV;
921+
const float BdotV2 = currInteraction.inner.BdotV * currInteraction.inner.BdotV;
922+
const float NdotV2 = currInteraction.inner.isotropic.NdotV_squared;
918923

919-
const vec3 upperHemisphereLocalV = currInteraction.isotropic.NdotV < 0.0 ? -localV : localV;
924+
const vec3 upperHemisphereLocalV = currInteraction.inner.isotropic.NdotV < 0.0 ? -localV : localV;
920925

921926
float G2_over_G1 = 0.0;
922927
float G1_over_2NdotV = 0.0;
@@ -973,12 +978,13 @@ irr_glsl_LightSample irr_bsdf_cos_generate(in MC_precomputed_t precomp, in instr
973978
float eta = colorToScalar(ior[0]);
974979
float rcpEta = 1.0/eta;
975980

976-
out_microfacet = irr_glsl_calcAnisotropicMicrofacetCache(refraction, localV, localH, localL, rcpEta, rcpEta*rcpEta);
981+
out_microfacet.inner = irr_glsl_calcAnisotropicMicrofacetCache(refraction, localV, localH, localL, rcpEta, rcpEta*rcpEta);
977982
s = irr_glsl_createLightSampleTangentSpace(localV, localL, tangentFrame);
978983

979-
const float TdotH2 = out_microfacet.TdotH * out_microfacet.TdotH;
980-
const float BdotH2 = out_microfacet.BdotH * out_microfacet.BdotH;
981-
const float NdotH2 = out_microfacet.isotropic.NdotH2;
984+
finalizeMicrofacet(out_microfacet);
985+
const float TdotH2 = out_microfacet.TdotH2;
986+
const float BdotH2 = out_microfacet.BdotH2;
987+
const float NdotH2 = out_microfacet.inner.isotropic.NdotH2;
982988
const float NdotL = irr_glsl_conditionalAbsOrMax(is_bsdf, s.NdotL, 0.0);
983989

984990
BEGIN_CASES(ndf)
@@ -1014,7 +1020,7 @@ irr_glsl_LightSample irr_bsdf_cos_generate(in MC_precomputed_t precomp, in instr
10141020
{}
10151021
END_CASES
10161022

1017-
const float LdotH = out_microfacet.isotropic.LdotH;
1023+
const float LdotH = out_microfacet.inner.isotropic.LdotH;
10181024
const float VdotHLdotH = VdotH * LdotH;
10191025
// a trick, pdf was already multiplied by transmission/reflection choice probability above
10201026
const float reflectance = refraction ? 0.0 : 1.0;
@@ -1035,7 +1041,7 @@ vec3 runGenerateAndRemainderStream(in MC_precomputed_t precomp, in instr_stream_
10351041
{
10361042
vec3 generator_rem;
10371043
float generator_pdf;
1038-
irr_glsl_AnisotropicMicrofacetCache microfacet;
1044+
MC_microfacet_t microfacet;
10391045
uint generator_rnpOffset;
10401046
irr_glsl_LightSample s = irr_bsdf_cos_generate(precomp, gcs, rand, generator_rem, generator_pdf, microfacet, generator_rnpOffset);
10411047
eval_and_pdf_t eval_pdf = irr_bsdf_eval_and_pdf(precomp, rnps, generator_rnpOffset, s, microfacet);

include/irr/builtin/material_compiler/glsl/common_declarations.glsl

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include <irr/builtin/glsl/virtual_texturing/extensions.glsl>
55
#include <irr/builtin/glsl/colorspace/encodeCIEXYZ.glsl>
6+
#include <irr/builtin/glsl/bxdf/common.glsl>
67

78
#define instr_t uvec2
89
#define prefetch_instr_t uvec4
@@ -36,6 +37,30 @@ struct MC_precomputed_t
3637
bool frontface;
3738
};
3839

40+
struct MC_microfacet_t
41+
{
42+
irr_glsl_AnisotropicMicrofacetCache inner;
43+
float TdotH2;
44+
float BdotH2;
45+
};
46+
void finalizeMicrofacet(inout MC_microfacet_t mf)
47+
{
48+
mf.TdotH2 = mf.inner.TdotH * mf.inner.TdotH;
49+
mf.BdotH2 = mf.inner.BdotH * mf.inner.BdotH;
50+
}
51+
52+
struct MC_interaction_t
53+
{
54+
irr_glsl_AnisotropicViewSurfaceInteraction inner;
55+
float TdotV2;
56+
float BdotV2;
57+
};
58+
void finalizeInteraction(inout MC_interaction_t i)
59+
{
60+
i.TdotV2 = i.inner.TdotV * i.inner.TdotV;
61+
i.BdotV2 = i.inner.BdotV * i.inner.BdotV;
62+
}
63+
3964
#define ALPHA_EPSILON 1.0e-08
4065

4166
#define CIE_XYZ_Luma_Y_coeffs transpose(irr_glsl_sRGBtoXYZ)[1]

0 commit comments

Comments
 (0)