size_t CompositeClosure::choose_closure(const double w) const { assert(w >= 0.0); assert(w < 1.0); const double *i = upper_bound( m_cdf, m_cdf + get_num_closures(), w); assert(i < m_cdf + get_num_closures()); return i - m_cdf; }
void CompositeClosure::do_add_closure( const ClosureID closure_type, const Color3f& weight, const Vector3d& normal, const bool has_tangent, const Vector3d& tangent, const InputValues& params) { // Check that InputValues is included in our type list. typedef typename boost::mpl::contains<InputValuesTypeList,InputValues>::type value_in_list; BOOST_STATIC_ASSERT( value_in_list::value); // Make sure we have enough space. if (get_num_closures() >= MaxClosureEntries) { RENDERER_LOG_WARNING("maximum number of closures in OSL shadergroup exceeded; ignoring closure."); return; } assert(m_num_bytes + sizeof(InputValues) <= MaxPoolSize); // We use the luminance of the weight as the BSDF weight. const double w = luminance(weight); // Ignore zero or negative weights. if (w <= 0.0) return; m_cdf.insert(get_num_closures(), w); linear_rgb_reflectance_to_spectrum(weight, m_spectrum_multipliers[m_num_closures]); m_normals[m_num_closures] = normalize(normal); m_has_tangent[m_num_closures] = has_tangent; if (has_tangent) m_tangents[m_num_closures] = normalize(tangent); m_closure_types[m_num_closures] = closure_type; char* values_ptr = m_pool + m_num_bytes; assert(is_aligned(values_ptr, InputValuesAlignment)); new (values_ptr) InputValues(params); m_input_values[m_num_closures] = values_ptr; m_num_bytes += align(sizeof(InputValues), InputValuesAlignment); ++m_num_closures; }
CompositeClosure::CompositeClosure( const OSL::ClosureColor* ci) : m_num_closures(0) , m_num_bytes(0) { assert(is_aligned(m_pool, InputValuesAlignment)); process_closure_tree(ci, Color3f(1.0f)); if (get_num_closures()) m_cdf.prepare(); }
void CompositeSurfaceClosure::do_add_closure( const ClosureID closure_type, const Color3f& weight, const Vector3d& normal, bool has_tangent, const Vector3d& tangent, const InputValues& params) { // Check that InputValues is included in our type list. typedef typename boost::mpl::contains<InputValuesTypeList, InputValues>::type value_in_list; BOOST_STATIC_ASSERT(value_in_list::value); // Make sure we have enough space. if (get_num_closures() >= MaxClosureEntries) { RENDERER_LOG_WARNING("maximum number of closures in osl shader group exceeded; ignoring closure."); return; } assert(m_num_bytes + sizeof(InputValues) <= MaxPoolSize); // We use the luminance of the weight as the BSDF weight. const double w = luminance(weight); // Ignore zero or negative weights. if (w <= 0.0) return; m_pdf_weights[m_num_closures] = w; m_weights[m_num_closures] = weight; m_normals[m_num_closures] = normalize(normal); // If the tangent is zero, ignore it. // This can happen when using the isotropic microfacet closure overloads, for example. if (square_norm(tangent) == 0.0) has_tangent = false; m_has_tangent[m_num_closures] = has_tangent; if (has_tangent) m_tangents[m_num_closures] = normalize(tangent); m_closure_types[m_num_closures] = closure_type; char* values_ptr = m_pool + m_num_bytes; assert(is_aligned(values_ptr, InputValuesAlignment)); new (values_ptr) InputValues(params); m_input_values[m_num_closures] = values_ptr; m_num_bytes += align(sizeof(InputValues), InputValuesAlignment); ++m_num_closures; }
CompositeClosure::CompositeClosure( const OSL::ClosureColor* ci) : m_num_closures(0) , m_num_bytes(0) { assert(is_aligned(m_pool, InputValuesAlignment)); process_closure_tree(ci, Color3f(1.0f)); if (get_num_closures()) { double total_weight = 0.0; for (size_t i = 0, e = get_num_closures(); i < e; ++i) { total_weight += m_cdf[i]; m_cdf[i] = total_weight; } for (size_t i = 0, e = get_num_closures() - 1; i < e; ++i) m_cdf[i] /= total_weight; m_cdf[get_num_closures() - 1] = 1.0; } }
void CompositeClosure::compute_cdf() { const size_t closure_count = get_num_closures(); if (closure_count > 0) { double total_weight = 0.0; for (size_t i = 0; i < closure_count; ++i) { total_weight += m_pdf_weights[i]; m_cdf[i] = total_weight; } const double rcp_total_weight = 1.0 / total_weight; for (size_t i = 0; i < closure_count; ++i) m_pdf_weights[i] *= rcp_total_weight; for (size_t i = 0; i < closure_count - 1; ++i) m_cdf[i] *= rcp_total_weight; m_cdf[closure_count - 1] = 1.0; } }
void CompositeSubsurfaceClosure::add_closure( const ClosureID closure_type, const Color3f& weight, const InputValues& params) { // Check that InputValues is included in our type list. typedef typename boost::mpl::contains<InputValuesTypeList, InputValues>::type value_in_list; BOOST_STATIC_ASSERT(value_in_list::value); // Make sure we have enough space. if (get_num_closures() >= MaxClosureEntries) { RENDERER_LOG_WARNING("maximum number of subsurface closures in osl shader group exceeded; ignoring closure."); return; } assert(m_num_bytes + sizeof(InputValues) <= MaxPoolSize); // We use the luminance of the weight as the BSSRDF weight. const double w = luminance(weight); // Ignore zero or negative weights. if (w <= 0.0) return; m_pdf_weights[m_num_closures] = w; m_weights[m_num_closures] = weight; m_closure_types[m_num_closures] = closure_type; char* values_ptr = m_pool + m_num_bytes; assert(is_aligned(values_ptr, InputValuesAlignment)); new (values_ptr) InputValues(params); m_input_values[m_num_closures] = values_ptr; m_num_bytes += align(sizeof(InputValues), InputValuesAlignment); ++m_num_closures; }
size_t CompositeClosure::choose_closure(const double w) const { return sample_cdf(m_cdf, m_cdf + get_num_closures(), w); }