Spectrum sample(BSDFQueryRecord &bRec, const Point2 &sample) const { bool sampleReflection = (bRec.typeMask & EDeltaReflection) && (bRec.component == -1 || bRec.component == 0); if (!sampleReflection || Frame::cosTheta(bRec.wi) <= 0) return Spectrum(0.0f); bRec.sampledComponent = 0; bRec.sampledType = EDeltaReflection; bRec.wo = reflect(bRec.wi); return m_specularReflectance->getValue(bRec.its) * fresnelConductor(Frame::cosTheta(bRec.wi), m_eta, m_k); }
Spectrum eval(const BSDFQueryRecord &bRec, EMeasure measure) const { bool sampleReflection = (bRec.typeMask & EDeltaReflection) && (bRec.component == -1 || bRec.component == 0); /* Verify that the provided direction pair matches an ideal specular reflection; tolerate some roundoff errors */ if (!sampleReflection || measure != EDiscrete || Frame::cosTheta(bRec.wi) <= 0 || Frame::cosTheta(bRec.wo) <= 0 || std::abs(1 - dot(reflect(bRec.wi), bRec.wo)) > Epsilon) return Spectrum(0.0f); return m_specularReflectance->getValue(bRec.its) * fresnelConductor(Frame::cosTheta(bRec.wi), m_eta, m_k); }
Float microfacet(Float mu_o, Float mu_i, std::complex<Float> eta_, Float alpha, Float phi_d) { Float sinThetaI = math::safe_sqrt(1-mu_i*mu_i), sinThetaO = math::safe_sqrt(1-mu_o*mu_o), cosPhi = std::cos(phi_d), sinPhi = std::sin(phi_d); Vector wi(-sinThetaI, 0, -mu_i); Vector wo(sinThetaO*cosPhi, sinThetaO*sinPhi, mu_o); bool reflect = -mu_i*mu_o > 0; if (mu_o == 0 || mu_i == 0) return 0.f; bool conductor = eta_.imag() != 0.0f; if (conductor && !reflect) return 0.0f; std::complex<Float> eta = (-mu_i > 0 || conductor) ? eta_ : std::complex<Float>(1) / eta_; Vector H = (wi + wo * (reflect ? 1.0f : eta.real())).normalized(); H *= math::signum(Frame::cosTheta(H)); Float cosThetaH2 = Frame::cosTheta2(H), exponent = -Frame::tanTheta2(H) / (alpha*alpha), D = std::exp(exponent) / (math::Pi * alpha*alpha * cosThetaH2*cosThetaH2), F = !conductor ? fresnelDielectric(wi.dot(H), eta_.real()) : fresnelConductor(std::abs(wi.dot(H)), eta), G = smithG1(wi, H, alpha) * smithG1(wo, H, alpha); if (reflect) { return F * D * G / (4.0f * std::abs(mu_i*mu_o)); } else { Float sqrtDenom = wi.dot(H) + eta.real() * wo.dot(H); return std::abs(((1 - F) * D * G * eta.real() * eta.real() * wi.dot(H) * wo.dot(H)) / (mu_i*mu_o * sqrtDenom * sqrtDenom)); } }
LDEVICE float3 F( float cos_theta ) { return fresnelConductor( cos_theta, m_eta, m_k ); }