Esempio n. 1
0
double BSDF::ShadingNormalCorrectionFactor( BSDFRecord& record, Intersection& isect )
{
	// Prevent light leak
	// In some cases wi and wo are same side according to the shading normal but
	// opposite side according to the geometry normal.
	auto worldWi = isect.shadingToWorld * record.wi;
	auto worldWo = isect.shadingToWorld * record.wo;
	double wiDotNg = Math::Dot(worldWi, isect.gn);
	double woDotNg = Math::Dot(worldWo, isect.gn);

	if (wiDotNg * CosTheta(record.wi) <= 0 || woDotNg * CosTheta(record.wo) <= 0)
	{
		return 0.0;
	}

	// Special handling for adjoint case
	// Be careful of the difference of the notation between Veach's thesis;
	// in the framework, wo is always the propagating direction.
	if (record.adjoint)
	{
		// |w_i, N_s| * |w_o, N_g| / |w_i, N_g| / |w_o, N_s| 
		return CosTheta(record.wi) * woDotNg / (CosTheta(record.wo) * wiDotNg);
	}

	return 1.0;
}
Esempio n. 2
0
Spectrum FresnelSpecular::Sample_f(const Vector3f &wo, Vector3f *wi,
                                   const Point2f &u, Float *pdf,
                                   BxDFType *sampledType) const {
    Float F = FrDielectric(CosTheta(wo), etaA, etaB);
    if (u[0] < F) {
        // Compute specular reflection for _FresnelSpecular_

        // Compute perfect specular reflection direction
        *wi = Vector3f(-wo.x, -wo.y, wo.z);
        if (sampledType)
            *sampledType = BxDFType(BSDF_SPECULAR | BSDF_REFLECTION);
        *pdf = F;
        return F * R / AbsCosTheta(*wi);
    } else {
        // Compute specular transmission for _FresnelSpecular_

        // Figure out which $\eta$ is incident and which is transmitted
        bool entering = CosTheta(wo) > 0;
        Float etaI = entering ? etaA : etaB;
        Float etaT = entering ? etaB : etaA;

        // Compute ray direction for specular transmission
        if (!Refract(wo, Faceforward(Normal3f(0, 0, 1), wo), etaI / etaT, wi))
            return 0;
        Spectrum ft = T * (1 - F);

        // Account for non-symmetry with transmission to different medium
        if (mode == TransportMode::Radiance)
            ft *= (etaI * etaI) / (etaT * etaT);
        if (sampledType)
            *sampledType = BxDFType(BSDF_SPECULAR | BSDF_TRANSMISSION);
        *pdf = 1 - F;
        return ft / AbsCosTheta(*wi);
    }
}
Spectrum SpecularReflection::Sample_f(const Vector &wo,
		Vector *wi, float u1, float u2, float *pdf) const {
	// Compute perfect specular reflection direction
	*wi = Vector(-wo.x, -wo.y, wo.z);
	*pdf = 1.f;
	return fresnel->Evaluate(CosTheta(wo)) * R /
		fabsf(CosTheta(*wi));
}
Esempio n. 4
0
double DiffuseBSDF::Pdf( BSDFRecord& record )
{
	if ((record.type & BSDFType::DiffuseReflection) == 0 || CosTheta(record.wi) <= 0 || CosTheta(record.wo) <= 0)
	{
		return 0.0;
	}

	return CosTheta(record.wo) * InvPi;
}
Spectrum Microfacet::f(const Vector &wo,
                       const Vector &wi) const {
	float cosThetaO = fabsf(CosTheta(wo));
	float cosThetaI = fabsf(CosTheta(wi));
	Vector wh = Normalize(wi + wo);
	float cosThetaH = Dot(wi, wh);
	Spectrum F = fresnel->Evaluate(cosThetaH);
	return R * distribution->D(wh) * G(wo, wi, wh) * F /
		 (4.f * cosThetaI * cosThetaO);
}
Esempio n. 6
0
Spectrum FourierBSDF::f(const Vector3f &wo, const Vector3f &wi) const {
    // Find the zenith angle cosines and azimuth difference angle
    Float muI = CosTheta(-wi), muO = CosTheta(wo);
    Float cosPhi = CosDPhi(-wi, wo);

    // Compute Fourier coefficients $a_k$ for $(\mui, \muo)$

    // Determine offsets and weights for $\mui$ and $\muo$
    int offsetI, offsetO;
    Float weightsI[4], weightsO[4];
    if (!bsdfTable.GetWeightsAndOffset(muI, &offsetI, weightsI) ||
        !bsdfTable.GetWeightsAndOffset(muO, &offsetO, weightsO))
        return Spectrum(0.f);

    // Allocate storage to accumulate _ak_ coefficients
    Float *ak = ALLOCA(Float, bsdfTable.mMax * bsdfTable.nChannels);
    memset(ak, 0, bsdfTable.mMax * bsdfTable.nChannels * sizeof(Float));

    // Accumulate weighted sums of nearby $a_k$ coefficients
    int mMax = 0;
    for (int b = 0; b < 4; ++b) {
        for (int a = 0; a < 4; ++a) {
            // Add contribution of _(a, b)_ to $a_k$ values
            Float weight = weightsI[a] * weightsO[b];
            if (weight != 0) {
                int m;
                const Float *ap = bsdfTable.GetAk(offsetI + a, offsetO + b, &m);
                mMax = std::max(mMax, m);
                for (int c = 0; c < bsdfTable.nChannels; ++c)
                    for (int k = 0; k < m; ++k)
                        ak[c * bsdfTable.mMax + k] += weight * ap[c * m + k];
            }
        }
    }

    // Evaluate Fourier expansion for angle $\phi$
    Float Y = std::max((Float)0, Fourier(ak, mMax, cosPhi));
    Float scale = muI != 0 ? (1 / std::abs(muI)) : (Float)0;

    // Update _scale_ to account for adjoint light transport
    if (mode == TransportMode::Radiance && muI * muO > 0) {
        float eta = muI > 0 ? 1 / bsdfTable.eta : bsdfTable.eta;
        scale *= eta * eta;
    }
    if (bsdfTable.nChannels == 1)
        return Spectrum(Y * scale);
    else {
        // Compute and return RGB colors for tabulated BSDF
        Float R = Fourier(ak + 1 * bsdfTable.mMax, mMax, cosPhi);
        Float B = Fourier(ak + 2 * bsdfTable.mMax, mMax, cosPhi);
        Float G = 1.39829f * Y - 0.100913f * B - 0.297375f * R;
        Float rgb[3] = {R * scale, G * scale, B * scale};
        return Spectrum::FromRGB(rgb).Clamp();
    }
}
Spectrum FresnelBlend::f(const Vector &wo,
                         const Vector &wi) const {
	Spectrum diffuse = (28.f/(23.f*M_PI)) * Rd *
		(Spectrum(1.) - Rs) *
		(1 - powf(1 - .5f * fabsf(CosTheta(wi)), 5)) *
		(1 - powf(1 - .5f * fabsf(CosTheta(wo)), 5));
	Vector H = Normalize(wi + wo);
	Spectrum specular = distribution->D(H) /
		(8.f * M_PI * AbsDot(wi, H) *
		max(fabsf(CosTheta(wi)), fabsf(CosTheta(wo)))) *
		SchlickFresnel(Dot(wi, H));
	return diffuse + specular;
}
Esempio n. 8
0
float
GGXForHeitz::Pdf(const Vector &wo, const Vector &wi) const
{
    // We allow cos(theta_o) == 0 because it doesn't break our computation
    Assert(CosTheta(wo) >= 0.f);

    Vector wh = Normalize(wo + wi);
    float dotHO = Dot(wo, wh);
    if (dotHO < sSmallValue) {
        return 0.f;
    }

    return D(wh) * CosTheta(wh) / (4.f * dotHO);
}
Esempio n. 9
0
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;
}
Esempio n. 10
0
Vec3d DiffuseBSDF::Evaluate( BSDFRecord& record, Intersection& isect )
{
	if ((record.type & BSDFType::DiffuseReflection) == 0 || CosTheta(record.wi) <= 0 || CosTheta(record.wo) <= 0)
	{
		return Vec3d();
	}

	// Correction factor
	double sf = ShadingNormalCorrectionFactor(record, isect);
	if (sf == 0.0)
	{
		return Vec3d();
	}

	return R->Evaluate(isect.uv) * InvPi * CosTheta(record.wo) * sf;
}
Esempio n. 11
0
// wo.z >= 0 is guaranteed
// Note the sampled wi ~ D(wh)*cos(thetah)/(4*dot(wo,wh))
// and pdf = 0 when dot(wo, wh) < 0 (make sure Pdf() does the same thing)
void
GGXForHeitz::Sample_f(const Vector &wo, Vector *wi, float u1, float u2,
                     float *pdf) const
{
    // We allow cos(theta_o) == 0 because it doesn't break our computation
    Assert(CosTheta(wo) >= 0.f);

    // From [Walter et al., 2007]
    float thetah = atanf(mAlpha * sqrt(u1) / sqrt(1.f-u1)),
          costhetah = cosf(thetah), 
          sinthetah = sinf(thetah),
          phih = u2 * 2.f * M_PI;
    Vector wh = SphericalDirection(sinthetah, costhetah, phih);

    // Compute incident direction by reflecting about $\wh$
    float dotHO = Dot(wo, wh);

    if (dotHO < sSmallValue) {
        *pdf = 0.f;

    } else {
        *wi = -wo + 2.f * dotHO * wh;
        // TODO: test
        //if (wi->z < 0) {
        //    fprintf(stderr, "wi.z == %f\n", wi->z);
        //}
        // TODO: can be optimized
        *pdf = D(wh) * costhetah / (4.f * dotHO);
    }
}
Esempio n. 12
0
Spectrum KajiyaKay::f(const Vector3f &wo, const Vector3f &wi) const {
    Spectrum diffuse(0.f), specular(0.f);
    if (!Ks.IsBlack()) {
        // Compute specular Kajiya-Kay term
        Vector3f wh = wi + wo;
        if (!(wh.x == 0 && wh.y == 0 && wh.z == 0)) {
            wh = Normalize(wh);
#if 0
            Float cosThetaH = Dot(wo, wh);
            Float sinThetaH = std::sqrt(std::max((Float)0, (Float)1 - cosThetaH * cosThetaH));
            Float cosThetaO = CosTheta(wo), sinThetaO = SinTheta(wo);
            Float spec = std::pow(cosThetao * cosThetah + sinThetaO * sinThetaH,
                                  exponent);
#else
            Float tdoth = wh.x;
            Float spec = std::pow(
                std::sqrt(std::max((Float)0, (Float)1 - tdoth * tdoth)),
                exponent);
#endif
            specular = spec * Ks;
        }
    }
    // Compute diffuse Kajiya-Kay term
    diffuse = Kd * std::sqrt(std::max((Float)0., (Float)1. - wi.x * wi.x));
    return (InvPi / AbsCosTheta(wi)) * (diffuse + specular);
}
Esempio n. 13
0
void SpotLight::Pdf_Le(const Ray &ray, const Normal3f &, Float *pdfPos,
                       Float *pdfDir) const {
    *pdfPos = 0;
    *pdfDir = (CosTheta(WorldToLight(ray.d)) >= cosTotalWidth)
                  ? UniformConePdf(cosTotalWidth)
                  : 0;
}
Esempio n. 14
0
struct Spectrum SpecularReflection_cc_Sample_f(struct const_Vector wo, struct Vector *wi, float u1, float u2, float *pdf) {
    // Compute perfect specular reflection direction
    *wi = make_Vector(-wo.x, -wo.y, wo.z);
    *pdf = 1.f;
    struct Spectrum tmp1 = multiply(fresnel_arrow_Evaluate(CosTheta(wo)), make_Spectrum(R));
    return div(tmp1, make_Spectrum(AbsCosTheta(*wi)));
}
struct Spectrum SpecularReflection_cc_Sample_f(const_Vector wo, Vector *wi, float u1, float u2, float *pdf) {
//    return 0;// mgr
//    return 1;//mgr
    // Compute perfect specular reflection direction
    *wi = make_Vector(-wo.x, -wo.y, wo.z);
    *pdf = 1.f;
    return make_Spectrum(fresnel__Evaluate(CosTheta(wo)) * R / AbsCosTheta(*wi));
}
Esempio n. 16
0
Spectrum SpecularTransmission::Sample_f(const Vector3f &wo, Vector3f *wi,
                                        const Point2f &sample, Float *pdf,
                                        BxDFType *sampledType) const {
    // Figure out which $\eta$ is incident and which is transmitted
    bool entering = CosTheta(wo) > 0;
    Float etaI = entering ? etaA : etaB;
    Float etaT = entering ? etaB : etaA;

    // Compute ray direction for specular transmission
    if (!Refract(wo, Faceforward(Normal3f(0, 0, 1), wo), etaI / etaT, wi))
        return 0;
    *pdf = 1;
    Spectrum ft = T * (Spectrum(1.) - fresnel.Evaluate(CosTheta(*wi)));
    // Account for non-symmetry with transmission to different medium
    if (mode == TransportMode::Radiance) ft *= (etaI * etaI) / (etaT * etaT);
    return ft / AbsCosTheta(*wi);
}
Esempio n. 17
0
void ProjectionLight::Pdf_Le(const Ray &ray, const Normal3f &, Float *pdfPos,
                             Float *pdfDir) const {
    ProfilePhase _(Prof::LightPdf);
    *pdfPos = 0.f;
    *pdfDir = (CosTheta(WorldToLight(ray.d)) >= cosTotalWidth)
                  ? UniformConePdf(cosTotalWidth)
                  : 0;
}
Esempio n. 18
0
Spectrum SpecularReflection::Sample_f(const Vector3f &wo, Vector3f *wi,
                                      const Point2f &sample, Float *pdf,
                                      BxDFType *sampledType) const {
    // Compute perfect specular reflection direction
    *wi = Vector3f(-wo.x, -wo.y, wo.z);
    *pdf = 1;
    return fresnel->Evaluate(CosTheta(*wi)) * R / AbsCosTheta(*wi);
}
Esempio n. 19
0
Spectrum
Heitz::f(const Vector &woInput, const Vector &wiInput) const
{
    // In PBRT's implementation, woInput and wiInput is not guaranteed to be at the same side of the shading normal
    // We inverse them if woInput is on the other side.
    // Note: because BSDF::f() determines BSDF_REFLECTION and BSDF_TRANSMISSION using ng (geometric normal) instead
	//       of nn (shading normal), it's possible that woInput and wiInput has opposite sign of z-axis. Therefore,
	//       we determine if the shading normal is at the opposite side using woInput (viewing direction) only: we
	//       always make the viewing direction from the +Z side

    Vector wo = woInput, wi = wiInput;
    if (wo.z < 0.f) {
        // Reverse side
        wo = -wo;
        wi = -wi;
    }

    float cosThetaO = CosTheta(wo),
          absCosThetaI = AbsCosTheta(wi);
    Assert(cosThetaO >= 0.f);
    if (cosThetaO < sSmallValue || absCosThetaI < sSmallValue) {
        return Spectrum(0.f);
    }

    Vector wh = wi + wo;
    if (wh.x == 0. && wh.y == 0. && wh.z == 0.) {
        return Spectrum(0.f);
    }
    wh = Normalize(wh);
    float i_dot_h = Dot(wi, wh);
    Spectrum F = fresnel->Evaluate(i_dot_h);

    // Specular/glossy component
    float spec = mDistribution.D(wh) * mDistribution.G(wo, wi, wh) /
            (4.f * cosThetaO * absCosThetaI);

    // Diffuse component
    Spectrum Fdiff = Spectrum(1.f) - fresnel->Evaluate(cosThetaO);
    float diff = wi.z > 0.f ? INV_PI : 0.f;

    // TODO: test
    //F = Spectrum(1.f);

    // Note wi is possible to be at lower hemisphere, so we need to use
    // AbsCosTheta()
    //return R * (F * spec + (Spectrum(1.f) - F) * diff);
    return R * (F * spec + Fdiff * diff);

    // TODO: test
    /*float Dval = mDistribution.D(wh),
          Gval = mDistribution.G(wo, wi, wh);
    Spectrum val = R * Dval * Gval * F /
            (4.f * cosThetaO * absCosThetaI);
    if (isinf(val.y()) || val.y() < -sSmallValue) {
        fprintf(stderr, "invalid value\n");
    }
    return val;*/
}
Esempio n. 20
0
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);
}
Esempio n. 21
0
Float FourierBSDF::Pdf(const Vector3f &wo, const Vector3f &wi) const {
    // Find the zenith angle cosines and azimuth difference angle
    Float muI = CosTheta(-wi), muO = CosTheta(wo);
    Float cosPhi = CosDPhi(-wi, wo);

    // Compute luminance Fourier coefficients $a_k$ for $(\mui, \muo)$
    int offsetI, offsetO;
    Float weightsI[4], weightsO[4];
    if (!bsdfTable.GetWeightsAndOffset(muI, &offsetI, weightsI) ||
        !bsdfTable.GetWeightsAndOffset(muO, &offsetO, weightsO))
        return 0;
    Float *ak = ALLOCA(Float, bsdfTable.mMax * bsdfTable.nChannels);
    memset(ak, 0, bsdfTable.mMax * bsdfTable.nChannels * sizeof(Float));
    int mMax = 0;
    for (int o = 0; o < 4; ++o) {
        for (int i = 0; i < 4; ++i) {
            Float weight = weightsI[i] * weightsO[o];
            if (weight == 0) continue;

            int order;
            const Float *coeffs =
                bsdfTable.GetAk(offsetI + i, offsetO + o, &order);
            mMax = std::max(mMax, order);

            for (int k = 0; k < order; ++k) ak[k] += *coeffs++ * weight;
        }
    }

    // Evaluate probability of sampling _wi_
    Float rho = 0;
    for (int o = 0; o < 4; ++o) {
        if (weightsO[o] == 0) continue;
        rho +=
            weightsO[o] *
            bsdfTable.cdf[(offsetO + o) * bsdfTable.nMu + bsdfTable.nMu - 1] *
            (2 * Pi);
    }
    Float Y = Fourier(ak, mMax, cosPhi);
    return (rho > 0 && Y > 0) ? (Y / rho) : 0;
}
// commented, dpl 10 august 2005
Spectrum OrenNayar::f(const Vector &wo,
		const Vector &wi) const {
	float sinthetai = SinTheta(wi);
	float sinthetao = SinTheta(wo);
	// Compute cosine term of Oren--Nayar model
	float sinphii = SinPhi(wi), cosphii = CosPhi(wi);
	float sinphio = SinPhi(wo), cosphio = CosPhi(wo);
	float dcos = cosphii * cosphio + sinphii * sinphio;
	float maxcos = max(0.f, dcos);
	// Compute sine and tangent terms of Oren--Nayar model
	float sinalpha, tanbeta;
	if (fabsf(CosTheta(wi)) > fabsf(CosTheta(wo))) {
		sinalpha = sinthetao;
		tanbeta = sinthetai / fabsf(CosTheta(wi));
	}
	else {
		sinalpha = sinthetai;
		tanbeta = sinthetao / fabsf(CosTheta(wo));
	}
	return R * INV_PI *
	       (A + B * maxcos * sinalpha * tanbeta);
}
Esempio n. 23
0
RGB SpecularTransmission::Sample_f(const Vector& wo, Vector* wi, float u1,
		float u2, float *pdf) const {
	bool entering = CosTheta(wo) > 0.;
	float ei = mEtaI, et = mEtaT;
	if (!entering) //判断wo是从外面射入还是从内部射出
		swap(ei, et);
	//根据Snell's law 计算折射方向
	float sini2 = SinTheta2(wo);
	float eta = ei / et;
	float sint2 = eta * eta * sini2;

	if (sint2 >= 1.)
		return 0.; //所有的光线全部反射,所以没有折射
	float cost = sqrtf(max(0.f, 1.f - sint2));
	if (entering)
		cost = -cost; //设置符号
	float sintOverSini = eta;
	*wi = Vector(sintOverSini * -wo.x, sintOverSini * -wo.y, cost);
	*pdf = 1.f;
	RGB F = mFresnel.Evaluate(CosTheta(wo)); //计算反射系数
	return (ei * ei) / (et * et) * (RGB(1.0f) - F) * mScale / AbsCosTheta(*wi);
}
Esempio n. 24
0
Float MicrofacetTransmission::Pdf(const Vector3f &wo,
                                  const Vector3f &wi) const {
    if (SameHemisphere(wo, wi)) return 0;
    // Compute $\wh$ from $\wo$ and $\wi$ for microfacet transmission
    Float eta = CosTheta(wo) > 0 ? (etaB / etaA) : (etaA / etaB);
    Vector3f wh = Normalize(wo + wi * eta);

    // Compute change of variables _dwh\_dwi_ for microfacet transmission
    Float sqrtDenom = Dot(wo, wh) + eta * Dot(wi, wh);
    Float dwh_dwi =
        std::abs((eta * eta * Dot(wi, wh)) / (sqrtDenom * sqrtDenom));
    return distribution->Pdf(wo, wh) * dwh_dwi;
}
Esempio n. 25
0
Spectrum MicrofacetTransmission::f(const Vector3f &wo,
                                   const Vector3f &wi) const {
    if (SameHemisphere(wo, wi)) return 0;  // transmission only

    Float cosThetaO = CosTheta(wo);
    Float cosThetaI = CosTheta(wi);
    if (cosThetaI == 0 || cosThetaO == 0) return Spectrum(0);

    // Compute $\wh$ from $\wo$ and $\wi$ for microfacet transmission
    Float eta = CosTheta(wo) > 0 ? (etaB / etaA) : (etaA / etaB);
    Vector3f wh = Normalize(wo + wi * eta);
    if (wh.z < 0) wh = -wh;

    Spectrum F = fresnel.Evaluate(Dot(wo, wh));

    Float sqrtDenom = Dot(wo, wh) + eta * Dot(wi, wh);
    Float factor = (mode == TransportMode::Radiance) ? (1 / eta) : 1;

    return (Spectrum(1.f) - F) * T *
           std::abs(distribution->D(wh) * distribution->G(wo, wi) * eta * eta *
                    AbsDot(wi, wh) * AbsDot(wo, wh) * factor * factor /
                    (cosThetaI * cosThetaO * sqrtDenom * sqrtDenom));
}
// commented, dpl 10 august 2005
Spectrum SpecularTransmission::Sample_f(const Vector &wo,
		Vector *wi, float u1, float u2, float *pdf) const {
	// Figure out which $\eta$ is incident and which is transmitted
	bool entering = CosTheta(wo) > 0.;
	float ei = etai, et = etat;
	if (!entering)
		swap(ei, et);
	// Compute transmitted ray direction
	float sini2 = SinTheta2(wo);
	float eta = ei / et;
	float sint2 = eta * eta * sini2;
	// Handle total internal reflection for transmission
	if (sint2 > 1.) return 0.;
	float cost = sqrtf(max(0.f, 1.f - sint2));
	if (entering) cost = -cost;
	float sintOverSini = eta;
	*wi = Vector(sintOverSini * -wo.x,
	             sintOverSini * -wo.y,
				 cost);
	*pdf = 1.f;
	Spectrum F = fresnel.Evaluate(CosTheta(wo));
	return (ei*ei)/(et*et) * (Spectrum(1.)-F) * T /
		fabsf(CosTheta(*wi));
}
Esempio n. 27
0
float
GGXForHeitz::D(const Vector &wh) const
{
    float costhetah = CosTheta(wh);
    if (costhetah < sSmallValue) {
        return 0.f;
    } else {
        Assert(costhetah > 0.f && costhetah <= 1.f);
        float thetah = acosf(costhetah),
              costhetah2 = costhetah * costhetah,
              costhetah4 = costhetah2 * costhetah2,
              tanthetah = tanf(thetah),
              alphaSq = mAlpha * mAlpha,
              tanOverAlpha2 = (tanthetah * tanthetah) / alphaSq,
              factor = 1.f + tanOverAlpha2;
        return 1.f / (M_PI * alphaSq * costhetah4 * factor * factor);
    }
}
Esempio n. 28
0
float
GGXForHeitz::G(const Vector &wo, const Vector &/*wi*/, const Vector &wh) const
{
    float costhetao = CosTheta(wo);
    if (costhetao < sSmallValue) {
        return 0.f;
    }

    // TODO: currently, we only compute G1(wo, wh)
    float dotHO = Dot(wo, wh);
    if (dotHO < 0.f) {
        return 0.f;
    }
    float thetao = acosf(costhetao);
    if (thetao < sSmallValue) {
        return 1.f;
    }
    float a = 1.f / (mAlpha * tanf(thetao)),
          lambda = (-1.f + sqrtf(1.f + 1.f / (a*a))) / 2;
    return 1.f / (1.f + lambda);
}
Esempio n. 29
0
static Vector3f TrowbridgeReitzSample(const Vector3f &wi, Float alpha_x,
                                      Float alpha_y, Float U1, Float U2) {
    // 1. stretch wi
    Vector3f wiStretched =
        Normalize(Vector3f(alpha_x * wi.x, alpha_y * wi.y, wi.z));

    // 2. simulate P22_{wi}(x_slope, y_slope, 1, 1)
    Float slope_x, slope_y;
    TrowbridgeReitzSample11(CosTheta(wiStretched), U1, U2, &slope_x, &slope_y);

    // 3. rotate
    Float tmp = CosPhi(wiStretched) * slope_x - SinPhi(wiStretched) * slope_y;
    slope_y = SinPhi(wiStretched) * slope_x + CosPhi(wiStretched) * slope_y;
    slope_x = tmp;

    // 4. unstretch
    slope_x = alpha_x * slope_x;
    slope_y = alpha_y * slope_y;

    // 5. compute normal
    return Normalize(Vector3f(-slope_x, -slope_y, 1.));
}
Esempio n. 30
0
RGB SpecularReflection::Sample_f(const Vector& wo, Vector* wi, float u1,
		float u2, float *pdf) const {
	*wi = Vector(-wo.x, -wo.y, wo.z);	//反射向量
	*pdf = 1.f;	//概率分布为1
	return mFresnel->Evaluate(CosTheta(wo)) * mScale / AbsCosTheta(*wi); //镜面反射的brdf公式
}