Spectrum BSDF::Sample_f(const Vector3f &woWorld, Vector3f *wiWorld, const Point2f &u, Float *pdf, BxDFType type, BxDFType *sampledType) const { ProfilePhase pp(Prof::BSDFEvaluation); // Choose which _BxDF_ to sample int matchingComps = NumComponents(type); if (matchingComps == 0) { *pdf = 0; if (sampledType) *sampledType = BxDFType(0); return Spectrum(0); } int comp = std::min((int)std::floor(u[0] * matchingComps), matchingComps - 1); // Get _BxDF_ pointer for chosen component BxDF *bxdf = nullptr; int count = comp; for (int i = 0; i < nBxDFs; ++i) if (bxdfs[i]->MatchesFlags(type) && count-- == 0) { bxdf = bxdfs[i]; break; } Assert(bxdf); // Remap _BxDF_ sample _u_ to $[0,1)^2$ Point2f uRemapped(u[0] * matchingComps - comp, u[1]); // Sample chosen _BxDF_ Vector3f wi, wo = WorldToLocal(woWorld); *pdf = 0; if (sampledType) *sampledType = bxdf->type; Spectrum f = bxdf->Sample_f(wo, &wi, uRemapped, pdf, sampledType); if (*pdf == 0) { if (sampledType) *sampledType = BxDFType(0); return 0; } *wiWorld = LocalToWorld(wi); // Compute overall PDF with all matching _BxDF_s if (!(bxdf->type & BSDF_SPECULAR) && matchingComps > 1) for (int i = 0; i < nBxDFs; ++i) if (bxdfs[i] != bxdf && bxdfs[i]->MatchesFlags(type)) *pdf += bxdfs[i]->Pdf(wo, wi); if (matchingComps > 1) *pdf /= matchingComps; // Compute value of BSDF for sampled direction if (!(bxdf->type & BSDF_SPECULAR) && matchingComps > 1) { bool reflect = Dot(*wiWorld, ng) * Dot(woWorld, ng) > 0; f = 0.; for (int i = 0; i < nBxDFs; ++i) if (bxdfs[i]->MatchesFlags(type) && ((reflect && (bxdfs[i]->type & BSDF_REFLECTION)) || (!reflect && (bxdfs[i]->type & BSDF_TRANSMISSION)))) f += bxdfs[i]->f(wo, wi); } return f; }
Spectrum BSDF::Sample_f(const Vector &woW, Vector *wiW, float u1, float u2, float u3, float *pdf, BxDFType flags, BxDFType *sampledType) const { // Choose which _BxDF_ to sample int matchingComps = NumComponents(flags); if (matchingComps == 0) { *pdf = 0.f; return Spectrum(0.f); } int which = min(Floor2Int(u3 * matchingComps), matchingComps-1); BxDF *bxdf = NULL; int count = which; for (int i = 0; i < nBxDFs; ++i) if (bxdfs[i]->MatchesFlags(flags)) if (count-- == 0) { bxdf = bxdfs[i]; break; } Assert(bxdf); // NOBOOK // Sample chosen _BxDF_ Vector wi; Vector wo = WorldToLocal(woW); *pdf = 0.f; Spectrum f = bxdf->Sample_f(wo, &wi, u1, u2, pdf); if (*pdf == 0.f) return 0.f; if (sampledType) *sampledType = bxdf->type; *wiW = LocalToWorld(wi); // Compute overall PDF with all matching _BxDF_s if (!(bxdf->type & BSDF_SPECULAR) && matchingComps > 1) { for (int i = 0; i < nBxDFs; ++i) { if (bxdfs[i] != bxdf && bxdfs[i]->MatchesFlags(flags)) *pdf += bxdfs[i]->Pdf(wo, wi); } } if (matchingComps > 1) *pdf /= matchingComps; // Compute value of BSDF for sampled direction if (!(bxdf->type & BSDF_SPECULAR)) { f = 0.; if (Dot(*wiW, ng) * Dot(woW, ng) > 0) // ignore BTDFs flags = BxDFType(flags & ~BSDF_TRANSMISSION); else // ignore BRDFs flags = BxDFType(flags & ~BSDF_REFLECTION); for (int i = 0; i < nBxDFs; ++i) if (bxdfs[i]->MatchesFlags(flags)) f += bxdfs[i]->f(wo, wi); } return f; }
RGB BSDF::Sample_f(const Vector &woWorld, Vector *wiWorld, const BSDFSample &bsdfSample, float *pdf, BxDFType flags, BxDFType *sampledType) const { int numComp = NumComponents(flags); if (numComp == 0) { *pdf = 0; if (sampledType) *sampledType = BxDFType(0); return 0; } int whichComp = min(Floor2Int(bsdfSample.uComponent * numComp), numComp - 1); int count = whichComp; BxDF *bxdf = nullptr; //被选中的Bxdf for (int i = 0; i < mNumBxdf; ++i) { if (mBxdfs[i]->MatchesFlag(flags) && count-- == 0) { //这技巧 GOOD bxdf = mBxdfs[i]; break; } } Vector wo = WorldToLocal(woWorld); //获得局部坐标下的wo Vector wi; *pdf = 0.f; RGB f = bxdf->Sample_f(wo, &wi, bsdfSample.uDir[0], bsdfSample.uDir[1], pdf); //这里的主要作用是采样出射方向 if (*pdf == 0) { if (sampledType) *sampledType = BxDFType(0); return 0; } if (sampledType) *sampledType = bxdf->type; *wiWorld = LocalToWorld(wi); //获得世界坐标系下的wi //计算pdf if (!(bxdf->type & BSDF_SPECULAR) && numComp > 1) { for (int i = 0; i < mNumBxdf; ++i) { if (bxdf != mBxdfs[i] && mBxdfs[i]->MatchesFlag(flags)) { *pdf += mBxdfs[i]->Pdf(wo, wi); } } } if (numComp > 1) { *pdf /= numComp; } //开始计算BRDF系数 if (!(bxdf->type & BSDF_SPECULAR)) { f=0;//因为不是镜面反射 所以重新计算BRDF if (Dot(*wiWorld, mNG) * Dot(woWorld, mNG) > 0) //反射 flags = BxDFType(flags & ~BSDF_TRANSMISSION); else//折射 flags = BxDFType(flags & ~BSDF_REFLECTION); for (int i = 0; i < mNumBxdf; ++i) if (mBxdfs[i]->MatchesFlag(flags)) f += mBxdfs[i]->f(wo, wi); } return f; }