FORCE_INLINE virtual double evaluate_pdf( const void* data, const Vector3d& geometric_normal, const Basis3d& shading_basis, const Vector3d& outgoing, const Vector3d& incoming, const int modes) const { if (!(modes & Glossy)) return 0.0; // If incoming and outgoing are on the same hemisphere // this is not a refraction. const Vector3d& n = shading_basis.get_normal(); if (dot(incoming, n) * dot(outgoing, n) >= 0.0) return Absorption; const InputValues* values = static_cast<const InputValues*>(data); double ht_norm; const Vector3d ht = half_refraction_vector( outgoing, incoming, n, values->m_from_ior, values->m_to_ior, ht_norm); const Vector3d m = shading_basis.transform_to_local(ht); const double dwh_dwo = refraction_jacobian( incoming, values->m_to_ior, ht, ht_norm); return m_mdf->pdf(m, values->m_ax, values->m_ay) * dwh_dwo; }
FORCE_INLINE virtual double evaluate( const void* data, const bool adjoint, const bool cosine_mult, const Vector3d& geometric_normal, const Basis3d& shading_basis, const Vector3d& outgoing, const Vector3d& incoming, const int modes, Spectrum& value) const { if (!(modes & Glossy)) return 0.0; // If incoming and outgoing are on the same hemisphere // this is not a refraction. const Vector3d& n = shading_basis.get_normal(); if (dot(incoming, n) * dot(outgoing, n) >= 0.0) return Absorption; const InputValues* values = static_cast<const InputValues*>(data); double ht_norm; const Vector3d ht = half_refraction_vector( outgoing, incoming, n, values->m_from_ior, values->m_to_ior, ht_norm); const Vector3d m = shading_basis.transform_to_local(ht); const double G = m_mdf->G( shading_basis.transform_to_local(incoming), shading_basis.transform_to_local(outgoing), m, values->m_ax, values->m_ay); if (G == 0.0) return 0.0; const double D = m_mdf->D(m, values->m_ax, values->m_ay); const double cos_oh = dot(outgoing, ht); const double cos_ih = dot(incoming, ht); const double cos_in = dot(incoming, n); const double cos_on = dot(outgoing, n); // [1] equation 21. double v = abs((cos_ih * cos_oh) / (cos_in * cos_on)); v *= square(values->m_to_ior) * D * G; const double denom = values->m_to_ior * cos_ih + values->m_from_ior * cos_oh; v /= square(denom); value.set(static_cast<float>(v)); const double dwh_dwo = refraction_jacobian( incoming, values->m_to_ior, ht, ht_norm); return m_mdf->pdf(m, values->m_ax, values->m_ay) * dwh_dwo; }
FORCE_INLINE virtual Mode sample( SamplingContext& sampling_context, const void* data, const bool adjoint, const bool cosine_mult, const Vector3d& geometric_normal, const Basis3d& shading_basis, const Vector3d& outgoing, Vector3d& incoming, Spectrum& value, double& probability) const { const InputValues* values = static_cast<const InputValues*>(data); // Compute the incoming direction by sampling the MDF. sampling_context.split_in_place(2, 1); const Vector2d s = sampling_context.next_vector2<2>(); const Vector3d m = m_mdf->sample(s, values->m_ax, values->m_ay); const Vector3d ht = shading_basis.transform_to_parent(m); if (!refract( outgoing, ht, values->m_from_ior / values->m_to_ior, incoming)) { // Ignore TIR. return Absorption; } // If incoming and outgoing are on the same hemisphere // this is not a refraction. const Vector3d& n = shading_basis.get_normal(); if (dot(incoming, n) * dot(outgoing, n) >= 0.0) return Absorption; const double G = m_mdf->G( shading_basis.transform_to_local(incoming), shading_basis.transform_to_local(outgoing), m, values->m_ax, values->m_ay); if (G == 0.0) return Absorption; const double D = m_mdf->D(m, values->m_ax, values->m_ay); const double cos_oh = dot(outgoing, ht); const double cos_ih = dot(incoming, ht); const double cos_in = dot(incoming, n); const double cos_on = dot(outgoing, n); // [1] equation 21. double v = abs((cos_ih * cos_oh) / (cos_in * cos_on)); v *= square(values->m_to_ior) * D * G; const double denom = values->m_to_ior * cos_ih + values->m_from_ior * cos_oh; v /= square(denom); value.set(static_cast<float>(v)); const double ht_norm = norm(values->m_from_ior * outgoing + values->m_to_ior * incoming); const double dwh_dwo = refraction_jacobian( incoming, values->m_to_ior, ht, ht_norm); probability = m_mdf->pdf(m, values->m_ax, values->m_ay) * dwh_dwo; return Glossy; }