@@ -466,7 +466,7 @@ parameter_t SContext::getTexture(const CElementTexture* const rootTex, hlsl::flo
466466 params.AnisotropicFilter = core::max (hlsl::findMSB<uint32_t >(bitmap.maxAnisotropy ),1u );
467467 // TODO: embed the gamma in the material compiler Frontend
468468 // or adjust gamma on pixels (painful and long process)
469- assert (std::isnan (bitmap.gamma ));
469+ // assert(std::isnan(bitmap.gamma));
470470 auto & transform = *outUvTransform;
471471 transform[0 ][0 ] = bitmap.uscale ;
472472 transform[0 ][2 ] = bitmap.uoffset ;
@@ -617,6 +617,7 @@ auto SContext::genProfile(const CElementEmissionProfile* profile) -> frontend_ir
617617 return retval;
618618}
619619
620+ // TODO: include source debug information / location, e.g. XML path, line and column in the nodes
620621auto SContext::genMaterial (const CElementBSDF* bsdf, system::ISystem* debugFileWriter) -> frontend_material_t
621622{
622623 auto & frontPool = frontIR->getObjectPool ();
@@ -632,6 +633,12 @@ auto SContext::genMaterial(const CElementBSDF* bsdf, system::ISystem* debugFileW
632633 frontPool.deref (factorH)->debugInfo = commonDebugNames[uint16_t (debug)]._const_cast ();
633634 return factorH;
634635 };
636+
637+ struct SDerivativeMap
638+ {
639+ // TODO: derivative map SParameter[2]
640+ };
641+ // TODO: take `SParameter[2]` for the derivative maps
635642 auto createCookTorrance = [&](const CElementBSDF::RoughSpecularBase* base, const frontend_ir_t ::typed_pointer_type<frontend_ir_t ::CFresnel> fresnelH, const CElementTexture::SpectrumOrTexture& specularReflectance)->auto
636643 {
637644 const auto mulH = frontPool.emplace <frontend_ir_t ::CMul>();
@@ -660,6 +667,7 @@ auto SContext::genMaterial(const CElementBSDF* bsdf, system::ISystem* debugFileW
660667 // TODO: check if UV transform is the same and warn if not
661668 getParameters ({roughness.data ()+1 ,1 },base->alphaV );
662669 }
670+ // TODO: derivative maps
663671 }
664672 else
665673 roughness[0 ].scale = roughness[1 ].scale = 0 .f ;
@@ -687,6 +695,7 @@ auto SContext::genMaterial(const CElementBSDF* bsdf, system::ISystem* debugFileW
687695 // TODO: check if UV transform is the same and warn if not
688696 getParameters ({roughness.data ()+1 ,1 },alphaV);
689697 }
698+ // TODO: derivative maps
690699 }
691700 return frontIR->createMul (orenNayarH,factorH);
692701 };
@@ -699,7 +708,10 @@ auto SContext::genMaterial(const CElementBSDF* bsdf, system::ISystem* debugFileW
699708 const auto transH = frontPool.emplace <frontend_ir_t ::CMul>();
700709 {
701710 auto * const trans = frontPool.deref (transH);
702- trans->lhs = frontIR->createMul (deltaTransmission._const_cast (),extinctionH);
711+ if (extinctionH)
712+ trans->lhs = frontIR->createMul (deltaTransmission._const_cast (),extinctionH);
713+ else
714+ trans->lhs = deltaTransmission._const_cast ();
703715 const auto factorH = createFactorNode (element.specularTransmittance ,ECommonDebug::MitsubaExtraFactor);
704716 trans->rhs = frontIR->createMul (fresnelH,factorH);
705717 }
@@ -708,10 +720,23 @@ auto SContext::genMaterial(const CElementBSDF* bsdf, system::ISystem* debugFileW
708720 layer->brdfBottom = dielectricH;
709721 };
710722
711- using bxdf_t = frontend_ir_t ::typed_pointer_type<frontend_ir_t ::IExprNode>;
723+ struct SEntry
724+ {
725+ inline bool operator ==(const SEntry& other) const {return bsdf==other.bsdf ;}
726+
727+ const CElementBSDF* bsdf;
728+ // SDerivativeMap derivMap;
729+ };
730+ struct HashEntry
731+ {
732+ inline size_t operator ()(const SEntry& entry) const {return std::hash<const void *>()(entry.bsdf );}
733+ };
734+ core::unordered_map<SEntry,material_t ,HashEntry> localCache;
735+ localCache.reserve (16 );
712736 // the layer returned will never have a bottom BRDF
713- auto createMistubaLeaf = [&](const CElementBSDF* _bsdf /* TODO: debug source information */ )->frontend_ir_t ::typed_pointer_type<frontend_ir_t ::CLayer>
737+ auto createMistubaLeaf = [&](const SEntry& entry )->frontend_ir_t ::typed_pointer_type<frontend_ir_t ::CLayer>
714738 {
739+ const CElementBSDF* _bsdf = entry.bsdf ;
715740 auto retval = frontPool.emplace <frontend_ir_t ::CLayer>();
716741 auto * leaf = frontPool.deref (retval);
717742 switch (_bsdf->type )
@@ -796,7 +821,7 @@ auto SContext::genMaterial(const CElementBSDF* bsdf, system::ISystem* debugFileW
796821 {
797822 // want a specularTransmittance instead of SpecularReflectance factor
798823 const auto factorH = createFactorNode (_bsdf->dielectric .specularTransmittance ,ECommonDebug::MitsubaExtraFactor);
799- bxdf_t btdfH;
824+ frontend_ir_t ::typed_pointer_type< frontend_ir_t ::IExprNode> btdfH;
800825 {
801826 const auto * const brdf = frontPool.deref (brdfH);
802827 // make the trans node refraction-less for thin dielectric and apply thin scattering correction to the transmissive fresnel
@@ -886,21 +911,18 @@ auto SContext::genMaterial(const CElementBSDF* bsdf, system::ISystem* debugFileW
886911 // Post-order Depth First Traversal (create children first, then create parent)
887912 struct SStackEntry
888913 {
889- const CElementBSDF* bsdf;
890- uint64_t visited : 1 = false ;
891- uint64_t unused : 63 = 0 ;
914+ SEntry immutable;
915+ bool visited = false ;
892916 };
893917 core::vector<SStackEntry> stack;
894918 stack.reserve (128 );
895- stack.emplace_back () = {.bsdf =bsdf};
896- // for the static casts of handles
897- core::unordered_map<const CElementBSDF*,material_t > localCache;
898- localCache.reserve (16 );
919+ stack.emplace_back () = {.immutable ={.bsdf =bsdf}};
899920 //
921+ frontend_ir_t ::typed_pointer_type<frontend_ir_t ::CLayer> rootH = {};
900922 while (!stack.empty ())
901923 {
902924 auto & entry = stack.back ();
903- const auto * const _bsdf = entry.bsdf ;
925+ const auto * const _bsdf = entry.immutable . bsdf ;
904926 assert (_bsdf);
905927 // we only do post-dfs for non-leafs
906928 if (_bsdf->isMeta () && !entry.visited )
@@ -912,9 +934,14 @@ auto SContext::genMaterial(const CElementBSDF* bsdf, system::ISystem* debugFileW
912934 switch (_bsdf->type )
913935 {
914936 case CElementBSDF::COATING: [[fallthrough]];
915- case CElementBSDF::ROUGHCOATING: [[fallthrough]];
937+ case CElementBSDF::ROUGHCOATING:
938+ assert (meta_common.childCount ==1 );
939+ break ;
916940 case CElementBSDF::BUMPMAP: [[fallthrough]];
917- case CElementBSDF::NORMALMAP: [[fallthrough]];
941+ case CElementBSDF::NORMALMAP:
942+ assert (meta_common.childCount ==1 );
943+ // TODO : create the derivative map and cache it
944+ break ;
918945 case CElementBSDF::MASK:
919946 assert (meta_common.childCount ==1 );
920947 break ;
@@ -930,9 +957,9 @@ auto SContext::genMaterial(const CElementBSDF* bsdf, system::ISystem* debugFileW
930957 assert (false ); // we shouldn't get this case here
931958 break ;
932959 }
933- stack. emplace_back () = {. bsdf =meta_common. bsdf [ 0 ]};
934- for (decltype (meta_common.childCount ) i=1 ; i<meta_common.childCount ; i++)
935- stack.emplace_back () = {.bsdf =meta_common.bsdf [i]};
960+ // TODO : make sure child gets pushed with derivative map info
961+ for (decltype (meta_common.childCount ) i=0 ; i<meta_common.childCount ; i++)
962+ stack.emplace_back () = {.immutable ={. bsdf =meta_common.bsdf [i]} };
936963 }
937964 entry.visited = true ;
938965 }
@@ -942,6 +969,10 @@ auto SContext::genMaterial(const CElementBSDF* bsdf, system::ISystem* debugFileW
942969 if (_bsdf->isMeta ())
943970 {
944971 const auto childCount = _bsdf->meta_common .childCount ;
972+ auto getChildFromCache = [&](const CElementBSDF* child)->frontend_ir_t ::typed_pointer_type<frontend_ir_t ::CLayer>
973+ {
974+ return localCache[{.bsdf =child/* , TODO: copy the current normalmap stuff from entry or self if self is bump map*/ }]._const_cast ();
975+ };
945976 switch (_bsdf->type )
946977 {
947978 case CElementBSDF::COATING: [[fallthrough]];
@@ -962,7 +993,7 @@ auto SContext::genMaterial(const CElementBSDF* bsdf, system::ISystem* debugFileW
962993 }
963994 fillCoatingLayer (coating,_bsdf->coating ,_bsdf->type ==CElementBSDF::ROUGHCOATING,beerH);
964995 // attach the nested as layer
965- coating->coated = localCache[ _bsdf->mask .bsdf [0 ]]. _const_cast ( );
996+ coating->coated = getChildFromCache ( _bsdf->mask .bsdf [0 ]);
966997 newMaterialH = coatingH;
967998 break ;
968999 }
@@ -971,7 +1002,7 @@ auto SContext::genMaterial(const CElementBSDF* bsdf, system::ISystem* debugFileW
9711002 const auto maskH = frontPool.emplace <frontend_ir_t ::CLayer>();
9721003 auto * const mask = frontPool.deref (maskH);
9731004 //
974- const auto nestedH = localCache[ _bsdf->mask .bsdf [0 ]] ;
1005+ const auto nestedH = getChildFromCache ( _bsdf->mask .bsdf [0 ]) ;
9751006 const auto * const nested = frontPool.deref (nestedH);
9761007 assert (nested && nested->brdfTop );
9771008 const auto opacityH = createFactorNode (_bsdf->mask .opacity ,ECommonDebug::Opacity);
@@ -985,15 +1016,12 @@ auto SContext::genMaterial(const CElementBSDF* bsdf, system::ISystem* debugFileW
9851016 mask->brdfBottom = frontIR->createMul (nested->brdfBottom ,opacityH);
9861017 newMaterialH = maskH;
9871018 break ;
988- }
989- case CElementBSDF::BUMPMAP:
990- {
991- assert (false ); // unimplemented
992- break ;
993- }
1019+ }
1020+ case CElementBSDF::BUMPMAP: [[fallthrough]];
9941021 case CElementBSDF::NORMALMAP:
9951022 {
996- assert (false ); // unimplemented
1023+ // we basically ignore and skip because derivative map already applied
1024+ newMaterialH = getChildFromCache (_bsdf->mask .bsdf [0 ]);
9971025 break ;
9981026 }
9991027 case CElementBSDF::MIXTURE_BSDF:
@@ -1008,8 +1036,8 @@ auto SContext::genMaterial(const CElementBSDF* bsdf, system::ISystem* debugFileW
10081036 }
10091037 case CElementBSDF::TWO_SIDED:
10101038 {
1011- const auto origFrontH = localCache[ _bsdf->twosided .bsdf [0 ]] ;
1012- const auto chosenBackH = childCount!=1 ? localCache[ _bsdf->twosided .bsdf [1 ]] :origFrontH;
1039+ const auto origFrontH = getChildFromCache ( _bsdf->twosided .bsdf [0 ]) ;
1040+ const auto chosenBackH = childCount!=1 ? getChildFromCache ( _bsdf->twosided .bsdf [1 ]) :origFrontH;
10131041 // Mitsuba does a mad thing where it will pick the BSDF to use based on NdotV which would normally break the required reciprocity of a BxDF
10141042 // but then it saves the day by disallowing transmission on the combination two BxDFs it layers together. Lets do the same.
10151043 if (const bool firstIsTransmissive=frontIR->transmissive (origFrontH); firstIsTransmissive && (childCount==1 || frontIR->transmissive (chosenBackH)))
@@ -1043,20 +1071,19 @@ auto SContext::genMaterial(const CElementBSDF* bsdf, system::ISystem* debugFileW
10431071 }
10441072 }
10451073 else
1046- newMaterialH = createMistubaLeaf (_bsdf );
1074+ newMaterialH = createMistubaLeaf (entry. immutable );
10471075 if (!newMaterialH)
10481076 newMaterialH = errorMaterial;
1049- localCache[_bsdf ] = newMaterialH;
1077+ localCache[entry. immutable ] = newMaterialH;
10501078 stack.pop_back ();
1079+ if (stack.empty ())
1080+ rootH = newMaterialH._const_cast ();
10511081 }
10521082 }
1053-
1054- const auto found = localCache.find (bsdf);
1055- if (found!=localCache.end ())
1056- return errorMaterial;
1057- const auto rootH = found->second ._const_cast ();
10581083 if (!rootH)
10591084 return errorMaterial;
1085+
1086+ // add debug info
10601087 auto * const root = frontPool.deref (rootH);
10611088 root->debugInfo = frontPool.emplace <frontend_ir_t ::CDebugInfo>(debugName);
10621089
0 commit comments