Skip to content

Commit bf98737

Browse files
author
devsh
committed
do the complex Vegetation BSDF
1 parent 2a6d98c commit bf98737

File tree

1 file changed

+132
-44
lines changed

1 file changed

+132
-44
lines changed

13_MaterialCompilerTest/main.cpp

Lines changed: 132 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -441,82 +441,170 @@ if constexpr (std::is_same_v<decltype(VALUE),bool>) \
441441
ASSERT_VALUE(forest->addMaterial(layerH,logger),true,"ThinDielectric");
442442
}
443443

444-
// plastics with IOR 1.5
444+
// compled materials with coatings with IOR 1.5
445445
{
446-
// make the node everyone shares
446+
// make the nodes everyone shares
447+
const auto roughDiffuseH = forest->_new<CFrontendIR::CMul>();
448+
{
449+
auto* mul = forest->deref(roughDiffuseH);
450+
{
451+
const auto orenNayarH = forest->_new<CFrontendIR::COrenNayar>();
452+
auto* orenNayar = forest->deref(orenNayarH);
453+
orenNayar->ndParams.getRougness()[0].scale = orenNayar->ndParams.getRougness()[1].scale = 0.2f;
454+
mul->lhs = orenNayarH;
455+
}
456+
{
457+
spectral_var_t::SCreationParams<3> params = {};
458+
params.getSemantics() = spectral_var_t::Semantics::Fixed3_SRGB;
459+
params.knots.params[0].scale = 0.9f;
460+
params.knots.params[1].scale = 0.6f;
461+
params.knots.params[2].scale = 0.01f;
462+
const auto albedoH = forest->_new<CFrontendIR::CSpectralVariable>(std::move(params));
463+
forest->deref(albedoH)->debugInfo = forest->_new<CNodePool::CDebugInfo>("Albedo");
464+
mul->rhs = albedoH;
465+
}
466+
}
447467
const auto fresnelH = forest->_new<CFrontendIR::CFresnel>();
448468
{
449469
auto* fresnel = forest->deref(fresnelH);
450470
spectral_var_t::SCreationParams<1> params = {};
451471
params.knots.params[0].scale = 1.5f;
452472
fresnel->orientedRealEta = forest->_new<CFrontendIR::CSpectralVariable>(std::move(params));
453473
}
474+
// the delta layering should optimize out nicely due to the sampling property
475+
const auto transH = forest->_new<CFrontendIR::CMul>();
476+
{
477+
auto* mul = forest->deref(transH);
478+
mul->lhs = forest->_new<CFrontendIR::CDeltaTransmission>();
479+
mul->rhs = fresnelH;
480+
}
481+
// can't attach a copy of the top layer because we'll have a cycle, also the BRDF needs to be on the other side
482+
const auto bottomH = forest->_new<CFrontendIR::CLayer>();
483+
{
484+
auto* bottomLayer = forest->deref(bottomH);
485+
bottomLayer->debugInfo = forest->_new<CNodePool::CDebugInfo>("Rough Coating Copy");
486+
// no brdf on the top of last layer, kill multiscattering
487+
bottomLayer->btdf = transH;
488+
bottomLayer->brdfBottom = dielectricH;
489+
}
454490

455-
// rough plastic
491+
// twosided rough plastic
456492
{
457493
const auto rootH = forest->_new<CFrontendIR::CLayer>();
458494
auto* topLayer = forest->deref(rootH);
459-
topLayer->debugInfo = forest->_new<CNodePool::CDebugInfo>("Rough Plastic");
495+
topLayer->debugInfo = forest->_new<CNodePool::CDebugInfo>("Twosided Rough Plastic");
460496

461497
topLayer->brdfTop = dielectricH;
462-
// the delta layering should optimize out nicely due to the sampling property
463-
const auto transH = forest->_new<CFrontendIR::CMul>();
464-
{
465-
auto* mul = forest->deref(transH);
466-
mul->lhs = forest->_new<CFrontendIR::CDeltaTransmission>();
467-
mul->rhs = fresnelH;
468-
}
469498
topLayer->btdf = transH;
499+
// no brdf on the bottom of first layer, kill multiscattering
470500

471501
const auto diffuseH = forest->_new<CFrontendIR::CLayer>();
472502
auto* midLayer = forest->deref(diffuseH);
473503
{
474-
const auto mulH = forest->_new<CFrontendIR::CMul>();
475-
{
476-
auto* mul = forest->deref(mulH);
477-
{
478-
const auto orenNayarH = forest->_new<CFrontendIR::COrenNayar>();
479-
auto* orenNayar = forest->deref(orenNayarH);
480-
orenNayar->ndParams.getRougness()[0].scale = orenNayar->ndParams.getRougness()[1].scale = 0.2f;
481-
mul->lhs = orenNayarH;
482-
}
483-
{
484-
spectral_var_t::SCreationParams<3> params = {};
485-
params.getSemantics() = spectral_var_t::Semantics::Fixed3_SRGB;
486-
params.knots.params[0].scale = 0.9f;
487-
params.knots.params[1].scale = 0.6f;
488-
params.knots.params[2].scale = 0.01f;
489-
const auto albedoH = forest->_new<CFrontendIR::CSpectralVariable>(std::move(params));
490-
forest->deref(albedoH)->debugInfo = forest->_new<CNodePool::CDebugInfo>("Albedo");
491-
mul->rhs = albedoH;
492-
}
493-
}
494-
midLayer->brdfTop = mulH;
504+
midLayer->brdfTop = roughDiffuseH;
495505
// no transmission in the mid-layer, the backend needs to decompose into separate front/back materials
496-
midLayer->brdfBottom = mulH;
497-
498-
// can't attach a copy of the top layer because we'll have a cycle, also the BRDF needs to be on the other side
499-
const auto bottomH = forest->_new<CFrontendIR::CLayer>();
500-
{
501-
auto* bottomLayer = forest->deref(bottomH);
502-
bottomLayer->debugInfo = forest->_new<CNodePool::CDebugInfo>("Rough Plastic Copy");
503-
bottomLayer->brdfBottom = dielectricH;
504-
}
506+
midLayer->brdfBottom = roughDiffuseH;
505507
midLayer->coated = bottomH;
506508
}
507509
topLayer->coated = diffuseH;
508510

509511
ASSERT_VALUE(forest->addMaterial(rootH,logger),true,"Twosided Rough Plastic");
510512
}
511513

514+
// Diffuse transmitter normalized to whoel sphere
515+
const auto roughDiffTransH = forest->_new<CFrontendIR::CMul>();
516+
{
517+
// normalize the Oren Nayar over the full sphere
518+
auto* mul = forest->deref(roughDiffTransH);
519+
mul->lhs = roughDiffuseH;
520+
{
521+
spectral_var_t::SCreationParams<1> params = {};
522+
params.knots.params[0].scale = 0.5f;
523+
mul->rhs = forest->_new<CFrontendIR::CSpectralVariable>(std::move(params));
524+
}
525+
}
526+
512527
// coated diffuse transmitter
513528
{
514-
//
529+
const auto rootH = forest->_new<CFrontendIR::CLayer>();
530+
auto* topLayer = forest->deref(rootH);
531+
topLayer->debugInfo = forest->_new<CNodePool::CDebugInfo>("Coated Diffuse Transmitter");
532+
533+
topLayer->brdfTop = dielectricH;
534+
topLayer->btdf = transH;
535+
// no brdf on the bottom of first layer, kill multiscattering
536+
537+
const auto midH = forest->_new<CFrontendIR::CLayer>();
538+
auto* midLayer = forest->deref(midH);
539+
{
540+
midLayer->brdfTop = roughDiffTransH;
541+
midLayer->btdf = roughDiffTransH;
542+
midLayer->brdfBottom = roughDiffTransH;
543+
544+
// we could even have a BSDF with a different Fresnel and Roughness on the bottom layer!
545+
midLayer->coated = bottomH;
546+
}
547+
topLayer->coated = midH;
548+
549+
ASSERT_VALUE(forest->addMaterial(rootH,logger),true,"Coated Diffuse Transmitter");
515550
}
516551

517-
// same thing but with subsurface beer scattering
552+
// same thing but with subsurface beer absorption
518553
{
519-
//
554+
const auto rootH = forest->_new<CFrontendIR::CLayer>();
555+
auto* topLayer = forest->deref(rootH);
556+
topLayer->debugInfo = forest->_new<CNodePool::CDebugInfo>("Coated Diffuse Extinction Transmitter");
557+
558+
// we have a choice of where to stick the Beer Absorption:
559+
// - on the BTDF of the outside layer, means that it will be applied to the transmission so twice according to VdotN and LdotN
560+
// (but delta transmission makes special weight nodes behave in a special and only once because `L=-V` is forced in a single scattering)
561+
// - inner layer BRDF or BTDF but thats intractable for most compiler backends because the `L` and `V` in the internal layers are not trivially known
562+
// unless the previous layers are delta distributions (in which case we can equivalently hoist beer to the previous layer).
563+
const auto beerH = forest->_new<CFrontendIR::CBeer>();
564+
{
565+
auto* beer = forest->deref(beerH);
566+
spectral_var_t::SCreationParams<3> params = {};
567+
params.getSemantics() = spectral_var_t::Semantics::Fixed3_SRGB;
568+
params.knots.params[0].scale = 0.3f;
569+
params.knots.params[1].scale = 0.9f;
570+
params.knots.params[2].scale = 0.7f;
571+
beer->perpTransparency = forest->_new<spectral_var_t>(std::move(params));
572+
}
573+
574+
topLayer->brdfTop = dielectricH;
575+
// simplest/recommended
576+
{
577+
const auto transAbsorbH = forest->_new<CFrontendIR::CMul>();
578+
auto* transAbsorb = forest->deref(transAbsorbH);
579+
transAbsorb->lhs = transH;
580+
{
581+
transAbsorb->rhs = beerH;
582+
}
583+
topLayer->btdf = transAbsorbH;
584+
}
585+
586+
const auto midH = forest->_new<CFrontendIR::CLayer>();
587+
auto* midLayer = forest->deref(midH);
588+
{
589+
midLayer->brdfTop = roughDiffTransH;
590+
midLayer->btdf = roughDiffTransH;
591+
// making extra work for our canonicalizer
592+
{
593+
const auto roughAbsorbH = forest->_new<CFrontendIR::CMul>();
594+
auto* transAbsorb = forest->deref(roughAbsorbH);
595+
transAbsorb->lhs = roughDiffTransH;
596+
{
597+
transAbsorb->rhs = beerH;
598+
}
599+
midLayer->brdfBottom = roughAbsorbH;
600+
}
601+
602+
// we could even have a BSDF with a different Fresnel and Roughness on the bottom layer!
603+
midLayer->coated = bottomH;
604+
}
605+
topLayer->coated = midH;
606+
607+
ASSERT_VALUE(forest->addMaterial(rootH,logger),true,"Coated Diffuse Extinction Transmitter");
520608
}
521609
}
522610

0 commit comments

Comments
 (0)