CompositeSurfaceClosure::CompositeSurfaceClosure( const BSDF* osl_bsdf, const OSL::ClosureColor* ci) : m_osl_bsdf(osl_bsdf) { assert(m_osl_bsdf); process_closure_tree(ci, Color3f(1.0f)); compute_cdf(); }
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 CompositeEmissionClosure::process_closure_tree( const OSL::ClosureColor* closure, const Color3f& weight) { if (closure == 0) return; switch (closure->type) { case OSL::ClosureColor::MUL: { const OSL::ClosureMul* c = reinterpret_cast<const OSL::ClosureMul*>(closure); process_closure_tree(c->closure, weight * Color3f(c->weight)); } break; case OSL::ClosureColor::ADD: { const OSL::ClosureAdd* c = reinterpret_cast<const OSL::ClosureAdd*>(closure); process_closure_tree(c->closureA, weight); process_closure_tree(c->closureB, weight); } break; case OSL::ClosureColor::COMPONENT: { const OSL::ClosureComponent* c = reinterpret_cast<const OSL::ClosureComponent*>(closure); if (c->id == EmissionID) m_total_weight += weight * Color3f(c->w); } break; assert_otherwise; } }
CompositeEmissionClosure::CompositeEmissionClosure( const OSL::ClosureColor* ci) { m_total_weight = Color3f(0.0f); process_closure_tree(ci, Color3f(1.0f)); const float max_comp = max_value(m_total_weight); if (max_comp != 0.0f) { m_total_weight /= max_comp; m_edf_values.m_radiance = m_total_weight; m_edf_values.m_radiance_multiplier = static_cast<double>(max_comp); } else { m_edf_values.m_radiance.set(0.0f); m_edf_values.m_radiance_multiplier = 1.0; } }
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::process_closure_tree( const OSL::ClosureColor* closure, const Color3f& weight) { if (closure == 0) return; switch (closure->type) { case OSL::ClosureColor::MUL: { const OSL::ClosureMul* c = reinterpret_cast<const OSL::ClosureMul*>(closure); const Color3f w = weight * Color3f(c->weight); process_closure_tree(c->closure, w); } break; case OSL::ClosureColor::ADD: { const OSL::ClosureAdd* c = reinterpret_cast<const OSL::ClosureAdd*>(closure); process_closure_tree(c->closureA, weight); process_closure_tree(c->closureB, weight); } break; case OSL::ClosureColor::COMPONENT: { const OSL::ClosureComponent* c = reinterpret_cast<const OSL::ClosureComponent*>(closure); const Color3f w = weight * Color3f(c->w); switch (c->id) { case AshikhminShirleyID: { const AshikhminShirleyClosureParams* p = reinterpret_cast<const AshikhminShirleyClosureParams*>(c->data()); AshikminBRDFInputValues values; linear_rgb_reflectance_to_spectrum(Color3f(p->Cd), values.m_rd); values.m_rd_alpha.set(1.0f); values.m_rd_multiplier = p->kd; linear_rgb_reflectance_to_spectrum(Color3f(p->Cs), values.m_rg); values.m_rg_alpha.set(1.0f); values.m_rg_multiplier = p->ks; values.m_fr_multiplier = 1.0; values.m_nu = p->nu; values.m_nv = p->nv; add_closure<AshikminBRDFInputValues>( static_cast<ClosureID>(c->id), w, Vector3d(p->N), Vector3d(p->T), values); } break; case BackgroundID: { // ignored for now. } break; case DebugID: { // ignored for now. } break; case EmissionID: { // TODO: implement... } break; case HoldoutID: { // ignored for now. } break; case LambertID: { const LambertClosureParams* p = reinterpret_cast<const LambertClosureParams*>(c->data()); LambertianBRDFInputValues values; values.m_reflectance.set(1.0f); values.m_reflectance_alpha.set(1.0f); values.m_reflectance_multiplier = 1.0; add_closure<LambertianBRDFInputValues>( static_cast<ClosureID>(c->id), w, Vector3d(p->N), values); } break; case MicrofacetBeckmannID: case MicrofacetBlinnID: case MicrofacetGGXID: case MicrofacetWardID: { const MicrofacetBRDFClosureParams* p = reinterpret_cast<const MicrofacetBRDFClosureParams*>(c->data()); MicrofacetBRDFInputValues values; values.m_reflectance.set(1.0f); values.m_reflectance_alpha.set(1.0f); values.m_reflectance_multiplier = 1.0; values.m_glossiness = p->glossiness; values.m_glossiness_multiplier = 1.0; values.m_fr_multiplier = 1.0; add_closure<MicrofacetBRDFInputValues>( static_cast<ClosureID>(c->id), w, Vector3d(p->N), values); } break; case ReflectionID: { const ReflectionClosureParams* p = reinterpret_cast<const ReflectionClosureParams*>(c->data()); SpecularBRDFInputValues values; values.m_reflectance.set(1.0f); values.m_reflectance_alpha.set(1.0f); values.m_reflectance_multiplier = 1.0; add_closure<SpecularBRDFInputValues>( static_cast<ClosureID>(c->id), w, Vector3d(p->N), values); } break; case RefractionID: { const RefractionClosureParams* p = reinterpret_cast<const RefractionClosureParams*>(c->data()); SpecularBTDFInputValues values; values.m_reflectance.set(1.0f); values.m_from_ior = p->from_ior; values.m_to_ior = p->to_ior; values.m_reflectance_alpha = Alpha(1.0); values.m_reflectance_multiplier = 1.0; add_closure<SpecularBTDFInputValues>( static_cast<ClosureID>(c->id), w, Vector3d(p->N), values); } break; case TranslucentID: { const TranslucentClosureParams* p = reinterpret_cast<const TranslucentClosureParams*>(c->data()); DiffuseBTDFInputValues values; values.m_transmittance.set(1.0f); values.m_transmittance_alpha = Alpha(1.0); values.m_transmittance_multiplier = 1.0; add_closure<DiffuseBTDFInputValues>( static_cast<ClosureID>(c->id), w, Vector3d(p->N), values); } break; case TransparentID: // Transparency is handled in another place. break; assert_otherwise; } } break; assert_otherwise; } }
void CompositeClosure::process_closure_tree( const OSL::ClosureColor* closure, const Color3f& weight) { if (closure == 0) return; switch (closure->type) { case OSL::ClosureColor::MUL: { const OSL::ClosureMul* c = reinterpret_cast<const OSL::ClosureMul*>(closure); const Color3f w = weight * Color3f(c->weight); process_closure_tree(c->closure, w); } break; case OSL::ClosureColor::ADD: { const OSL::ClosureAdd* c = reinterpret_cast<const OSL::ClosureAdd*>(closure); process_closure_tree(c->closureA, weight); process_closure_tree(c->closureB, weight); } break; case OSL::ClosureColor::COMPONENT: { const OSL::ClosureComponent* c = reinterpret_cast<const OSL::ClosureComponent*>(closure); const Color3f w = weight * Color3f(c->w); switch (c->id) { case AshikhminShirleyID: { const AshikhminShirleyBRDFClosureParams* p = reinterpret_cast<const AshikhminShirleyBRDFClosureParams*>(c->data()); AshikminBRDFInputValues values; linear_rgb_reflectance_to_spectrum(Color3f(p->Cd), values.m_rd); values.m_rd_multiplier = saturate(p->kd); linear_rgb_reflectance_to_spectrum(Color3f(p->Cs), values.m_rg); values.m_rg_multiplier = saturate(p->ks); values.m_fr_multiplier = 1.0; values.m_nu = max(p->nu, 0.0f); values.m_nv = max(p->nv, 0.0f); add_closure<AshikminBRDFInputValues>( static_cast<ClosureID>(c->id), w, Vector3d(p->N), Vector3d(p->T), values); } break; case DisneyID: { const DisneyBRDFClosureParams* p = reinterpret_cast<const DisneyBRDFClosureParams*>(c->data()); DisneyBRDFInputValues values; linear_rgb_reflectance_to_spectrum(Color3f(p->base_color), values.m_base_color); values.m_subsurface = saturate(p->subsurface); values.m_metallic = saturate(p->metallic); values.m_specular = max(p->specular, 0.0f); values.m_specular_tint = saturate(p->specular_tint); values.m_anisotropic = saturate(p->anisotropic); values.m_roughness = clamp(p->roughness, 0.0001f, 1.0f); values.m_sheen = saturate(p->sheen); values.m_sheen_tint = saturate(p->sheen_tint); values.m_clearcoat = max(p->clearcoat, 0.0f); values.m_clearcoat_gloss = clamp(p->clearcoat_gloss, 0.0001f, 1.0f); values.precompute_tint_color(); add_closure<DisneyBRDFInputValues>( static_cast<ClosureID>(c->id), w, Vector3d(p->N), Vector3d(p->T), values); } break; case LambertID: { const DiffuseBSDFClosureParams* p = reinterpret_cast<const DiffuseBSDFClosureParams*>(c->data()); LambertianBRDFInputValues values; values.m_reflectance.set(1.0f); values.m_reflectance_multiplier = 1.0; add_closure<LambertianBRDFInputValues>( static_cast<ClosureID>(c->id), w, Vector3d(p->N), values); } break; case MicrofacetID: { const MicrofacetClosureParams* p = reinterpret_cast<const MicrofacetClosureParams*>(c->data()); if (!p->refract) { OSLMicrofacetBRDFInputValues values; values.m_ax = max(p->xalpha, 0.0001f); values.m_ay = max(p->yalpha, 0.0001f); if (p->dist == blinn_mdf_name) { add_closure<OSLMicrofacetBRDFInputValues>( MicrofacetBlinnReflectionID, w, Vector3d(p->N), Vector3d(p->T), values); } else if (p->dist == ggx_mdf_name) { add_closure<OSLMicrofacetBRDFInputValues>( MicrofacetGGXReflectionID, w, Vector3d(p->N), Vector3d(p->T), values); } else // Beckmann by default. { add_closure<OSLMicrofacetBRDFInputValues>( MicrofacetBeckmannReflectionID, w, Vector3d(p->N), Vector3d(p->T), values); } } else { // Assume one of the media is air. double from_ior, to_ior; if (p->eta > 1.0) { from_ior = 1.0; to_ior = 1.0 / p->eta; } else { from_ior = p->eta; to_ior = 1.0; } OSLMicrofacetBTDFInputValues values; values.m_ax = max(p->xalpha, 0.0001f); values.m_ay = max(p->yalpha, 0.0001f); values.m_from_ior = from_ior; values.m_to_ior = to_ior; if (p->dist == ggx_mdf_name) { add_closure<OSLMicrofacetBTDFInputValues>( MicrofacetGGXRefractionID, w, Vector3d(p->N), Vector3d(p->T), values); } else // beckmann by default { add_closure<OSLMicrofacetBTDFInputValues>( MicrofacetBeckmannRefractionID, w, Vector3d(p->N), Vector3d(p->T), values); } } } break; case OrenNayarID: { const OrenNayarBRDFClosureParams* p = reinterpret_cast<const OrenNayarBRDFClosureParams*>(c->data()); OrenNayarBRDFInputValues values; values.m_reflectance.set(1.0f); values.m_reflectance_multiplier = 1.0; values.m_roughness = max(p->roughness, 0.0f); add_closure<OrenNayarBRDFInputValues>( static_cast<ClosureID>(c->id), w, Vector3d(p->N), values); } break; case ReflectionID: { const ReflectionBRDFClosureParams* p = reinterpret_cast<const ReflectionBRDFClosureParams*>(c->data()); SpecularBRDFInputValues values; values.m_reflectance.set(1.0f); values.m_reflectance_multiplier = 1.0; add_closure<SpecularBRDFInputValues>( static_cast<ClosureID>(c->id), w, Vector3d(p->N), values); } break; case RefractionID: { const RefractionBTDFClosureParams* p = reinterpret_cast<const RefractionBTDFClosureParams*>(c->data()); // Assume on of the mediums is air. double from_ior, to_ior; if (p->eta > 1.0) { from_ior = 1.0; to_ior = 1.0f / p->eta; } else { from_ior = p->eta; to_ior = 1.0; } SpecularBTDFInputValues values; values.m_reflectance.set(0.0f); values.m_reflectance_multiplier = 0.0; values.m_transmittance.set(1.0f); values.m_transmittance_multiplier = 1.0; values.m_fresnel_multiplier = 0.0; values.m_from_ior = from_ior; values.m_to_ior = to_ior; add_closure<SpecularBTDFInputValues>( static_cast<ClosureID>(c->id), w, Vector3d(p->N), values); } break; case TranslucentID: { const DiffuseBSDFClosureParams* p = reinterpret_cast<const DiffuseBSDFClosureParams*>(c->data()); DiffuseBTDFInputValues values; values.m_transmittance.set(1.0f); values.m_transmittance_multiplier = 1.0; add_closure<DiffuseBTDFInputValues>( static_cast<ClosureID>(c->id), w, Vector3d(p->N), values); } break; // These are handled in another place. case BackgroundID: case DebugID: case EmissionID: case HoldoutID: case TransparentID: break; assert_otherwise; } } break; assert_otherwise; } }
void CompositeSubsurfaceClosure::process_closure_tree( const OSL::ClosureColor* closure, const foundation::Color3f& weight) { if (closure == 0) return; switch (closure->type) { case OSL::ClosureColor::MUL: { const OSL::ClosureMul* c = reinterpret_cast<const OSL::ClosureMul*>(closure); process_closure_tree(c->closure, weight * Color3f(c->weight)); } break; case OSL::ClosureColor::ADD: { const OSL::ClosureAdd* c = reinterpret_cast<const OSL::ClosureAdd*>(closure); process_closure_tree(c->closureA, weight); process_closure_tree(c->closureB, weight); } break; case OSL::ClosureColor::COMPONENT: { const OSL::ClosureComponent* c = reinterpret_cast<const OSL::ClosureComponent*>(closure); const Color3f w = weight * Color3f(c->w); if (c->id == SubsurfaceID) { /* const SubsurfaceClosureParams* p = reinterpret_cast<const SubsurfaceClosureParams*>(c->data()); if (p->profile == directional_profile_name) { DirectionalDipoleBSSRDFInputValues values; values.m_reflectance = Color3f(p->reflectance); values.m_dmfp = Color3f(p->diffuse_mean_free_path); values.m_dmfp_multiplier = 1.0; values.m_anisotropy = 0.0; values.m_outside_ior = 1.0; values.m_inside_ior = 1.0 / p->eta; add_closure<DirectionalDipoleBSSRDFInputValues>( SubsurfaceDirectionalID, w, values); } else assert(false); */ } } break; assert_otherwise; } }
CompositeSubsurfaceClosure::CompositeSubsurfaceClosure( const OSL::ClosureColor* ci) { process_closure_tree(ci, Color3f(1.0f)); compute_cdf(); }