void RoughCoatBsdf::substrateEvalAndPdf(const SurfaceScatterEvent &event, float eta, float Fi, float cosThetaTi, float &pdf, Vec3f &brdf) const { const Vec3f &wi = event.wi; const Vec3f &wo = event.wo; float cosThetaTo; float Fo = Fresnel::dielectricReflectance(eta, wo.z(), cosThetaTo); if (Fi == 1.0f || Fo == 1.0f) { pdf = 0.0f; brdf = Vec3f(0.0f); return; } Vec3f wiSubstrate(wi.x()*eta, wi.y()*eta, std::copysign(cosThetaTi, wi.z())); Vec3f woSubstrate(wo.x()*eta, wo.y()*eta, std::copysign(cosThetaTo, wo.z())); pdf = _substrate->pdf(event.makeWarpedQuery(wiSubstrate, woSubstrate)); pdf *= eta*eta*std::abs(wo.z()/cosThetaTo); float compressionProjection = eta*eta*wo.z()/cosThetaTo; Vec3f substrateF = _substrate->eval(event.makeWarpedQuery(wiSubstrate, woSubstrate)); if (_scaledSigmaA.max() > 0.0f) substrateF *= std::exp(_scaledSigmaA*(-1.0f/cosThetaTo - 1.0f/cosThetaTi)); brdf = compressionProjection*(1.0f - Fi)*(1.0f - Fo)*substrateF; }
float RoughCoatBsdf::pdf(const SurfaceScatterEvent &event) const { bool sampleR = event.requestedLobe.test(BsdfLobes::GlossyReflectionLobe); bool sampleT = event.requestedLobe.test(_substrate->lobes()); if (!sampleT && !sampleR) return 0.0f; if (event.wi.z() <= 0.0f || event.wo.z() <= 0.0f) return 0.0f; const Vec3f &wi = event.wi; const Vec3f &wo = event.wo; float eta = 1.0f/_ior; float cosThetaTi, cosThetaTo; float Fi = Fresnel::dielectricReflectance(eta, wi.z(), cosThetaTi); float Fo = Fresnel::dielectricReflectance(eta, wo.z(), cosThetaTo); float specularProbability; if (sampleR && sampleT) { float substrateWeight = _avgTransmittance*(1.0f - Fi); float specularWeight = Fi; specularProbability = specularWeight/(specularWeight + substrateWeight); } else { specularProbability = sampleR ? 1.0f : 0.0f; } float glossyPdf = 0.0f; if (sampleR) glossyPdf = RoughDielectricBsdf::pdfBase(event, true, false, (*_roughness)[*event.info].x(), _ior, _distribution); float substratePdf = 0.0f; if (sampleT) { if (Fi < 1.0f && Fo < 1.0f) { Vec3f wiSubstrate(wi.x()*eta, wi.y()*eta, std::copysign(cosThetaTi, wi.z())); Vec3f woSubstrate(wo.x()*eta, wo.y()*eta, std::copysign(cosThetaTo, wo.z())); substratePdf = _substrate->pdf(event.makeWarpedQuery(wiSubstrate, woSubstrate)); substratePdf *= eta*eta*std::abs(wo.z()/cosThetaTo); } } return glossyPdf*specularProbability + substratePdf*(1.0f - specularProbability); }
Vec3f RoughCoatBsdf::eval(const SurfaceScatterEvent &event) const { bool sampleR = event.requestedLobe.test(BsdfLobes::GlossyReflectionLobe); bool sampleT = event.requestedLobe.test(_substrate->lobes()); if (!sampleT && !sampleR) return Vec3f(0.0f); if (event.wi.z() <= 0.0f || event.wo.z() <= 0.0f) return Vec3f(0.0f); Vec3f glossyR(0.0f); if (sampleR) glossyR = RoughDielectricBsdf::evalBase(event, true, false, (*_roughness)[*event.info].x(), _ior, _distribution); Vec3f substrateR(0.0f); if (sampleT) { const Vec3f &wi = event.wi; const Vec3f &wo = event.wo; float eta = 1.0f/_ior; float cosThetaTi, cosThetaTo; float Fi = Fresnel::dielectricReflectance(eta, wi.z(), cosThetaTi); float Fo = Fresnel::dielectricReflectance(eta, wo.z(), cosThetaTo); if (Fi == 1.0f || Fo == 1.0f) return glossyR; Vec3f wiSubstrate(wi.x()*eta, wi.y()*eta, std::copysign(cosThetaTi, wi.z())); Vec3f woSubstrate(wo.x()*eta, wo.y()*eta, std::copysign(cosThetaTo, wo.z())); float compressionProjection = eta*eta*wo.z()/cosThetaTo; Vec3f substrateF = _substrate->eval(event.makeWarpedQuery(wiSubstrate, woSubstrate)); if (_scaledSigmaA.max() > 0.0f) substrateF *= std::exp(_scaledSigmaA*(-1.0f/cosThetaTo - 1.0f/cosThetaTi)); substrateR = compressionProjection*(1.0f - Fi)*(1.0f - Fo)*substrateF; } return glossyR + substrateR; }