diff --git a/13_MaterialCompilerTest/main.cpp b/13_MaterialCompilerTest/main.cpp index 9f6238efc..bdba96d29 100644 --- a/13_MaterialCompilerTest/main.cpp +++ b/13_MaterialCompilerTest/main.cpp @@ -5,8 +5,6 @@ #include "nbl/examples/examples.hpp" -//! Temporary, for faster iteration outside of PCH -#include "nbl/asset/material_compiler3/CFrontendIR.h" using namespace nbl; @@ -399,25 +397,16 @@ class MaterialCompilerTest final : public application_templates::MonoDeviceAppli const auto fresnelH = forest->createNamedFresnel("ThF4"); const auto* fresnel = forestPool.deref(fresnelH); - const auto brdfH = forestPool.emplace(); + const auto ctH = forestPool.emplace(); { - auto* mul = forestPool.deref(brdfH); - const auto ctH = forestPool.emplace(); - { - auto* ct = forestPool.deref(ctH); - ct->ndParams.getRougness()[0].scale = ct->ndParams.getRougness()[1].scale = 0.1f; - // ignored for BRDFs, needed for BTDFs - ct->orientedRealEta = fresnel->orientedRealEta; - } - mul->lhs = ctH; - mul->rhs = fresnelH; + auto* ct = forestPool.deref(ctH); + ct->ndParams.getRougness()[0].scale = ct->ndParams.getRougness()[1].scale = 0.1f; + // ignored for BRDFs, needed for BTDFs + ct->orientedRealEta = fresnel->orientedRealEta; + layer->brdfTop = forest->createMul(ctH,fresnelH); } - layer->brdfTop = brdfH; - layer->brdfBottom = brdfH; - - const auto btdfH = forestPool.emplace(); + // the BTDF { - auto* mul = forestPool.deref(btdfH); const auto thinInfiniteScatterH = forestPool.emplace(); { auto* thinInfiniteScatter = forestPool.deref(thinInfiniteScatterH); @@ -425,10 +414,10 @@ class MaterialCompilerTest final : public application_templates::MonoDeviceAppli thinInfiniteScatter->reflectanceBottom = fresnelH; // without extinction } - mul->lhs = forestPool.emplace(); - mul->rhs = thinInfiniteScatterH; + layer->btdf = forest->createMul(forestPool.emplace(),thinInfiniteScatterH); } - layer->btdf = btdfH; + // the interface on top as Air->ThF4, we need interface on bottom to be ThF4->Air so reciprocate te Eta + layer->brdfBottom = forest->createMul(forest->reciprocate(ctH)._const_cast(),fresnelH); { auto* imagEta = forestPool.deref(fresnel->orientedImagEta); @@ -443,7 +432,7 @@ class MaterialCompilerTest final : public application_templates::MonoDeviceAppli ASSERT_VALUE(forest->addMaterial(layerH,logger),true,"ThinDielectric"); } - // compled materials with coatings with IOR 1.5 + // complex materials with coatings with IOR 1.5 { // make the nodes everyone shares const auto roughDiffuseH = forestPool.emplace(); @@ -474,12 +463,7 @@ class MaterialCompilerTest final : public application_templates::MonoDeviceAppli fresnel->orientedRealEta = forestPool.emplace(std::move(params)); } // the delta layering should optimize out nicely due to the sampling property - const auto transH = forestPool.emplace(); - { - auto* mul = forestPool.deref(transH); - mul->lhs = forestPool.emplace(); - mul->rhs = fresnelH; - } + const auto transH = forest->createMul(forestPool.emplace(),fresnelH); // 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 const auto bottomH = forestPool.emplace(); { @@ -487,7 +471,8 @@ class MaterialCompilerTest final : public application_templates::MonoDeviceAppli bottomLayer->debugInfo = forestPool.emplace("Rough Coating Copy"); // no brdf on the top of last layer, kill multiscattering bottomLayer->btdf = transH; - bottomLayer->brdfBottom = dielectricH; + // need the interface to be Air on the bottom, not Glass + bottomLayer->brdfBottom = forest->reciprocate(dielectricH)._const_cast(); } // twosided rough plastic @@ -501,19 +486,19 @@ class MaterialCompilerTest final : public application_templates::MonoDeviceAppli // no brdf on the bottom of first layer, kill multiscattering const auto diffuseH = forestPool.emplace(); - auto* midLayer = forestPool.deref(diffuseH); + topLayer->coated = diffuseH; { + auto* midLayer = forestPool.deref(diffuseH); midLayer->brdfTop = roughDiffuseH; - // no transmission in the mid-layer, the backend needs to decompose into separate front/back materials + // no transmission in the mid-layer, so the backend needs to decompose into separate front/back materials midLayer->brdfBottom = roughDiffuseH; midLayer->coated = bottomH; } - topLayer->coated = diffuseH; ASSERT_VALUE(forest->addMaterial(rootH,logger),true,"Twosided Rough Plastic"); } - // Diffuse transmitter normalized to whoel sphere + // Diffuse transmitter normalized to whole sphere const auto roughDiffTransH = forestPool.emplace(); { // normalize the Oren Nayar over the full sphere @@ -543,7 +528,7 @@ class MaterialCompilerTest final : public application_templates::MonoDeviceAppli midLayer->btdf = roughDiffTransH; midLayer->brdfBottom = roughDiffTransH; - // we could even have a BSDF with a different Fresnel and Roughness on the bottom layer! + // we could even have a BSDF with a different Roughness on the bottom layer! midLayer->coated = bottomH; } topLayer->coated = midH; @@ -556,15 +541,15 @@ class MaterialCompilerTest final : public application_templates::MonoDeviceAppli const auto rootH = forestPool.emplace(); auto* topLayer = forestPool.deref(rootH); topLayer->debugInfo = forestPool.emplace("Coated Diffuse Extinction Transmitter"); - +// TODO: triple check this example Material // we have a choice of where to stick the Beer Absorption: // - on the BTDF of the outside layer, means that it will be applied to the transmission so twice according to VdotN and LdotN // (but delta transmission makes special weight nodes behave in a special and only once because `L=-V` is forced in a single scattering) // - 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 // unless the previous layers are delta distributions (in which case we can equivalently hoist beer to the previous layer). const auto beerH = forestPool.emplace(); + auto* beer = forestPool.deref(beerH); { - auto* beer = forestPool.deref(beerH); spectral_var_t::SCreationParams<3> params = {}; params.getSemantics() = spectral_var_t::Semantics::Fixed3_SRGB; params.knots.params[0].scale = 0.3f; @@ -572,6 +557,11 @@ class MaterialCompilerTest final : public application_templates::MonoDeviceAppli params.knots.params[2].scale = 0.7f; beer->perpTransmittance = forestPool.emplace(std::move(params)); } + { + spectral_var_t::SCreationParams<1> params = {}; + params.knots.params[0].scale = 1.f; + beer->thickness = forestPool.emplace(std::move(params)); + } topLayer->brdfTop = dielectricH; // simplest/recommended @@ -592,13 +582,7 @@ class MaterialCompilerTest final : public application_templates::MonoDeviceAppli midLayer->btdf = roughDiffTransH; // making extra work for our canonicalizer { - const auto roughAbsorbH = forestPool.emplace(); - auto* transAbsorb = forestPool.deref(roughAbsorbH); - transAbsorb->lhs = roughDiffTransH; - { - transAbsorb->rhs = beerH; - } - midLayer->brdfBottom = roughAbsorbH; + midLayer->brdfBottom = forest->createMul(roughDiffTransH,beerH); } // we could even have a BSDF with a different Fresnel and Roughness on the bottom layer! diff --git a/31_HLSLPathTracer/app_resources/hlsl/example_common.hlsl b/31_HLSLPathTracer/app_resources/hlsl/example_common.hlsl index 4e21f0309..a30abfc5b 100644 --- a/31_HLSLPathTracer/app_resources/hlsl/example_common.hlsl +++ b/31_HLSLPathTracer/app_resources/hlsl/example_common.hlsl @@ -85,6 +85,7 @@ struct Ray // mutable scalar_type intersectionT; + uint16_t depth; payload_type payload; using spectral_type = typename payload_type::spectral_type; @@ -132,6 +133,7 @@ struct Ray void setT(scalar_type t) { intersectionT = t; } scalar_type getT() NBL_CONST_MEMBER_FUNC { return intersectionT; } + void setDepth(uint16_t d) { depth = d; } spectral_type getPayloadThroughput() NBL_CONST_MEMBER_FUNC { return payload.throughput; } }; @@ -153,6 +155,7 @@ struct Ray // mutable scalar_type intersectionT; + uint16_t depth; payload_type payload; using spectral_type = typename payload_type::spectral_type; @@ -201,6 +204,7 @@ struct Ray void setT(scalar_type t) { intersectionT = t; } scalar_type getT() NBL_CONST_MEMBER_FUNC { return intersectionT; } + void setDepth(uint16_t d) { depth = d; } vector3_type getPayloadThroughput() NBL_CONST_MEMBER_FUNC { return payload.throughput; } }; @@ -699,7 +703,8 @@ struct PTIsoConfiguration; using sample_type = LS; using spectral_type = Spectrum; - using quotient_pdf_type = sampling::quotient_and_pdf; + using quotient_weight_type = sampling::quotient_and_pdf; + using value_weight_type = sampling::value_and_weight; }; template diff --git a/31_HLSLPathTracer/app_resources/hlsl/material_system.hlsl b/31_HLSLPathTracer/app_resources/hlsl/material_system.hlsl index 9798ad8e8..c45cd426c 100644 --- a/31_HLSLPathTracer/app_resources/hlsl/material_system.hlsl +++ b/31_HLSLPathTracer/app_resources/hlsl/material_system.hlsl @@ -21,7 +21,8 @@ struct MaterialSystem using measure_type = typename DiffuseBxDF::spectral_type; using sample_type = typename DiffuseBxDF::sample_type; using ray_dir_info_type = typename sample_type::ray_dir_info_type; - using quotient_pdf_type = typename DiffuseBxDF::quotient_pdf_type; + using quotient_weight_type = typename DiffuseBxDF::quotient_weight_type; + using value_weight_type = typename DiffuseBxDF::value_weight_type; using anisotropic_interaction_type = typename DiffuseBxDF::anisotropic_interaction_type; using isotropic_interaction_type = typename anisotropic_interaction_type::isotropic_interaction_type; using anisocache_type = typename ConductorBxDF::anisocache_type; @@ -133,7 +134,7 @@ struct MaterialSystem } } - measure_type eval(material_id_type matID, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction) + value_weight_type evalAndWeight(material_id_type matID, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction) { cache_type _cache = getCacheFromSampleInteraction(matID, _sample, interaction); MaterialType matType = (MaterialType)bxdfs[matID.id].materialType; @@ -141,26 +142,29 @@ struct MaterialSystem { case MaterialType::DIFFUSE: { - return bxdfs[matID.id].albedo * _cache.diffuseBxDF.eval(_sample, interaction.isotropic); + typename diffuse_op_type::isocache_type dummycache; + value_weight_type ret = _cache.diffuseBxDF.evalAndWeight(_sample, interaction.isotropic, dummycache); + ret._value *= bxdfs[matID.id].albedo; + return ret; } case MaterialType::CONDUCTOR: { - return _cache.conductorBxDF.eval(_sample, interaction.isotropic, _cache.aniso_cache.iso_cache); + return _cache.conductorBxDF.evalAndWeight(_sample, interaction.isotropic, _cache.aniso_cache.iso_cache); } case MaterialType::DIELECTRIC: { - return _cache.dielectricBxDF.eval(_sample, interaction.isotropic, _cache.aniso_cache.iso_cache); + return _cache.dielectricBxDF.evalAndWeight(_sample, interaction.isotropic, _cache.aniso_cache.iso_cache); } case MaterialType::IRIDESCENT_CONDUCTOR: { - return _cache.iridescentConductorBxDF.eval(_sample, interaction.isotropic, _cache.aniso_cache.iso_cache); + return _cache.iridescentConductorBxDF.evalAndWeight(_sample, interaction.isotropic, _cache.aniso_cache.iso_cache); } case MaterialType::IRIDESCENT_DIELECTRIC: { - return _cache.iridescentDielectricBxDF.eval(_sample, interaction.isotropic, _cache.aniso_cache.iso_cache); + return _cache.iridescentDielectricBxDF.evalAndWeight(_sample, interaction.isotropic, _cache.aniso_cache.iso_cache); } default: - return hlsl::promote(0.0); + return value_weight_type::create(0.0, 0.0); } } @@ -172,7 +176,8 @@ struct MaterialSystem { case MaterialType::DIFFUSE: { - return _cache.diffuseBxDF.generate(interaction, u.xy); + typename diffuse_op_type::isocache_type dummycache; + return _cache.diffuseBxDF.generate(interaction, u.xy, dummycache); } case MaterialType::CONDUCTOR: { @@ -230,7 +235,7 @@ struct MaterialSystem } } - quotient_pdf_type quotient_and_pdf(material_id_type matID, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_REF_ARG(cache_type) _cache) + quotient_weight_type quotientAndWeight(material_id_type matID, NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(anisotropic_interaction_type) interaction, NBL_REF_ARG(cache_type) _cache) { const float minimumProjVectorLen = 0.00000001; // TODO: still need this check? if (interaction.getNdotV(bxdf::BxDFClampMode::BCM_ABS) > minimumProjVectorLen && _sample.getNdotL(bxdf::BxDFClampMode::BCM_ABS) > minimumProjVectorLen) @@ -240,31 +245,32 @@ struct MaterialSystem { case MaterialType::DIFFUSE: { - quotient_pdf_type ret = _cache.diffuseBxDF.quotient_and_pdf(_sample, interaction.isotropic); + typename diffuse_op_type::isocache_type dummycache; + quotient_weight_type ret = _cache.diffuseBxDF.quotientAndWeight(_sample, interaction.isotropic, dummycache); ret._quotient *= bxdfs[matID.id].albedo; return ret; } case MaterialType::CONDUCTOR: { - return _cache.conductorBxDF.quotient_and_pdf(_sample, interaction.isotropic, _cache.aniso_cache.iso_cache); + return _cache.conductorBxDF.quotientAndWeight(_sample, interaction.isotropic, _cache.aniso_cache.iso_cache); } case MaterialType::DIELECTRIC: { - return _cache.dielectricBxDF.quotient_and_pdf(_sample, interaction.isotropic, _cache.aniso_cache.iso_cache); + return _cache.dielectricBxDF.quotientAndWeight(_sample, interaction.isotropic, _cache.aniso_cache.iso_cache); } case MaterialType::IRIDESCENT_CONDUCTOR: { - return _cache.iridescentConductorBxDF.quotient_and_pdf(_sample, interaction.isotropic, _cache.aniso_cache.iso_cache); + return _cache.iridescentConductorBxDF.quotientAndWeight(_sample, interaction.isotropic, _cache.aniso_cache.iso_cache); } case MaterialType::IRIDESCENT_DIELECTRIC: { - return _cache.iridescentDielectricBxDF.quotient_and_pdf(_sample, interaction.isotropic, _cache.aniso_cache.iso_cache); + return _cache.iridescentDielectricBxDF.quotientAndWeight(_sample, interaction.isotropic, _cache.aniso_cache.iso_cache); } default: break; } } - return quotient_pdf_type::create(hlsl::promote(0.0), 0.0); + return quotient_weight_type::create(0.0, 0.0); } bool hasEmission(material_id_type matID) diff --git a/31_HLSLPathTracer/app_resources/hlsl/next_event_estimator.hlsl b/31_HLSLPathTracer/app_resources/hlsl/next_event_estimator.hlsl index 33135a677..a1b836f22 100644 --- a/31_HLSLPathTracer/app_resources/hlsl/next_event_estimator.hlsl +++ b/31_HLSLPathTracer/app_resources/hlsl/next_event_estimator.hlsl @@ -9,6 +9,7 @@ using namespace hlsl; template struct ShapeSampling; +// Sphere only supports solid angle template struct ShapeSampling { @@ -29,7 +30,7 @@ struct ShapeSampling } template - vector3_type generate_and_pdf(NBL_REF_ARG(scalar_type) pdf, NBL_REF_ARG(scalar_type) newRayMaxT, NBL_CONST_REF_ARG(vector3_type) origin, NBL_CONST_REF_ARG(Aniso) interaction, NBL_CONST_REF_ARG(vector3_type) xi) + vector3_type generateAndPdf(NBL_REF_ARG(scalar_type) pdf, NBL_REF_ARG(scalar_type) newRayMaxT, NBL_CONST_REF_ARG(vector3_type) origin, NBL_CONST_REF_ARG(Aniso) interaction, NBL_CONST_REF_ARG(vector3_type) xi) { vector3_type Z = sphere.position - origin; const scalar_type distanceSQ = hlsl::dot(Z,Z); @@ -64,15 +65,16 @@ struct ShapeSampling Shape sphere; }; -template -struct ShapeSampling +// make Area sampling default spec for everything +template +struct ShapeSampling { using scalar_type = T; using vector3_type = vector; - static ShapeSampling create(NBL_CONST_REF_ARG(Shape) tri) + static ShapeSampling create(NBL_CONST_REF_ARG(Shape) tri) { - ShapeSampling retval; + ShapeSampling retval; retval.tri = tri; return retval; } @@ -86,7 +88,7 @@ struct ShapeSampling } template - vector3_type generate_and_pdf(NBL_REF_ARG(scalar_type) pdf, NBL_REF_ARG(scalar_type) newRayMaxT, NBL_CONST_REF_ARG(vector3_type) origin, NBL_CONST_REF_ARG(Aniso) interaction, NBL_CONST_REF_ARG(vector3_type) xi) + vector3_type generateAndPdf(NBL_REF_ARG(scalar_type) pdf, NBL_REF_ARG(scalar_type) newRayMaxT, NBL_CONST_REF_ARG(vector3_type) origin, NBL_CONST_REF_ARG(Aniso) interaction, NBL_CONST_REF_ARG(vector3_type) xi) { const vector3_type edge0 = tri.vertex1 - tri.vertex0; const vector3_type edge1 = tri.vertex2 - tri.vertex0; @@ -130,7 +132,7 @@ struct ShapeSampling } template - vector3_type generate_and_pdf(NBL_REF_ARG(scalar_type) pdf, NBL_REF_ARG(scalar_type) newRayMaxT, NBL_CONST_REF_ARG(vector3_type) origin, NBL_CONST_REF_ARG(Aniso) interaction, NBL_CONST_REF_ARG(vector3_type) xi) + vector3_type generateAndPdf(NBL_REF_ARG(scalar_type) pdf, NBL_REF_ARG(scalar_type) newRayMaxT, NBL_CONST_REF_ARG(vector3_type) origin, NBL_CONST_REF_ARG(Aniso) interaction, NBL_CONST_REF_ARG(vector3_type) xi) { const vector3_type tri_vertices[3] = {tri.vertex0, tri.vertex1, tri.vertex2}; shapes::SphericalTriangle st = shapes::SphericalTriangle::create(tri_vertices, origin); @@ -168,23 +170,30 @@ struct ShapeSampling const vector3_type L = ray.direction; const vector3_type tri_vertices[3] = {tri.vertex0, tri.vertex1, tri.vertex2}; shapes::SphericalTriangle st = shapes::SphericalTriangle::create(tri_vertices, ray.origin); - sampling::ProjectedSphericalTriangle pst = sampling::ProjectedSphericalTriangle::create(st); - const scalar_type pdf = pst.backwardPdf(ray.normalAtOrigin, ray.wasBSDFAtOrigin, L); + sampling::ProjectedSphericalTriangle pst; + pst.sphtri = sampling::SphericalTriangle::create(st); + pst.receiverNormal = ray.normalAtOrigin; + pst.receiverWasBSDF = ray.wasBSDFAtOrigin; + const scalar_type pdf = pst.backwardPdf(L); // if `pdf` is NAN then the triangle's projected solid angle was close to 0.0, if its close to INF then the triangle was very small return pdf < numeric_limits::max ? pdf : numeric_limits::max; } template - vector3_type generate_and_pdf(NBL_REF_ARG(scalar_type) pdf, NBL_REF_ARG(scalar_type) newRayMaxT, NBL_CONST_REF_ARG(vector3_type) origin, NBL_CONST_REF_ARG(Aniso) interaction, NBL_CONST_REF_ARG(vector3_type) xi) + vector3_type generateAndPdf(NBL_REF_ARG(scalar_type) pdf, NBL_REF_ARG(scalar_type) newRayMaxT, NBL_CONST_REF_ARG(vector3_type) origin, NBL_CONST_REF_ARG(Aniso) interaction, NBL_CONST_REF_ARG(vector3_type) xi) { scalar_type rcpPdf; const vector3_type tri_vertices[3] = {tri.vertex0, tri.vertex1, tri.vertex2}; shapes::SphericalTriangle st = shapes::SphericalTriangle::create(tri_vertices, origin); - sampling::ProjectedSphericalTriangle pst = sampling::ProjectedSphericalTriangle::create(st); + sampling::ProjectedSphericalTriangle pst; + pst.sphtri = sampling::SphericalTriangle::create(st); + pst.receiverNormal = interaction.getN(); + pst.receiverWasBSDF = interaction.isMaterialBSDF(); - const vector3_type L = pst.generate(rcpPdf, interaction.getN(), interaction.isMaterialBSDF(), xi.xy); + typename sampling::ProjectedSphericalTriangle::cache_type cache; + const vector3_type L = pst.generate(xi.xy, cache); - pdf = rcpPdf > numeric_limits::min ? (1.0 / rcpPdf) : numeric_limits::max; + pdf = cache.pdf; const vector3_type N = tri.getNormalTimesArea(); newRayMaxT = hlsl::dot(N, tri.vertex0 - origin) / hlsl::dot(N, L); @@ -194,15 +203,16 @@ struct ShapeSampling Shape tri; }; -template -struct ShapeSampling +// make Area sampling default spec for everything +template +struct ShapeSampling { using scalar_type = T; using vector3_type = vector; - static ShapeSampling create(NBL_CONST_REF_ARG(Shape) rect) + static ShapeSampling create(NBL_CONST_REF_ARG(Shape) rect) { - ShapeSampling retval; + ShapeSampling retval; retval.rect = rect; return retval; } @@ -216,7 +226,7 @@ struct ShapeSampling } template - vector3_type generate_and_pdf(NBL_REF_ARG(scalar_type) pdf, NBL_REF_ARG(scalar_type) newRayMaxT, NBL_CONST_REF_ARG(vector3_type) origin, NBL_CONST_REF_ARG(Aniso) interaction, NBL_CONST_REF_ARG(vector3_type) xi) + vector3_type generateAndPdf(NBL_REF_ARG(scalar_type) pdf, NBL_REF_ARG(scalar_type) newRayMaxT, NBL_CONST_REF_ARG(vector3_type) origin, NBL_CONST_REF_ARG(Aniso) interaction, NBL_CONST_REF_ARG(vector3_type) xi) { const vector3_type N = rect.getNormalTimesArea(); const vector3_type origin2origin = rect.offset - origin; @@ -266,7 +276,7 @@ struct ShapeSampling } template - vector3_type generate_and_pdf(NBL_REF_ARG(scalar_type) pdf, NBL_REF_ARG(scalar_type) newRayMaxT, NBL_CONST_REF_ARG(vector3_type) origin, NBL_CONST_REF_ARG(Aniso) interaction, NBL_CONST_REF_ARG(vector3_type) xi) + vector3_type generateAndPdf(NBL_REF_ARG(scalar_type) pdf, NBL_REF_ARG(scalar_type) newRayMaxT, NBL_CONST_REF_ARG(vector3_type) origin, NBL_CONST_REF_ARG(Aniso) interaction, NBL_CONST_REF_ARG(vector3_type) xi) { const vector3_type N = rect.getNormalTimesArea(); const vector3_type origin2origin = rect.offset - origin; @@ -316,7 +326,7 @@ struct NextEventEstimator using light_id_type = LightID; using spectral_type = typename light_type::spectral_type; using interaction_type = Aniso; - using quotient_pdf_type = sampling::quotient_and_pdf; + using quotient_weight_type = sampling::quotient_and_pdf; using sample_type = LightSample; using ray_dir_info_type = typename sample_type::ray_dir_info_type; using tolerance_method_type = Tolerance; @@ -327,17 +337,17 @@ struct NextEventEstimator struct SampleQuotientReturn { using sample_type = sample_type; - using quotient_pdf_type = quotient_pdf_type; + using quotient_weight_type = quotient_weight_type; using scalar_type = scalar_type; using object_handle_type = ObjectID; sample_type sample_; - quotient_pdf_type quotient_pdf; + quotient_weight_type quotient_pdf; scalar_type newRayMaxT; object_handle_type lightObjectID; sample_type getSample() NBL_CONST_MEMBER_FUNC { return sample_; } - quotient_pdf_type getQuotientPdf() NBL_CONST_MEMBER_FUNC { return quotient_pdf; } + quotient_weight_type getQuotientPdf() NBL_CONST_MEMBER_FUNC { return quotient_pdf; } scalar_type getT() NBL_CONST_MEMBER_FUNC { return newRayMaxT; } object_handle_type getLightObjectID() NBL_CONST_MEMBER_FUNC { return lightObjectID; } }; @@ -362,7 +372,7 @@ struct NextEventEstimator return shape_sampling_type::create(rect); } - scalar_type deferred_pdf(NBL_CONST_REF_ARG(scene_type) scene, light_id_type lightID, NBL_CONST_REF_ARG(ray_type) ray) + scalar_type deferredWeight(NBL_CONST_REF_ARG(scene_type) scene, light_id_type lightID, NBL_CONST_REF_ARG(ray_type) ray) { if (lightID.id == 0u) return scalar_type(0.0); // env light pdf=0 @@ -372,7 +382,7 @@ struct NextEventEstimator } template - sample_quotient_return_type generate_and_quotient_and_pdf(NBL_CONST_REF_ARG(scene_type) scene, NBL_CONST_REF_ARG(MaterialSystem) materialSystem, const vector3_type origin, NBL_CONST_REF_ARG(interaction_type) interaction, const vector3_type xi, uint16_t depth) + sample_quotient_return_type generateAndQuotientAndWeight(NBL_CONST_REF_ARG(scene_type) scene, NBL_CONST_REF_ARG(MaterialSystem) materialSystem, const vector3_type origin, NBL_CONST_REF_ARG(interaction_type) interaction, const vector3_type xi, NBL_CONST_REF_ARG(ray_type) ray) { // light id 0 is reserved for env light // however, we start indexing light array without env light, so index 0 is first shape light @@ -383,7 +393,7 @@ struct NextEventEstimator sample_quotient_return_type retval; scalar_type pdf, newRayMaxT; - const vector3_type sampleL = sampling.template generate_and_pdf(pdf, newRayMaxT, origin, interaction, xi); + const vector3_type sampleL = sampling.template generateAndPdf(pdf, newRayMaxT, origin, interaction, xi); const vector3_type N = interaction.getN(); const scalar_type NdotL = nbl::hlsl::dot(N, sampleL); @@ -400,17 +410,17 @@ struct NextEventEstimator rayL.setDirection(sampleL); retval.sample_ = sample_type::create(rayL,interaction.getT(),interaction.getB(),NdotL); - newRayMaxT *= tolerance_method_type::getEnd(depth); + newRayMaxT *= tolerance_method_type::getEnd(ray.depth); pdf *= 1.0 / scalar_type(scene_type::SCENE_LIGHT_COUNT); const spectral_type radiance = materialSystem.getEmission(light.emissiveMatID, interaction); spectral_type quo = radiance / pdf; - retval.quotient_pdf = quotient_pdf_type::create(quo, pdf); + retval.quotient_pdf = quotient_weight_type::create(quo, pdf); retval.newRayMaxT = newRayMaxT; retval.lightObjectID = light.objectID; } else { - retval.quotient_pdf = quotient_pdf_type::create(0.0, 0.0); + retval.quotient_pdf = quotient_weight_type::create(0.0, 0.0); ray_dir_info_type rayL; rayL.makeInvalid(); retval.sample_ = sample_type::create(rayL,hlsl::promote(0.0)); @@ -419,14 +429,14 @@ struct NextEventEstimator return retval; } - light_id_type get_env_light_id() + light_id_type getEnvLightId() { light_id_type env_light_id; env_light_id.id = 0u; return env_light_id; } - spectral_type get_environment_radiance(NBL_CONST_REF_ARG(ray_type) ray) + spectral_type getEnvRadiance(NBL_CONST_REF_ARG(ray_type) ray) { // can also sample environment map using ray direction return vector3_type(0.15, 0.21, 0.3); diff --git a/31_HLSLPathTracer/app_resources/hlsl/render.comp.hlsl b/31_HLSLPathTracer/app_resources/hlsl/render.comp.hlsl index 6b0d1434b..204020719 100644 --- a/31_HLSLPathTracer/app_resources/hlsl/render.comp.hlsl +++ b/31_HLSLPathTracer/app_resources/hlsl/render.comp.hlsl @@ -59,7 +59,7 @@ using namespace hlsl; #include "scene_rectangle_light.hlsl" #endif -NBL_CONSTEXPR NEEPolygonMethod POLYGON_METHOD = PPM_SOLID_ANGLE; +NBL_CONSTEXPR NEEPolygonMethod POLYGON_METHOD = PPM_APPROX_PROJECTED_SOLID_ANGLE; int32_t2 getCoordinates() { diff --git a/40_PathTracer/main.cpp b/40_PathTracer/main.cpp index 8fd248f0a..3b772f51d 100644 --- a/40_PathTracer/main.cpp +++ b/40_PathTracer/main.cpp @@ -233,6 +233,9 @@ class PathTracingApp final : public SimpleWindowedApplication, public BuiltinRes #endif m_api->endCapture(); + if (!scene_daily_pt) + return logFail("Could not create scene"); + // quick test code nbl::core::vector sensors(3,scene_daily_pt->getSensors().front()); { diff --git a/40_PathTracer/src/renderer/CRenderer.cpp b/40_PathTracer/src/renderer/CRenderer.cpp index da4f39d6c..79057d374 100644 --- a/40_PathTracer/src/renderer/CRenderer.cpp +++ b/40_PathTracer/src/renderer/CRenderer.cpp @@ -352,7 +352,6 @@ core::smart_refctd_ptr CRenderer::createScene(CScene::SCreationParams&& const auto* geo = ref.geometry.get(); if (geo->getPrimitiveType()!=IGeometryBase::EPrimitiveType::Polygon) continue; - // TODO: test without and see why asset converter complains! ref.geometry = CPolygonGeometryManipulator::createTriangleListIndexing(static_cast(geo)); } } diff --git a/66_HLSLBxDFTests/app_resources/test_compile.comp.hlsl b/66_HLSLBxDFTests/app_resources/test_compile.comp.hlsl index 070cfe60d..2c8f2569e 100644 --- a/66_HLSLBxDFTests/app_resources/test_compile.comp.hlsl +++ b/66_HLSLBxDFTests/app_resources/test_compile.comp.hlsl @@ -60,43 +60,47 @@ void main(uint32_t3 ID : SV_DispatchThreadID) float3 L = float3(0,0,0); float3 q = float3(0,0,0); - sample_t s = lambertianBRDF.generate(anisointer, u.xy); + typename bxdf::reflection::SLambertian::anisocache_type _lcache; + sample_t s = lambertianBRDF.generate(anisointer, u.xy, _lcache); L += s.L.direction; - s = orenNayarBRDF.generate(anisointer, u.xy); + typename bxdf::reflection::SOrenNayar::anisocache_type _ocache; + s = orenNayarBRDF.generate(anisointer, u.xy, _ocache); L += s.L.direction; - quotient_pdf_t qp = orenNayarBRDF.quotient_and_pdf(s, isointer); + quotient_pdf_t qp = orenNayarBRDF.quotientAndWeight(s, isointer, _ocache); L -= qp.quotient(); s = beckmannAnisoBRDF.generate(anisointer, u.xy, cache); L += s.L.direction; - qp = beckmannAnisoBRDF.quotient_and_pdf(s, anisointer, cache); + qp = beckmannAnisoBRDF.quotientAndWeight(s, anisointer, cache); L -= qp.quotient(); s = ggxAnisoBRDF.generate(anisointer, u.xy, cache); L += s.L.direction; - qp = iridBRDF.quotient_and_pdf(s, anisointer, cache); + qp = iridBRDF.quotientAndWeight(s, anisointer, cache); L -= qp.quotient(); - qp = ggxAnisoBRDF.quotient_and_pdf(s, anisointer, cache); + qp = ggxAnisoBRDF.quotientAndWeight(s, anisointer, cache); L -= qp.quotient(); - s = lambertianBSDF.generate(anisointer, u); + typename bxdf::transmission::SLambertian::anisocache_type _tlcache; + s = lambertianBSDF.generate(anisointer, u, _tlcache); L += s.L.direction; - s = thinSmoothDielectricBSDF.generate(anisointer, u); + typename bxdf::transmission::SThinSmoothDielectric::anisocache_type _tscache; + s = thinSmoothDielectricBSDF.generate(anisointer, u, _tscache); L += s.L.direction; - qp = thinSmoothDielectricBSDF.quotient_and_pdf(s, isointer); + qp = thinSmoothDielectricBSDF.quotientAndWeight(s, isointer, _tscache); L -= qp.quotient(); s = ggxAnisoBSDF.generate(anisointer, u, cache); L += s.L.direction; - qp = ggxAnisoBSDF.quotient_and_pdf(s, anisointer, cache); + qp = ggxAnisoBSDF.quotientAndWeight(s, anisointer, cache); L -= qp.quotient(); buff[ID.x] = L; diff --git a/66_HLSLBxDFTests/app_resources/test_components.hlsl b/66_HLSLBxDFTests/app_resources/test_components.hlsl index 2570d68f9..dec73c67d 100644 --- a/66_HLSLBxDFTests/app_resources/test_components.hlsl +++ b/66_HLSLBxDFTests/app_resources/test_components.hlsl @@ -196,7 +196,8 @@ struct TestCTGenerateH : TestBxDF NBL_IF_CONSTEXPR(traits_t::type == bxdf::BT_BRDF && !traits_t::IsMicrofacet) { - s = base_t::bxdf.generate(base_t::anisointer, u.xy); + typename BxDF::anisocache_type _cache; + s = base_t::bxdf.generate(base_t::anisointer, u.xy, _cache); } NBL_IF_CONSTEXPR(traits_t::type == bxdf::BT_BRDF && traits_t::IsMicrofacet) { @@ -207,7 +208,8 @@ struct TestCTGenerateH : TestBxDF } NBL_IF_CONSTEXPR(traits_t::type == bxdf::BT_BSDF && !traits_t::IsMicrofacet) { - s = base_t::bxdf.generate(base_t::anisointer, u); + typename BxDF::anisocache_type _cache; + s = base_t::bxdf.generate(base_t::anisointer, u, _cache); } NBL_IF_CONSTEXPR(traits_t::type == bxdf::BT_BSDF && traits_t::IsMicrofacet) { diff --git a/66_HLSLBxDFTests/app_resources/tests.hlsl b/66_HLSLBxDFTests/app_resources/tests.hlsl index 0a17fd836..b2ad6a552 100644 --- a/66_HLSLBxDFTests/app_resources/tests.hlsl +++ b/66_HLSLBxDFTests/app_resources/tests.hlsl @@ -25,9 +25,10 @@ struct TestJacobian : TestBxDF NBL_IF_CONSTEXPR(traits_t::type == bxdf::BT_BRDF && !traits_t::IsMicrofacet) { - s = base_t::bxdf.generate(base_t::isointer, base_t::rc.u.xy); - sx = base_t::bxdf.generate(base_t::isointer, ux.xy); - sy = base_t::bxdf.generate(base_t::isointer, uy.xy); + typename BxDF::anisocache_type _cache; + s = base_t::bxdf.generate(base_t::isointer, base_t::rc.u.xy, _cache); + sx = base_t::bxdf.generate(base_t::isointer, ux.xy, _cache); + sy = base_t::bxdf.generate(base_t::isointer, uy.xy, _cache); } NBL_IF_CONSTEXPR(traits_t::type == bxdf::BT_BRDF && traits_t::IsMicrofacet) { @@ -46,9 +47,10 @@ struct TestJacobian : TestBxDF } NBL_IF_CONSTEXPR(traits_t::type == bxdf::BT_BSDF && !traits_t::IsMicrofacet) { - s = base_t::bxdf.generate(base_t::anisointer, base_t::rc.u); - sx = base_t::bxdf.generate(base_t::anisointer, ux); - sy = base_t::bxdf.generate(base_t::anisointer, uy); + typename BxDF::anisocache_type _cache; + s = base_t::bxdf.generate(base_t::anisointer, base_t::rc.u, _cache); + sx = base_t::bxdf.generate(base_t::anisointer, ux, _cache); + sy = base_t::bxdf.generate(base_t::anisointer, uy, _cache); } NBL_IF_CONSTEXPR(traits_t::type == bxdf::BT_BSDF && traits_t::IsMicrofacet) { @@ -72,22 +74,23 @@ struct TestJacobian : TestBxDF NBL_IF_CONSTEXPR(!traits_t::IsMicrofacet) { - sampledLi = base_t::bxdf.quotient_and_pdf(s, base_t::isointer); - Li = float32_t3(base_t::bxdf.eval(s, base_t::isointer)); + typename BxDF::anisocache_type _cache; + sampledLi = base_t::bxdf.quotientAndWeight(s, base_t::isointer, _cache); + Li = base_t::bxdf.evalAndWeight(s, base_t::isointer, _cache); transmitted = base_t::isointer.getNdotV() * s.getNdotL() < 0.f; } NBL_IF_CONSTEXPR(traits_t::IsMicrofacet) { NBL_IF_CONSTEXPR(aniso) { - sampledLi = base_t::bxdf.quotient_and_pdf(s, base_t::anisointer, cache); - Li = float32_t3(base_t::bxdf.eval(s, base_t::anisointer, cache)); + sampledLi = base_t::bxdf.quotientAndWeight(s, base_t::anisointer, cache); + Li = base_t::bxdf.evalAndWeight(s, base_t::anisointer, cache); transmitted = cache.isTransmission(); } else { - sampledLi = base_t::bxdf.quotient_and_pdf(s, base_t::isointer, isocache); - Li = float32_t3(base_t::bxdf.eval(s, base_t::isointer, isocache)); + sampledLi = base_t::bxdf.quotientAndWeight(s, base_t::isointer, isocache); + Li = base_t::bxdf.evalAndWeight(s, base_t::isointer, isocache); transmitted = isocache.isTransmission(); } } @@ -118,7 +121,7 @@ struct TestJacobian : TestBxDF if (sampledLi.pdf() < bit_cast(numeric_limits::min)) // there's exceptional cases where pdf=0, so we check here to avoid adding all edge-cases, but quotient must be positive afterwards return BTR_NONE; - if (checkLt(Li, hlsl::promote(0.0)) || checkLt(sampledLi.quotient(), hlsl::promote(0.0))) + if (checkLt(Li.value(), hlsl::promote(0.0)) || checkLt(sampledLi.quotient(), hlsl::promote(0.0))) return BTR_ERROR_NEGATIVE_VAL; if (!checkLt(sampledLi.quotient(), hlsl::promote(bit_cast(numeric_limits::infinity)))) // importance sampler's job to prevent inf @@ -129,7 +132,7 @@ struct TestJacobian : TestBxDF // 2. quotient is positive and (1) already checked // So if we must have `eval == quotient*pdf` , then eval must also be positive // However for mixture of, or singular delta BxDF the bsdf can be less due to removal of Dirac-Delta lobes from the eval method, which is why allow `BTR_NONE` in this case - if (checkZero(Li, 1e-5) || checkZero(sampledLi.quotient(), 1e-5)) + if (checkZero(Li.value(), 1e-5) || checkZero(sampledLi.quotient(), 1e-5)) return BTR_NONE; if (hlsl::isnan(sampledLi.pdf())) @@ -160,14 +163,14 @@ struct TestJacobian : TestBxDF } float32_t3 quo_pdf = sampledLi.value(); - if (!testing::relativeApproxCompare(quo_pdf, Li, 1e-4)) + if (!testing::relativeApproxCompare(quo_pdf, Li.value(), 1e-4)) { #ifndef __HLSL_VERSION if (verbose) base_t::errMsg += std::format("transmitted={}, quotient*pdf=[{},{},{}] eval=[{},{},{}]", transmitted ? "true" : "false", quo_pdf.x, quo_pdf.y, quo_pdf.z, - Li.x, Li.y, Li.z); + Li.value().x, Li.value().y, Li.value().z); #endif return BTR_ERROR_PDF_EVAL_DIFF; } @@ -191,7 +194,7 @@ struct TestJacobian : TestBxDF sample_t s, sx, sy; quotient_pdf_t sampledLi; - float32_t3 Li; + value_weight_t Li; bool transmitted; bool verbose; }; @@ -224,7 +227,8 @@ struct TestReciprocity : TestBxDF NBL_IF_CONSTEXPR(traits_t::type == bxdf::BT_BRDF && !traits_t::IsMicrofacet) { - s = base_t::bxdf.generate(anisointer, base_t::rc.u.xy); + typename BxDF::anisocache_type _cache; + s = base_t::bxdf.generate(anisointer, base_t::rc.u.xy, _cache); } NBL_IF_CONSTEXPR(traits_t::type == bxdf::BT_BRDF && traits_t::IsMicrofacet) { @@ -239,7 +243,8 @@ struct TestReciprocity : TestBxDF } NBL_IF_CONSTEXPR(traits_t::type == bxdf::BT_BSDF && !traits_t::IsMicrofacet) { - s = base_t::bxdf.generate(anisointer, base_t::rc.u); + typename BxDF::anisocache_type _cache; + s = base_t::bxdf.generate(anisointer, base_t::rc.u, _cache); } NBL_IF_CONSTEXPR(traits_t::type == bxdf::BT_BSDF && traits_t::IsMicrofacet) { @@ -280,20 +285,21 @@ struct TestReciprocity : TestBxDF NBL_IF_CONSTEXPR(!traits_t::IsMicrofacet) { - Li = float32_t3(base_t::bxdf.eval(s, isointer)); - recLi = float32_t3(base_t::bxdf.eval(rec_s, rec_isointer)); + typename BxDF::anisocache_type _cache; + Li = base_t::bxdf.evalAndWeight(s, isointer, _cache); + recLi = base_t::bxdf.evalAndWeight(rec_s, rec_isointer, _cache); } NBL_IF_CONSTEXPR(traits_t::type == bxdf::BT_BRDF && traits_t::IsMicrofacet) { NBL_IF_CONSTEXPR(aniso) { - Li = float32_t3(base_t::bxdf.eval(s, anisointer, cache)); - recLi = float32_t3(base_t::bxdf.eval(rec_s, rec_anisointer, rec_cache)); + Li = base_t::bxdf.evalAndWeight(s, anisointer, cache); + recLi = base_t::bxdf.evalAndWeight(rec_s, rec_anisointer, rec_cache); } else { - Li = float32_t3(base_t::bxdf.eval(s, isointer, isocache)); - recLi = float32_t3(base_t::bxdf.eval(rec_s, rec_isointer, rec_isocache)); + Li = base_t::bxdf.evalAndWeight(s, isointer, isocache); + recLi = base_t::bxdf.evalAndWeight(rec_s, rec_isointer, rec_isocache); } } NBL_IF_CONSTEXPR(traits_t::type == bxdf::BT_BSDF && traits_t::IsMicrofacet) @@ -301,16 +307,16 @@ struct TestReciprocity : TestBxDF NBL_IF_CONSTEXPR(aniso) { anisointer.isotropic.pathOrigin = bxdf::PathOrigin::PO_SENSOR; - Li = float32_t3(base_t::bxdf.eval(s, anisointer, cache)); + Li = base_t::bxdf.evalAndWeight(s, anisointer, cache); rec_anisointer.isotropic.pathOrigin = bxdf::PathOrigin::PO_LIGHT; - recLi = float32_t3(base_t::bxdf.eval(rec_s, rec_anisointer, rec_cache)); + recLi = base_t::bxdf.evalAndWeight(rec_s, rec_anisointer, rec_cache); } else { isointer.pathOrigin = bxdf::PathOrigin::PO_SENSOR; - Li = float32_t3(base_t::bxdf.eval(s, isointer, isocache)); + Li = base_t::bxdf.evalAndWeight(s, isointer, isocache); rec_isointer.pathOrigin = bxdf::PathOrigin::PO_LIGHT; - recLi = float32_t3(base_t::bxdf.eval(rec_s, rec_isointer, rec_isocache)); + recLi = base_t::bxdf.evalAndWeight(rec_s, rec_isointer, rec_isocache); } } @@ -346,14 +352,14 @@ struct TestReciprocity : TestBxDF if (absNdotL <= bit_cast(numeric_limits::min)) return BTR_INVALID_TEST_CONFIG; - if (checkLt(Li, hlsl::promote(0.0))) + if (checkLt(Li.value(), hlsl::promote(0.0))) return BTR_ERROR_NEGATIVE_VAL; - if (checkZero(Li, 1e-5)) // we don't have a pdf to check like in the one above but + if (checkZero(Li.value(), 1e-5)) // we don't have a pdf to check like in the one above but return BTR_NONE; - float32_t3 a = Li / absNdotL; - float32_t3 b = recLi / hlsl::abs(rec_s.getNdotL()); + float32_t3 a = Li.value() / absNdotL; + float32_t3 b = recLi.value() / hlsl::abs(rec_s.getNdotL()); if (!(a == b)) // avoid division by 0 if (!testing::relativeApproxCompare(a, b, 1.25e-2)) { @@ -384,7 +390,7 @@ struct TestReciprocity : TestBxDF } sample_t s, rec_s; - float32_t3 Li, recLi; + value_weight_t Li, recLi; iso_interaction_t isointer, rec_isointer; aniso_interaction_t anisointer, rec_anisointer; bool transmitted; diff --git a/66_HLSLBxDFTests/app_resources/tests_common.hlsl b/66_HLSLBxDFTests/app_resources/tests_common.hlsl index 478cd1f55..c8f4778b6 100644 --- a/66_HLSLBxDFTests/app_resources/tests_common.hlsl +++ b/66_HLSLBxDFTests/app_resources/tests_common.hlsl @@ -27,6 +27,7 @@ using sample_t = bxdf::SLightSample; using iso_cache = bxdf::SIsotropicMicrofacetCache; using aniso_cache = bxdf::SAnisotropicMicrofacetCache; using quotient_pdf_t = sampling::quotient_and_pdf; +using value_weight_t = sampling::value_and_weight; using iso_config_t = bxdf::SConfiguration; using aniso_config_t = bxdf::SConfiguration; @@ -628,7 +629,8 @@ struct CustomIsoMicrofacetConfiguration; using sample_type = LS; using spectral_type = Spectrum; - using quotient_pdf_type = sampling::quotient_and_pdf; + using quotient_weight_type = sampling::quotient_and_pdf; + using value_weight_type = sampling::value_and_weight; using isocache_type = MicrofacetCache; using anisocache_type = bxdf::SAnisotropicMicrofacetCache; }; diff --git a/66_HLSLBxDFTests/tests.h b/66_HLSLBxDFTests/tests.h index 442bac85c..775a48e22 100644 --- a/66_HLSLBxDFTests/tests.h +++ b/66_HLSLBxDFTests/tests.h @@ -39,7 +39,8 @@ struct TestModifiedWhiteFurnace : TestBxDF NBL_IF_CONSTEXPR(traits_t::type == bxdf::BT_BRDF && !traits_t::IsMicrofacet) { - s = base_t::bxdf.generate(base_t::anisointer, u.xy); + typename BxDF::anisocache_type _cache; + s = base_t::bxdf.generate(base_t::anisointer, u.xy, _cache); } NBL_IF_CONSTEXPR(traits_t::type == bxdf::BT_BRDF && traits_t::IsMicrofacet) { @@ -54,7 +55,8 @@ struct TestModifiedWhiteFurnace : TestBxDF } NBL_IF_CONSTEXPR(traits_t::type == bxdf::BT_BSDF && !traits_t::IsMicrofacet) { - s = base_t::bxdf.generate(base_t::anisointer, u); + typename BxDF::anisocache_type _cache; + s = base_t::bxdf.generate(base_t::anisointer, u, _cache); } NBL_IF_CONSTEXPR(traits_t::type == bxdf::BT_BSDF && traits_t::IsMicrofacet) { @@ -73,17 +75,18 @@ struct TestModifiedWhiteFurnace : TestBxDF NBL_IF_CONSTEXPR(!traits_t::IsMicrofacet) { - sampledLi = base_t::bxdf.quotient_and_pdf(s, base_t::isointer); + typename BxDF::anisocache_type _cache; + sampledLi = base_t::bxdf.quotientAndWeight(s, base_t::isointer, _cache); } NBL_IF_CONSTEXPR(traits_t::IsMicrofacet) { NBL_IF_CONSTEXPR(aniso) { - sampledLi = base_t::bxdf.quotient_and_pdf(s, base_t::anisointer, cache); + sampledLi = base_t::bxdf.quotientAndWeight(s, base_t::anisointer, cache); } else { - sampledLi = base_t::bxdf.quotient_and_pdf(s, base_t::isointer, isocache); + sampledLi = base_t::bxdf.quotientAndWeight(s, base_t::isointer, isocache); } } @@ -202,17 +205,17 @@ struct CalculatePdfSinTheta float pdf; NBL_IF_CONSTEXPR(!traits_t::IsMicrofacet) { - pdf = bxdf.pdf(s, isointer); + pdf = bxdf.forwardPdf(s, isointer); } NBL_IF_CONSTEXPR(traits_t::IsMicrofacet) { NBL_IF_CONSTEXPR(aniso) { - pdf = bxdf.pdf(s, anisointer, cache); + pdf = bxdf.forwardPdf(s, anisointer, cache); } else { - pdf = bxdf.pdf(s, isointer, cache.iso_cache); + pdf = bxdf.forwardPdf(s, isointer, cache.iso_cache); } } @@ -285,7 +288,8 @@ struct TestChi2 : TestBxDF NBL_IF_CONSTEXPR(traits_t::type == bxdf::BT_BRDF && !traits_t::IsMicrofacet) { - s = base_t::bxdf.generate(base_t::anisointer, u.xy); + typename BxDF::anisocache_type _cache; + s = base_t::bxdf.generate(base_t::anisointer, u.xy, _cache); } NBL_IF_CONSTEXPR(traits_t::type == bxdf::BT_BRDF && traits_t::IsMicrofacet) { @@ -296,7 +300,8 @@ struct TestChi2 : TestBxDF } NBL_IF_CONSTEXPR(traits_t::type == bxdf::BT_BSDF && !traits_t::IsMicrofacet) { - s = base_t::bxdf.generate(base_t::anisointer, u); + typename BxDF::anisocache_type _cache; + s = base_t::bxdf.generate(base_t::anisointer, u, _cache); } NBL_IF_CONSTEXPR(traits_t::type == bxdf::BT_BSDF && traits_t::IsMicrofacet) {