// sample the bsdf Colour BSDF::sample(RenderContext *rc, const HitContext *hc, const Vec3 &woW, Vec3 &wiW, float &pdf, const float r1, const float r2, const float r3, BxDFtype flags, BxDFtype *sampled) const { // Grab the number of appropriate BxDF int matchingComps = numComponents(flags); if (matchingComps == 0) { pdf = 0.f; return Colours::black; } // Pick the bxdf int which = (int)(r3 * matchingComps);//rc->rnd.randInt(matchingComps - 1); which = which == matchingComps ? matchingComps - 1 : which; BxDF *bxdf = NULL; int count = which; int bxdfNum = 0; for (int i = 0; i < numBxDFs; ++i) { if (bxdfs[i]->hasFlags(flags)) { if (count-- == 0) { bxdf = bxdfs[i]; bxdfNum = i; break; } } } // Sample the appropriate BxDF pdf = 0.0f; Vec3 wi; const Vec3 wo = hc->onb.untransform(woW); const Colour C = getCol(rc, hc, bxdfNum); Colour f = bxdf->sample(rc, wo, wi, pdf, r1, r2, C); f = adjust(hc, f, bxdfNum, wo, wi); // custom adjustment for each BSDF if (pdf == 0.0f) return 0.0f; if (sampled != NULL) *sampled = bxdf->type; wiW = hc->onb.transform(wi); // Compute overall PDF with all matching BxDFs if (matchingComps > 1) { if (!(bxdf->type & BSDF_SPECULAR)) { for (int i = 0; i < numBxDFs; ++i) { if (bxdfs[i] != bxdf && bxdfs[i]->hasFlags(flags)) pdf += bxdfs[i]->pdf(wo, wi); } } pdf /= matchingComps; } // Compute value of BSDF for sampled direction if (!(bxdf->type & BSDF_SPECULAR)) { f = 0.0; if (Dot(wiW, hc->gNormal) * Dot(woW, hc->gNormal) > 0) flags = BxDFtype(flags & ~BSDF_TRANSMISSION); // ignore BTDFs else flags = BxDFtype(flags & ~BSDF_REFLECTION); // ignore BRDFs for (int i = 0; i < numBxDFs; ++i) { if (bxdfs[i]->hasFlags(flags)) { // Tweak eval output to suit each BSDF f += adjust(hc, bxdfs[i]->eval(wo, wi, getCol(rc, hc, bxdfNum)), i, wo, wi); } } } return f; }