@@ -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
0 commit comments