Skip to content

Commit bc2295b

Browse files
make things compile nicely and differentiate BTDF and BRDF
1 parent bf7d846 commit bc2295b

4 files changed

Lines changed: 77 additions & 39 deletions

File tree

include/nbl/asset/material_compiler3/CFrontendIR.h

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ class CFrontendIR final : public CNodePool
215215
protected:
216216
friend class CFrontendIR;
217217
using ir_contributor_handle_t = CTrueIR::typed_pointer_type<CTrueIR::IContributor>;
218-
virtual ir_contributor_handle_t createIRNode(const CFrontendIR* ast, CTrueIR* ir) const = 0;
218+
virtual ir_contributor_handle_t createIRNode(const bool forBTDF, const CFrontendIR* ast, CTrueIR* ir) const = 0;
219219
};
220220

221221
// This node could also represent non directional emission, but we have another node for that
@@ -263,6 +263,9 @@ class CFrontendIR final : public CNodePool
263263
}
264264

265265
// encapsulation due to padding abuse
266+
inline auto& uvTransform() {return pWonky()->knots.uvTransform;}
267+
inline const auto& uvTransform() const {return pWonky()->knots.uvTransform;}
268+
266269
inline uint8_t& uvSlot() {return pWonky()->knots.uvSlot();}
267270
inline const uint8_t& uvSlot() const {return pWonky()->knots.uvSlot();}
268271

@@ -444,7 +447,7 @@ class CFrontendIR final : public CNodePool
444447

445448
NBL_API2 void printDot(std::ostringstream& sstr, const core::string& selfID) const override;
446449

447-
NBL_API2 ir_contributor_handle_t createIRNode(const CFrontendIR* ast, CTrueIR* ir) const;
450+
NBL_API2 ir_contributor_handle_t createIRNode(const bool forBTDF, const CFrontendIR* ast, CTrueIR* ir) const;
448451
};
449452
//! Special nodes meant to be used as `CMul::rhs`, their behaviour depends on the IContributor in its MUL node relative subgraph.
450453
//! If you use a different contributor node type or normal for shading, these nodes get split and duplicated into two in our Final IR.
@@ -616,7 +619,7 @@ class CFrontendIR final : public CNodePool
616619
protected:
617620
COPY_DEFAULT_IMPL
618621

619-
NBL_API2 ir_contributor_handle_t createIRNode(const CFrontendIR* ast, CTrueIR* ir) const;
622+
NBL_API2 ir_contributor_handle_t createIRNode(const bool forBTDF, const CFrontendIR* ast, CTrueIR* ir) const;
620623
};
621624
//! Because of Schussler et. al 2017 every one of these nodes splits into 2 (if no L dependence) or 3 during canonicalization
622625
// Base diffuse node
@@ -639,7 +642,7 @@ class CFrontendIR final : public CNodePool
639642

640643
NBL_API2 void printDot(std::ostringstream& sstr, const core::string& selfID) const override;
641644

642-
NBL_API2 ir_contributor_handle_t createIRNode(const CFrontendIR* ast, CTrueIR* ir) const;
645+
NBL_API2 ir_contributor_handle_t createIRNode(const bool forBTDF, const CFrontendIR* ast, CTrueIR* ir) const;
643646
};
644647
// Supports anisotropy for all models
645648
class CCookTorrance final : public IBxDF
@@ -682,7 +685,7 @@ class CFrontendIR final : public CNodePool
682685
inline std::string_view getChildName_impl(const uint8_t ix) const override {return "Oriented η";}
683686
NBL_API2 void printDot(std::ostringstream& sstr, const core::string& selfID) const override;
684687

685-
NBL_API2 ir_contributor_handle_t createIRNode(const CFrontendIR* ast, CTrueIR* ir) const;
688+
NBL_API2 ir_contributor_handle_t createIRNode(const bool forBTDF, const CFrontendIR* ast, CTrueIR* ir) const;
686689
};
687690
#undef COPY_DEFAULT_IMPL
688691
#undef TYPE_NAME_STR
@@ -872,6 +875,7 @@ class CFrontendIR final : public CNodePool
872875
core::smart_refctd_ptr<CTrueIR> tmpIR;
873876
// changes dynamically
874877
const CFrontendIR* srcAST;
878+
bool btdfSubtree = false;
875879
// for going over layers in the AST
876880
core::vector<const CLayer*> layerStack;
877881
// Some of the things we must canonicalize:

include/nbl/asset/material_compiler3/CTrueIR.h

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -455,9 +455,10 @@ class CTrueIR : public CNodePool // TODO: turn into an asset!
455455
hasher << paramSet;
456456
if constexpr (SpectralBins>1)
457457
{
458-
if (!getSemantics()==ESemantics::NoneUndefined)
458+
const ESemantics semantics = getSemantics<SpectralBins>();
459+
if (semantics!=ESemantics::NoneUndefined)
459460
return false;
460-
hasher << getSemantics();
461+
hasher << semantics;
461462
}
462463
return true;
463464
}
@@ -485,7 +486,7 @@ class CTrueIR : public CNodePool // TODO: turn into an asset!
485486
inline CSpectralVariable()
486487
{
487488
if constexpr (SpectralBins>1)
488-
setSemantics(ESemantics::Fixed3_SRGB);
489+
setSemantics<SpectralBins>(ESemantics::Fixed3_SRGB);
489490
}
490491

491492
SParameterSet<SpectralBins> paramSet = {};
@@ -680,13 +681,12 @@ class CTrueIR : public CNodePool // TODO: turn into an asset!
680681
NotBlackhole = 0x1u<<0, // actually have a material
681682
NonDelta = 0x1u<<1, // can evaluate against point lights (or other samplings)
682683
DeltaTransmissive = 0x1u<<2, // can use stochastic transparency for closest hit rays and blending for anyhit
683-
Emissive = 0x1u<<3, // maybe register for NEE, but definitely grab the emission
684-
NonSpatiallyVaryingEmissive = 0x1u<<4, // definitely register for NEE
685-
// TODO: 5,6 left
684+
NonSpatiallyVaryingEmissive = 0x1u<<3, // definitely register for NEE
685+
SpatiallyVaryingEmissive = 0x1u<<4, // maybe register for NEE but needs different kind of NEE
686+
// TODO: 5,6,7 left
686687
// Bits that help us remove expensive code from impl
687-
DerivativeMap = 0x1u<<7,
688-
DirectionallyVaryingEmissive = 0x1u<<8, // IES profile
689-
SpatiallyVaryingEmissive = 0x1u<<9, // textured light
688+
DerivativeMap = 0x1u<<8,
689+
DirectionallyVaryingEmissive = 0x1u<<9, // IES profile
690690
Lambertian = 0x1u<<10,
691691
OrenNayar = 0x1u<<11,
692692
GGX = 0x1u<<12,

src/nbl/asset/material_compiler3/CFrontendIR.cpp

Lines changed: 58 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -549,8 +549,9 @@ void CFrontendIR::CCookTorrance::printDot(std::ostringstream& sstr, const core::
549549
}
550550

551551
//! AST-> IR methods
552-
auto CFrontendIR::CEmitter::createIRNode(const CFrontendIR* ast, CTrueIR* ir) const -> ir_contributor_handle_t
552+
auto CFrontendIR::CEmitter::createIRNode(const bool forBTDF, const CFrontendIR* ast, CTrueIR* ir) const -> ir_contributor_handle_t
553553
{
554+
assert(!forBTDF);
554555
auto& irPool = ir->getObjectPool();
555556
const auto retval = irPool.emplace<CTrueIR::CEmitter>();
556557
if (auto* const contributor=irPool.deref(retval))
@@ -561,12 +562,13 @@ auto CFrontendIR::CEmitter::createIRNode(const CFrontendIR* ast, CTrueIR* ir) co
561562
return retval;
562563
}
563564

564-
auto CFrontendIR::CDeltaTransmission::createIRNode(const CFrontendIR* ast, CTrueIR* ir) const -> ir_contributor_handle_t
565+
auto CFrontendIR::CDeltaTransmission::createIRNode(const bool forBTDF, const CFrontendIR* ast, CTrueIR* ir) const -> ir_contributor_handle_t
565566
{
567+
assert(forBTDF);
566568
return ir->getObjectPool().emplace<CTrueIR::CDeltaTransmission>();
567569
}
568570

569-
auto CFrontendIR::COrenNayar::createIRNode(const CFrontendIR* ast, CTrueIR* ir) const -> ir_contributor_handle_t
571+
auto CFrontendIR::COrenNayar::createIRNode(const bool forBTDF, const CFrontendIR* ast, CTrueIR* ir) const -> ir_contributor_handle_t
570572
{
571573
if (ndParams.getDistribution()!=CTrueIR::SBasicNDFParams::EDistribution::Invalid)
572574
return {};
@@ -577,20 +579,44 @@ auto CFrontendIR::COrenNayar::createIRNode(const CFrontendIR* ast, CTrueIR* ir)
577579
return retval;
578580
}
579581

580-
auto CFrontendIR::CCookTorrance::createIRNode(const CFrontendIR* ast, CTrueIR* ir) const -> ir_contributor_handle_t
582+
auto CFrontendIR::CCookTorrance::createIRNode(const bool forBTDF, const CFrontendIR* ast, CTrueIR* ir) const -> ir_contributor_handle_t
581583
{
582584
if (ndParams.getDistribution()>CTrueIR::SBasicNDFParams::EDistribution::Beckmann)
583585
return {};
584586
auto& irPool = ir->getObjectPool();
585587
CTrueIR::typed_pointer_type<const CTrueIR::ISpectralVariable> etaH = {};
586-
#if 0 // TODO: pass the transmission info
587-
if (isBTDF)
588+
if (forBTDF)
588589
{
589-
etaH = irPool.emplace<CTrueIR::CSpectralVariable<>>();
590-
if (!etaH)
590+
if (!orientedRealEta)
591591
return {};
592+
const auto* const srcEta = ast->getObjectPool().deref(orientedRealEta);
593+
switch (srcEta->getSemantics())
594+
{
595+
case CSpectralVariable::semantics_e::NoneUndefined:
596+
{
597+
assert(srcEta->getKnotCount()==1);
598+
const auto handle = irPool.emplace<CTrueIR::CSpectralVariable<1>>();
599+
auto* const dstEta = irPool.deref(handle);
600+
if (!dstEta)
601+
return {};
602+
dstEta->paramSet.uvTransform = srcEta->uvTransform();
603+
dstEta->paramSet.params[0] = *srcEta->getParam(0);
604+
break;
605+
}
606+
default:
607+
{
608+
assert(srcEta->getKnotCount()==3);
609+
const auto handle = irPool.emplace<CTrueIR::CSpectralVariable<3>>();
610+
auto* const dstEta = irPool.deref(handle);
611+
if (!dstEta)
612+
return {};
613+
dstEta->paramSet.uvTransform = srcEta->uvTransform();
614+
for (auto i=0; i<3; i++)
615+
dstEta->paramSet.params[i] = *srcEta->getParam(i);
616+
break;
617+
}
618+
}
592619
}
593-
#endif
594620
const auto retval = irPool.emplace<CTrueIR::CCookTorrance>();
595621
if (auto* const ct=irPool.deref(retval); ct)
596622
{
@@ -607,6 +633,7 @@ auto CFrontendIR::SAdd2IRSession::makeOrientedMaterial(const CFrontendIR::typed_
607633
srcAST = _srcAST;
608634
const auto& astPool = srcAST->getObjectPool();
609635
assert(layerStack.empty());
636+
auto clearLayerStackOnExit = core::makeRAIIExiter([this]()->void{layerStack.clear();});
610637

611638
auto& irPool = tmpIR->getObjectPool();
612639
// go down through layers and enqueue them so the layers can be added in reverse
@@ -618,17 +645,20 @@ auto CFrontendIR::SAdd2IRSession::makeOrientedMaterial(const CFrontendIR::typed_
618645
// if there's literally nothing on the top level, you can't get to the next layer to retroreflect from it
619646
if (noTopReflection && noTransmission)
620647
{
621-
args.logger.log("Skipping current layer and farther ones due to no transmission and reflection",ELL_DEBUG);
648+
if (layer->coated)
649+
args.logger.log("Skipping current layer and farther ones due to no transmission and reflection",ELL_DEBUG);
622650
break;
623651
}
624652
layerStack.push_back(layer);
625653
// find out rest of the layers don't matter because they're blocked from being seen, its not a complete check
626654
if (noTransmission)
627655
{
628-
args.logger.log("Skipping remaining layers due to no transmission",ELL_DEBUG);
656+
if (layer->coated)
657+
args.logger.log("Skipping remaining layers due to no transmission",ELL_DEBUG);
629658
break;
630659
}
631660
}
661+
const auto errorBxDF = tmpIR->getBasicNodes().errorBxDF;
632662
// Some metadata needed for us
633663
bool layersBelowCanScatterBack = false;
634664
CTrueIR::typed_pointer_type<CTrueIR::COrientedLayer> prevLayerH = {};
@@ -642,18 +672,28 @@ auto CFrontendIR::SAdd2IRSession::makeOrientedMaterial(const CFrontendIR::typed_
642672
auto* const outLayer = irPool.deref(layerH);
643673
// process the top BRDF
644674
outLayer->brdfTop = makeContributors(inLayer->brdfTop);
675+
if (outLayer->brdfTop==errorBxDF)
676+
return {}; // TODO: error material
645677
// process the BTDF
678+
btdfSubtree = true;
646679
const auto btdfH = makeContributors(inLayer->btdf);
680+
btdfSubtree = false;
647681
// because we're oriented, the bottom brdf can't exist without a BTDF on top (there's no ray that can reach it from our oriented side)
648682
if (btdfH)
649683
{
684+
if (btdfH==errorBxDF)
685+
return {}; // TODO: error material
650686
const auto transmissionH = irPool.emplace<CTrueIR::CCorellatedTransmission>();
651687
{
652688
auto* const transmission = irPool.deref(transmissionH);
653689
transmission->btdf = btdfH;
654690
// Only if we have a layer below us capable of reflecting the ray back, do we care about the bottom BRDF (you can't hit it otherwise)
655691
if (layersBelowCanScatterBack)
692+
{
656693
transmission->brdfBottom = makeContributors(inLayer->brdfBottom);
694+
if (transmission->brdfBottom==errorBxDF)
695+
return {}; // TODO: error material
696+
}
657697
// we check if previous layer didn't get oprimized away, but we don't add its optimized version because don't want pointers across two pools (crash)
658698
if (retval.root)
659699
transmission->coated = prevLayerH;
@@ -683,7 +723,6 @@ auto CFrontendIR::SAdd2IRSession::makeOrientedMaterial(const CFrontendIR::typed_
683723
layersBelowCanScatterBack = false;
684724
}
685725
}
686-
layerStack.clear();
687726
// last touch ups
688727
if (retval.root)
689728
{
@@ -726,16 +765,6 @@ auto CFrontendIR::SAdd2IRSession::makeContributors(const CFrontendIR::typed_poin
726765
contributor_sum_handle_t tailH = {};
727766
while (!exprStack.empty())
728767
{
729-
// how to report an error
730-
#if 0
731-
{
732-
args.logger.log("MESSAGE",ELL_ERROR);
733-
exprStack.clear();
734-
mulChain.clear();
735-
contributorStack.clear();
736-
return tmpIR->getBasicNodes().errorBxDF;
737-
}
738-
#endif
739768
auto& entry = exprStack.back();
740769
const auto* const node = astPool.deref(entry.nodeH);
741770
using ast_expr_type_e = CFrontendIR::IExprNode::Type;
@@ -746,13 +775,17 @@ auto CFrontendIR::SAdd2IRSession::makeContributors(const CFrontendIR::typed_poin
746775
{
747776
if (isContributor)
748777
{
749-
const auto contributorH = static_cast<const IContributor*>(node)->createIRNode(srcAST,tmpIR.get());
778+
const auto contributorH = static_cast<const IContributor*>(node)->createIRNode(btdfSubtree,srcAST,tmpIR.get());
750779
// TODO: recompute instead of compute
751780
if (!contributorH || irPool.deref(contributorH)->computeHash(irPool)==core::blake3_hash_t{})
752781
{
753782
args.logger.log("Failed to Create IR Contributor from AST",ELL_ERROR);
754783
printSubtree(entry.nodeH);
755-
assert(false); // unimplemented
784+
// no point pushing an error contributor, don't want a best effort compilation within a layer, don't want contributors missing or substituted
785+
exprStack.clear();
786+
mulChain.clear();
787+
contributorStack.clear();
788+
return tmpIR->getBasicNodes().errorBxDF;
756789
}
757790
contributorStack.push_back({.contributor=contributorH});
758791
exprStack.pop_back();
@@ -882,6 +915,7 @@ CTrueIR::SMaterialHandle CFrontendIR::makeFinalIR(const typed_pointer_type<const
882915
{
883916
const auto& astPool = getObjectPool();
884917

918+
// TODO
885919
// core::unordered_map<const CFrontendIR::IExprNode*,bool> brdfs;
886920
// core::unordered_map<const CFrontendIR::IExprNode*,bool> btdfs;
887921

src/nbl/asset/material_compiler3/CTrueIR.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ CTrueIR::SBasicNodes::SBasicNodes(CTrueIR* ir)
8787
bool CTrueIR::rewrite(SMaterial& material, CTrueIR* srcIR)
8888
{
8989
// TODO: hash, deduplicate, collect metadata and insert into current IR
90-
return true;
90+
return false;
9191
}
9292

9393

0 commit comments

Comments
 (0)