Vec3d DiffuseBSDF::SampleAndEvaluate( BSDFRecord& record, BSDFSample& sample, double& pdf, Intersection& isect ) { if ((record.type & BSDFType::DiffuseReflection) == 0 || CosTheta(record.wi) <= 0) { return Vec3d(); } // Sample direction (cosine weighted) record.wo = RenderUtils::CosineSampleHemisphere(sample.u); record.sampledType = BSDFType::DiffuseReflection; // Pdf pdf = Pdf(record); if (pdf == 0.0) { return Vec3d(); } // Correction factor for shading normal double sf = ShadingNormalCorrectionFactor(record, isect); if (sf == 0.0) { return Vec3d(); } // f(wi, wo) * cos(theta) / p(wo) // = R * invPi * cos(theta) / (cos(theta) * invPi) = R return R->Evaluate(isect.uv) * sf; }
// commented, dpl 10 august 2005 Spectrum Lafortune::Sample_f(const Vector &wo, Vector *wi, float u1, float u2, float *pdf) const { u_int comp = RandomUInt() % (nLobes+1); if (comp == nLobes) { // Cosine-sample the hemisphere, flipping the direction if necessary *wi = CosineSampleHemisphere(u1, u2); if (wo.z < 0.) wi->z *= -1.f; } else { // Sample lobe _comp_ for Lafortune BRDF float xlum = x[comp].y(); float ylum = y[comp].y(); float zlum = z[comp].y(); float costheta = powf(u1, 1.f / (.8f * exponent[comp].y() + 1)); float sintheta = sqrtf(max(0.f, 1.f - costheta*costheta)); float phi = u2 * 2.f * M_PI; Vector lobeCenter = Normalize(Vector(xlum * wo.x, ylum * wo.y, zlum * wo.z)); Vector lobeX, lobeY; CoordinateSystem(lobeCenter, &lobeX, &lobeY); *wi = SphericalDirection(sintheta, costheta, phi, lobeX, lobeY, lobeCenter); } if (!SameHemisphere(wo, *wi)) return Spectrum(0.f); *pdf = Pdf(wo, *wi); return f(wo, *wi); }
Spectrum LambertianTransmission::Sample_f(const Vector3f &wo, Vector3f *wi, const Point2f &u, Float *pdf, BxDFType *sampledType) const { *wi = CosineSampleHemisphere(u); if (wo.z > 0) wi->z *= -1; *pdf = Pdf(wo, *wi); return f(wo, *wi); }
Spectrum BxDF::Sample_f(const Vector3f &wo, Vector3f *wi, const Point2f &u, Float *pdf, BxDFType *sampledType) const { // Cosine-sample the hemisphere, flipping the direction if necessary *wi = CosineSampleHemisphere(u); if (wo.z < 0) wi->z *= -1; *pdf = Pdf(wo, *wi); return f(wo, *wi); }
Spectrum BxDF::Sample_f(const Vector &wo, Vector *wi, float u1, float u2, float *pdf) const { // Cosine-sample the hemisphere, flipping the direction if necessary *wi = CosineSampleHemisphere(u1, u2); if (wo.z < 0.) wi->z *= -1.f; *pdf = Pdf(wo, *wi); return f(wo, *wi); }
Spectrum MicrofacetTransmission::Sample_f(const Vector3f &wo, Vector3f *wi, const Point2f &u, Float *pdf, BxDFType *sampledType) const { Vector3f wh = distribution->Sample_wh(wo, u); Float eta = CosTheta(wo) > 0 ? (etaA / etaB) : (etaB / etaA); if (!Refract(wo, (Normal3f)wh, eta, wi)) return 0; *pdf = Pdf(wo, *wi); return f(wo, *wi); }
// -------------------------------------------------- status_t DrawShape::IterateClose(void) { REPORT(kDebug, 0, "IterateClose %s", IsDrawing() ? (fStroke ? "stroke" : "fill") : "clip"); if (fDrawn) REPORT(kDebug, 0, ">>> IterateClose called multiple times!"); if (TransformPath()) fSubPath.Close(); else PDF_closepath(Pdf()); Draw(); return B_OK; }
// BxDF Method Definitions bool BxDF::SampleF(const SpectrumWavelengths &sw, const Vector &wo, Vector *wi, float u1, float u2, SWCSpectrum *const f, float *pdf, float *pdfBack, bool reverse) const { // Cosine-sample the hemisphere, flipping the direction if necessary *wi = CosineSampleHemisphere(u1, u2); if (wo.z < 0.f) wi->z = -(wi->z); // wi may be in the tangent plane, which will // fail the SameHemisphere test in Pdf() if (!SameHemisphere(wo, *wi)) return false; *pdf = Pdf(sw, wo, *wi); if (pdfBack) *pdfBack = Pdf(sw, *wi, wo); *f = SWCSpectrum(0.f); if (reverse) F(sw, *wi, wo, f); else F(sw, wo, *wi, f); *f /= *pdf; return true; }
// -------------------------------------------------- status_t DrawShape::IterateMoveTo(BPoint *point) { REPORT(kDebug, 0, "IterateMoveTo "); if (!TransformPath()) { PDF_moveto(Pdf(), tx(point->x), ty(point->y)); } else { EndSubPath(); fSubPath.MakeEmpty(); fSubPath.AddPoint(*point); } REPORT(kDebug, 0, "(%f, %f)", point->x, point->y); fCurrentPoint = *point; return B_OK; }
Spectrum Heitz::Sample_f(const Vector &wo, Vector *wi, float u1, float u2, float *pdf) const { // TODO: for test if (mUseUniformSampling) { return BxDF::Sample_f(wo, wi, u1, u2, pdf); } else { // TODO: what percentage between diffuse and specular? Currently use 50% if (u1 < 0.5f) { // Stretch u1 back to [0, 1) u1 *= 2; if (wo.z < 0.f) { // Reverse side mDistribution.Sample_f(-wo, wi, u1, u2, pdf); *wi = -(*wi); } else { mDistribution.Sample_f(wo, wi, u1, u2, pdf); } // Note: wo and wi are not guaranteed to be on the +Z side, nor are // they to be on the same side if (*pdf == 0.f) { // The sample is invalid - note it still needs to be considered // in Monte Carlo because invalid sample takes part of the PDF return Spectrum(0.f); } } else { // Stretch u1 back to [0, 1) u1 = 2 * (u1 - 0.5f); // Sampling wi at the same side as wo *wi = CosineSampleHemisphere(u1, u2); if (wo.z < 0.f) { *wi = -(*wi); } } // Compute PDF by calling Pdf(). This implementation is simpler and // less prone to error, but it's also less efficient *pdf = Pdf(wo, *wi); return f(wo, *wi); } }
// commented, dpl 10 august 2005 Spectrum FresnelBlend::Sample_f(const Vector &wo, Vector *wi, float u1, float u2, float *pdf) const { if (u1 < .5) { u1 = 2.f * u1; // Cosine-sample the hemisphere, flipping the direction if necessary *wi = CosineSampleHemisphere(u1, u2); if (wo.z < 0.) wi->z *= -1.f; } else { u1 = 2.f * (u1 - .5f); distribution->Sample_f(wo, wi, u1, u2, pdf); if (!SameHemisphere(wo, *wi)) return Spectrum(0.f); } *pdf = Pdf(wo, *wi); return f(wo, *wi); }
// -------------------------------------------------- status_t DrawShape::IterateLineTo(int32 lineCount, BPoint *linePoints) { REPORT(kDebug, 0, "IterateLineTo %d", (int)lineCount); BPoint *p = linePoints; for (int32 i = 0; i < lineCount; i++) { REPORT(kDebug, 0, "(%f, %f) ", p->x, p->y); if (TransformPath()) { fSubPath.AddPoint(*p); } else { PDF_lineto(Pdf(), tx(p->x), ty(p->y)); } fCurrentPoint = *p; p++; } return B_OK; }
// -------------------------------------------------- void DrawShape::Draw() { if (!fDrawn) { fDrawn = true; if (IsDrawing()) { if (fStroke) fWriter->StrokeOrClip(); // strokes always else { fWriter->FillOrClip(); // fills always } } else if (TransformPath()) { EndSubPath(); } else { PDF_closepath(Pdf()); } } }
// -------------------------------------------------- status_t DrawShape::IterateBezierTo(int32 bezierCount, BPoint *control) { REPORT(kDebug, 0, "BezierTo"); for (int32 i = 0; i < bezierCount; i++, control += 3) { REPORT(kDebug, 0," (%f %f) (%f %f) (%f %f)", tx(control[0].x), ty(control[0].y), tx(control[1].x), ty(control[1].y), tx(control[2].x), ty(control[2].y)); if (TransformPath()) { BPoint p[4] = { fCurrentPoint, control[0], control[1], control[2] }; CreateBezierPath(p); } else { PDF_curveto(Pdf(), tx(control[0].x), ty(control[0].y), tx(control[1].x), ty(control[1].y), tx(control[2].x), ty(control[2].y)); } fCurrentPoint = control[2]; } return B_OK; }
Spectrum FresnelBlend::Sample_f(const Vector3f &wo, Vector3f *wi, const Point2f &uOrig, Float *pdf, BxDFType *sampledType) const { Point2f u = uOrig; if (u[0] < .5) { u[0] = 2 * u[0]; // Cosine-sample the hemisphere, flipping the direction if necessary *wi = CosineSampleHemisphere(u); if (wo.z < 0) wi->z *= -1; } else { u[0] = 2 * (u[0] - .5f); // Sample microfacet orientation $\wh$ and reflected direction $\wi$ Vector3f wh = distribution->Sample_wh(wo, u); *wi = Reflect(wo, wh); if (!SameHemisphere(wo, *wi)) return Spectrum(0.f); } *pdf = Pdf(wo, *wi); return f(wo, *wi); }
// sample a direction randomly Spectrum Bxdf::sample_f( const Vector& wo , Vector& wi , const BsdfSample& bs , float* pdf ) const { wi = CosSampleHemisphere( bs.u , bs.v ); if( pdf ) *pdf = Pdf( wo , wi ); return f( wo , wi ); }