@@ -474,7 +474,7 @@ parameter_t SContext::getTexture(const CElementTexture* const rootTex, hlsl::flo
474474 transform[1 ][2 ] = bitmap.voffset ;
475475 }
476476 else
477- inner.params .logger .log (" Failed to load bitmap texture for %p with id %s" ,LoggerError,tex,tex ? tex->id .c_str ():" " );
477+ inner.params .logger .log (" Failed to load bitmap texture for %p with id %s from path \" %s \" " ,LoggerError,tex,tex ? tex->id .c_str ():" " ,tex-> bitmap . filename );
478478 }
479479 else
480480 inner.params .logger .log (" Failed to unroll texture scale for %p with id %s" ,LoggerError,rootTex,rootTex ? rootTex->id .c_str ():" " );
@@ -730,6 +730,31 @@ auto SContext::genMaterial(const CElementBSDF* bsdf, system::ISystem* debugFileW
730730 // identical BRDF on the bottom, to have correct multiscatter
731731 layer->brdfBottom = dielectricH;
732732 };
733+
734+ using expr_handle_t = frontend_ir_t ::typed_pointer_type<frontend_ir_t ::IExprNode>;
735+ auto createWeightedSum = [&](frontend_ir_t ::CLayer* out, material_t A, const expr_handle_t w0, material_t B, const expr_handle_t w1)->void
736+ {
737+ while (true )
738+ {
739+ auto * const a = frontPool.deref (A);
740+ auto * const b = frontPool.deref (B);
741+ // I don't actually need to check if the child Expressions are non-empty, the CFrontendIR utilities nicely carry through NOOPs
742+ out->brdfTop = frontIR->createWeightedSum (a ? a->brdfTop :expr_handle_t {},w0,b ? b->brdfTop :expr_handle_t {},w1);
743+ out->btdf = frontIR->createWeightedSum (a ? a->btdf :expr_handle_t {},w0,b ? b->btdf :expr_handle_t {},w1);
744+ out->brdfBottom = frontIR->createWeightedSum (a ? a->brdfBottom :expr_handle_t {},w0,b ? b->brdfBottom :expr_handle_t {},w1);
745+ if (a && a->coated || b && b->coated )
746+ {
747+ out = frontPool.deref (out->coated = frontPool.emplace <frontend_ir_t ::CLayer>());
748+ A = a ? a->coated :material_t {};
749+ B = b ? b->coated :material_t {};
750+ }
751+ else
752+ {
753+ out->coated = {};
754+ break ;
755+ }
756+ }
757+ };
733758
734759 struct SEntry
735760 {
@@ -832,7 +857,7 @@ auto SContext::genMaterial(const CElementBSDF* bsdf, system::ISystem* debugFileW
832857 {
833858 // want a specularTransmittance instead of SpecularReflectance factor
834859 const auto factorH = createFactorNode (_bsdf->dielectric .specularTransmittance ,ECommonDebug::MitsubaExtraFactor);
835- frontend_ir_t ::typed_pointer_type< frontend_ir_t ::IExprNode> btdfH;
860+ expr_handle_t btdfH;
836861 {
837862 const auto * const brdf = frontPool.deref (brdfH);
838863 // make the trans node refraction-less for thin dielectric and apply thin scattering correction to the transmissive fresnel
@@ -1037,23 +1062,35 @@ auto SContext::genMaterial(const CElementBSDF* bsdf, system::ISystem* debugFileW
10371062 }
10381063 case CElementBSDF::MIXTURE_BSDF:
10391064 {
1040- assert (false ); // unimplemented
1065+ const auto mixH = frontPool.emplace <frontend_ir_t ::CLayer>();
1066+ auto * const mix = frontPool.deref (mixH);
1067+ const uint8_t realChildCount = hlsl::min<uint8_t >(childCount,_bsdf->mixturebsdf .weightCount );
1068+ const auto firstH = realChildCount>=1 ? getChildFromCache (_bsdf->mixturebsdf .bsdf [0 ]):frontend_ir_t ::typed_pointer_type<frontend_ir_t ::CLayer>{};
1069+ spectral_var_t ::SCreationParams<1 > firstParams = {};
1070+ firstParams.knots .params [0 ].scale = _bsdf->mixturebsdf .weights [0 ];
1071+ const auto firstWeightH = frontPool.emplace <frontend_ir_t ::CSpectralVariable>(std::move (firstParams));
1072+ if (realChildCount<2 )
1073+ createWeightedSum (mix,firstH,firstWeightH,{},{});
1074+ else
1075+ for (uint8_t c=1 ; c<realChildCount; c++)
1076+ {
1077+ const auto otherH = getChildFromCache (_bsdf->mixturebsdf .bsdf [c]);
1078+ spectral_var_t ::SCreationParams<1 > params = {};
1079+ params.knots .params [0 ].scale = _bsdf->mixturebsdf .weights [c];
1080+ // don't feel like spending time on this, since its never used, trust CTrueIR optimizer to remove this during canonicalization
1081+ createWeightedSum (mix,mixH,unityFactor._const_cast (),otherH,frontPool.emplace <frontend_ir_t ::CSpectralVariable>(std::move (params)));
1082+ }
1083+ newMaterialH = mixH;
10411084 break ;
10421085 }
10431086 case CElementBSDF::BLEND_BSDF:
10441087 {
10451088 const auto blendH = frontPool.emplace <frontend_ir_t ::CLayer>();
1046- auto * const blend = frontPool.deref (blendH);
10471089 const auto tH = createFactorNode (_bsdf->blendbsdf .weight ,ECommonDebug::Weight);
10481090 const auto tComplementH = frontIR->createComplement (tH);
10491091 const auto loH = getChildFromCache (_bsdf->blendbsdf .bsdf [0 ]);
10501092 const auto hiH = getChildFromCache (_bsdf->blendbsdf .bsdf [1 ]);
1051- const auto * const lo = frontPool.deref (loH);
1052- const auto * const hi = frontPool.deref (hiH);
1053- // I don't actually need to check if the child Expressions are non-empty, the CFrontendIR utilities nicely carry through NOOPs
1054- blend->brdfTop = frontIR->createAdd (frontIR->createMul (lo->brdfTop ,tComplementH),frontIR->createMul (hi->brdfTop ,tH));
1055- blend->btdf = frontIR->createAdd (frontIR->createMul (lo->btdf ,tComplementH),frontIR->createMul (hi->btdf ,tH));
1056- blend->brdfBottom = frontIR->createAdd (frontIR->createMul (lo->brdfBottom ,tComplementH),frontIR->createMul (hi->brdfBottom ,tH));
1093+ createWeightedSum (frontPool.deref (blendH),loH,tComplementH,hiH,tH);
10571094 newMaterialH = blendH;
10581095 break ;
10591096 }
@@ -1239,6 +1276,11 @@ SContext::SContext(
12391276 }
12401277 //
12411278 {
1279+ {
1280+ spectral_var_t ::SCreationParams<1 > params = {};
1281+ params.knots .params [0 ].scale = 1 .f ;
1282+ unityFactor = frontPool.emplace <spectral_var_t >(std::move (params));
1283+ }
12421284 deltaTransmission = frontPool.emplace <frontend_ir_t ::CDeltaTransmission>();
12431285 const auto mulH = frontPool.emplace <frontend_ir_t ::CMul>();
12441286 {
0 commit comments