void weak_white_furnace_test( size_t num_runs, const float alpha_x, const float alpha_y, const float gamma, const float angle_step, WeakWhiteFurnaceTestResult& result) { result.m_min_G1 = numeric_limits<float>::max(); result.m_max_G1 = -numeric_limits<float>::max(); result.m_min_result = numeric_limits<float>::max(); result.m_max_result = -numeric_limits<float>::max(); MDF mdf; for (size_t i = 0; i < num_runs; ++i) { static const size_t Bases[] = { 2 }; const Vector2f s = hammersley_sequence<float, 2>(Bases, num_runs, i); const Vector3f v = sample_hemisphere_uniform(s); const float G1 = mdf.G1(v, Vector3f(0.0f, 1.0, 0.0f), alpha_x, alpha_y, gamma); result.m_min_G1 = std::min(result.m_min_G1, G1); result.m_max_G1 = std::max(result.m_max_G1, G1); const float cos_thetha_o_4 = std::abs(4.0f * v.y); float integral = 0.0f; for (float theta = 0.0f; theta < Pi<float>(); theta += angle_step) { const float cos_theta = std::cos(theta); const float sin_theta = std::sin(theta); for (float phi = 0.0f; phi < TwoPi<float>(); phi += angle_step) { const float cos_phi = std::cos(phi); const float sin_phi = std::sin(phi); const Vector3f l = Vector3f::make_unit_vector( cos_theta, sin_theta, cos_phi, sin_phi); const Vector3f h = normalize(v + l); if (h.y > 0.0f) integral += sin_theta * mdf.D(h, alpha_x, alpha_y, gamma) * G1 / cos_thetha_o_4; } } // Result should be 1. integral *= square(angle_step); result.m_min_result = std::min(result.m_min_result, integral); result.m_max_result = std::max(result.m_max_result, integral); } }
void weak_white_furnace_test( size_t num_runs, const double alpha_x, const double alpha_y, const double angle_step, WeakWhiteFurnaceTestResult& result) { result.m_min_G1 = numeric_limits<double>::max(); result.m_max_G1 = -numeric_limits<double>::max(); result.m_min_result = numeric_limits<double>::max(); result.m_max_result = -numeric_limits<double>::max(); MDF mdf; for (size_t i = 0; i < num_runs; ++i) { static const size_t Bases[] = { 2 }; const Vector2d s = hammersley_sequence<double, 2>(Bases, num_runs, i); const Vector3d v = sample_hemisphere_uniform(s); const double G1 = mdf.G1(v, Vector3d(0.0, 1.0, 0.0), alpha_x, alpha_y); result.m_min_G1 = std::min(result.m_min_G1, G1); result.m_max_G1 = std::max(result.m_max_G1, G1); const double cos_thetha_o_4 = std::abs(4.0 * v.y); double integral = 0.0; for (double theta = 0.0; theta < Pi<double>(); theta += angle_step) { const double cos_theta = std::cos(theta); const double sin_theta = std::sin(theta); for (double phi = 0.0; phi < TwoPi<double>(); phi += angle_step) { const double cos_phi = std::cos(phi); const double sin_phi = std::sin(phi); const Vector3d l = Vector3d::make_unit_vector( cos_theta, sin_theta, cos_phi, sin_phi); const Vector3d h = normalize(v + l); if (h.y > 0.0) integral += sin_theta * mdf.D(h, alpha_x, alpha_y) * G1 / cos_thetha_o_4; } } // Result should be 1. integral *= square(angle_step); result.m_min_result = std::min(result.m_min_result, integral); result.m_max_result = std::max(result.m_max_result, integral); } }
bool is_positive( const MDF& mdf, const typename MDF::ValueType alpha_x, const typename MDF::ValueType alpha_y, const size_t sample_count) { for (size_t i = 0; i < sample_count; ++i) { static const size_t Bases[] = { 2 }; const Vector2d s = hammersley_sequence<double, 2>(Bases, sample_count, i); const Vector<typename MDF::ValueType, 3> h = sample_hemisphere_uniform(s); const double value = mdf.D(h, alpha_x, alpha_y); if (value < 0.0) return false; } return true; }
bool is_positive( const MDF& mdf, const float alpha_x, const float alpha_y, const size_t sample_count, const float gamma = 0.0f) { for (size_t i = 0; i < sample_count; ++i) { static const size_t Bases[] = { 2 }; const Vector2f s = hammersley_sequence<float, 2>(Bases, sample_count, i); const Vector3f h = sample_hemisphere_uniform(s); const float value = mdf.D(h, alpha_x, alpha_y, gamma); if (value < 0.0f) return false; } return true; }
float integrate( const MDF& mdf, const float alpha, const size_t sample_count, const float gamma = 0.0f) { float integral = 0.0f; for (size_t i = 0; i < sample_count; ++i) { const float theta = radical_inverse_base2<float>(i) * HalfPi<float>(); const Vector3f h(0.0f, cos(theta), 0.0f); const float value = mdf.D(h, alpha, alpha, gamma); integral += value * h.y * sin(theta); } integral *= HalfPi<float>() / sample_count; // integration over theta integral *= TwoPi<float>(); // integration over phi return integral; }
typename MDF::ValueType integrate( const MDF& mdf, const typename MDF::ValueType alpha, const size_t sample_count) { typedef typename MDF::ValueType ValueType; ValueType integral = ValueType(0.0); for (size_t i = 0; i < sample_count; ++i) { const ValueType theta = radical_inverse_base2<ValueType>(i) * HalfPi<ValueType>(); const Vector<ValueType, 3> h(ValueType(0.0), cos(theta), ValueType(0.0)); const ValueType value = mdf.D(h, alpha, alpha); integral += value * h.y * sin(theta); } integral *= HalfPi<ValueType>() / sample_count; // integration over theta integral *= TwoPi<ValueType>(); // integration over phi return integral; }