Beispiel #1
0
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;
}
Beispiel #3
0
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;
}
Beispiel #4
0
// 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;
}