static float3 flatten_background_closure_tree(const OSL::ClosureColor *closure) { /* OSL gives us a closure tree, if we are shading for background there * is only one supported closure type at the moment, which has no evaluation * functions, so we just sum the weights */ if (closure->type == OSL::ClosureColor::COMPONENT) { OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure; OSL::ClosurePrimitive *prim = (OSL::ClosurePrimitive *)comp->data(); if (prim && prim->category() == OSL::ClosurePrimitive::Background) return make_float3(1.0f, 1.0f, 1.0f); } else if (closure->type == OSL::ClosureColor::MUL) { OSL::ClosureMul *mul = (OSL::ClosureMul *)closure; return TO_FLOAT3(mul->weight) * flatten_background_closure_tree(mul->closure); } else if (closure->type == OSL::ClosureColor::ADD) { OSL::ClosureAdd *add = (OSL::ClosureAdd *)closure; return flatten_background_closure_tree(add->closureA) + flatten_background_closure_tree(add->closureB); } return make_float3(0.0f, 0.0f, 0.0f); }
static bool generic_closure_compare(int id, const void *dataA, const void *dataB) { assert(dataA && dataB); OSL::ClosurePrimitive *primA = (OSL::ClosurePrimitive *)dataA; OSL::ClosurePrimitive *primB = (OSL::ClosurePrimitive *)dataB; return primA->mergeable(primB); }
static void flatten_volume_closure_tree(ShaderData *sd, const OSL::ClosureColor *closure, float3 weight = make_float3(1.0f, 1.0f, 1.0f)) { /* OSL gives us a closure tree, we flatten it into arrays per * closure type, for evaluation, sampling, etc later on. */ if (closure->type == OSL::ClosureColor::COMPONENT) { OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure; OSL::ClosurePrimitive *prim = (OSL::ClosurePrimitive *)comp->data(); if (prim) { ShaderClosure sc; #ifdef OSL_SUPPORTS_WEIGHTED_CLOSURE_COMPONENTS sc.weight = weight*TO_FLOAT3(comp->w); #else sc.weight = weight; #endif switch (prim->category()) { case OSL::ClosurePrimitive::Volume: { /* sample weight */ float sample_weight = fabsf(average(weight)); sc.sample_weight = sample_weight; sc.type = CLOSURE_VOLUME_ID; sc.data0 = 0.0f; sc.data1 = 0.0f; sc.prim = NULL; /* add */ if(sc.sample_weight > 1e-5f && sd->num_closure < MAX_CLOSURE) sd->closure[sd->num_closure++] = sc; break; } case OSL::ClosurePrimitive::Holdout: case OSL::ClosurePrimitive::Debug: break; /* not implemented */ case OSL::ClosurePrimitive::Background: case OSL::ClosurePrimitive::BSDF: case OSL::ClosurePrimitive::Emissive: case OSL::ClosurePrimitive::BSSRDF: break; /* not relevant */ } } } else if (closure->type == OSL::ClosureColor::MUL) { OSL::ClosureMul *mul = (OSL::ClosureMul *)closure; flatten_volume_closure_tree(sd, mul->closure, TO_FLOAT3(mul->weight) * weight); } else if (closure->type == OSL::ClosureColor::ADD) { OSL::ClosureAdd *add = (OSL::ClosureAdd *)closure; flatten_volume_closure_tree(sd, add->closureA, weight); flatten_volume_closure_tree(sd, add->closureB, weight); } }
static void flatten_volume_closure_tree(ShaderData *sd, const OSL::ClosureColor *closure, float3 weight = make_float3(1.0f, 1.0f, 1.0f)) { /* OSL gives use a closure tree, we flatten it into arrays per * closure type, for evaluation, sampling, etc later on. */ if(closure->type == OSL::ClosureColor::COMPONENT) { OSL::ClosureComponent *comp = (OSL::ClosureComponent*)closure; OSL::ClosurePrimitive *prim = (OSL::ClosurePrimitive*)comp->data(); if(prim) { ShaderClosure sc; sc.prim = prim; sc.weight = weight; switch(prim->category()) { case ClosurePrimitive::Volume: { if(sd->num_closure == MAX_CLOSURE) return; /* sample weight */ float sample_weight = fabsf(average(weight)); float sample_sum = sd->osl_closure.volume_sample_sum + sample_weight; sc.sample_weight = sample_weight; sc.type = CLOSURE_VOLUME_ID; sd->osl_closure.volume_sample_sum = sample_sum; /* add */ sd->closure[sd->num_closure++] = sc; break; } case ClosurePrimitive::Holdout: case ClosurePrimitive::Debug: break; /* not implemented */ case ClosurePrimitive::Background: case ClosurePrimitive::BSDF: case ClosurePrimitive::Emissive: case ClosurePrimitive::BSSRDF: break; /* not relevant */ } } } else if(closure->type == OSL::ClosureColor::MUL) { OSL::ClosureMul *mul = (OSL::ClosureMul*)closure; flatten_volume_closure_tree(sd, mul->closure, TO_FLOAT3(mul->weight) * weight); } else if(closure->type == OSL::ClosureColor::ADD) { OSL::ClosureAdd *add = (OSL::ClosureAdd*)closure; flatten_volume_closure_tree(sd, add->closureA, weight); flatten_volume_closure_tree(sd, add->closureB, weight); } }
static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy, const OSL::ClosureColor *closure, float3 weight = make_float3(1.0f, 1.0f, 1.0f)) { /* OSL gives us a closure tree, we flatten it into arrays per * closure type, for evaluation, sampling, etc later on. */ if (closure->type == OSL::ClosureColor::COMPONENT) { OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure; OSL::ClosurePrimitive *prim = (OSL::ClosurePrimitive *)comp->data(); if (prim) { ShaderClosure sc; sc.weight = weight; switch (prim->category()) { case OSL::ClosurePrimitive::BSDF: { CBSDFClosure *bsdf = (CBSDFClosure *)prim; int scattering = bsdf->scattering(); /* no caustics option */ if (no_glossy && scattering == LABEL_GLOSSY) return; /* sample weight */ float sample_weight = fabsf(average(weight)); sc.sample_weight = sample_weight; sc.type = bsdf->sc.type; sc.N = bsdf->sc.N; sc.T = bsdf->sc.T; sc.data0 = bsdf->sc.data0; sc.data1 = bsdf->sc.data1; sc.prim = bsdf->sc.prim; /* add */ if(sc.sample_weight > 1e-5f && sd->num_closure < MAX_CLOSURE) { sd->closure[sd->num_closure++] = sc; sd->flag |= bsdf->shaderdata_flag(); } break; } case OSL::ClosurePrimitive::Emissive: { /* sample weight */ float sample_weight = fabsf(average(weight)); sc.sample_weight = sample_weight; sc.type = CLOSURE_EMISSION_ID; sc.prim = NULL; /* flag */ if(sd->num_closure < MAX_CLOSURE) { sd->closure[sd->num_closure++] = sc; sd->flag |= SD_EMISSION; } break; } case AmbientOcclusion: { /* sample weight */ float sample_weight = fabsf(average(weight)); sc.sample_weight = sample_weight; sc.type = CLOSURE_AMBIENT_OCCLUSION_ID; sc.prim = NULL; if(sd->num_closure < MAX_CLOSURE) { sd->closure[sd->num_closure++] = sc; sd->flag |= SD_AO; } break; } case OSL::ClosurePrimitive::Holdout: { sc.sample_weight = 0.0f; sc.type = CLOSURE_HOLDOUT_ID; sc.prim = NULL; if(sd->num_closure < MAX_CLOSURE) { sd->closure[sd->num_closure++] = sc; sd->flag |= SD_HOLDOUT; } break; } case OSL::ClosurePrimitive::BSSRDF: { CBSSRDFClosure *bssrdf = (CBSSRDFClosure *)prim; float sample_weight = fabsf(average(weight)); if(sample_weight > 1e-5f && sd->num_closure+2 < MAX_CLOSURE) { sc.sample_weight = sample_weight; sc.type = bssrdf->sc.type; sc.N = bssrdf->sc.N; sc.data1 = bssrdf->sc.data1; sc.prim = NULL; /* create one closure for each color channel */ if(fabsf(weight.x) > 0.0f) { sc.weight = make_float3(weight.x, 0.0f, 0.0f); sc.data0 = bssrdf->radius.x; sd->closure[sd->num_closure++] = sc; sd->flag |= bssrdf->shaderdata_flag(); } if(fabsf(weight.y) > 0.0f) { sc.weight = make_float3(0.0f, weight.y, 0.0f); sc.data0 = bssrdf->radius.y; sd->closure[sd->num_closure++] = sc; sd->flag |= bssrdf->shaderdata_flag(); } if(fabsf(weight.z) > 0.0f) { sc.weight = make_float3(0.0f, 0.0f, weight.z); sc.data0 = bssrdf->radius.z; sd->closure[sd->num_closure++] = sc; sd->flag |= bssrdf->shaderdata_flag(); } } break; } case OSL::ClosurePrimitive::Debug: break; /* not implemented */ case OSL::ClosurePrimitive::Background: case OSL::ClosurePrimitive::Volume: break; /* not relevant */ } } } else if (closure->type == OSL::ClosureColor::MUL) { OSL::ClosureMul *mul = (OSL::ClosureMul *)closure; flatten_surface_closure_tree(sd, no_glossy, mul->closure, TO_FLOAT3(mul->weight) * weight); } else if (closure->type == OSL::ClosureColor::ADD) { OSL::ClosureAdd *add = (OSL::ClosureAdd *)closure; flatten_surface_closure_tree(sd, no_glossy, add->closureA, weight); flatten_surface_closure_tree(sd, no_glossy, add->closureB, weight); } }
static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy, const OSL::ClosureColor *closure, float3 weight = make_float3(1.0f, 1.0f, 1.0f)) { /* OSL gives use a closure tree, we flatten it into arrays per * closure type, for evaluation, sampling, etc later on. */ if(closure->type == OSL::ClosureColor::COMPONENT) { OSL::ClosureComponent *comp = (OSL::ClosureComponent*)closure; OSL::ClosurePrimitive *prim = (OSL::ClosurePrimitive*)comp->data(); if(prim) { ShaderClosure sc; sc.prim = prim; sc.weight = weight; switch(prim->category()) { case ClosurePrimitive::BSDF: { if(sd->num_closure == MAX_CLOSURE) return; OSL::BSDFClosure *bsdf = (OSL::BSDFClosure*)prim; ustring scattering = bsdf->scattering(); /* no caustics option */ if(no_glossy && scattering == OSL::Labels::GLOSSY) return; /* sample weight */ float albedo = bsdf->albedo(TO_VEC3(sd->I)); float sample_weight = fabsf(average(weight))*albedo; float sample_sum = sd->osl_closure.bsdf_sample_sum + sample_weight; sc.sample_weight = sample_weight; sc.type = CLOSURE_BSDF_ID; sd->osl_closure.bsdf_sample_sum = sample_sum; /* scattering flags */ if(scattering == OSL::Labels::DIFFUSE) sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL; else if(scattering == OSL::Labels::GLOSSY) sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY; else sd->flag |= SD_BSDF; /* add */ sd->closure[sd->num_closure++] = sc; break; } case ClosurePrimitive::Emissive: { if(sd->num_closure == MAX_CLOSURE) return; /* sample weight */ float sample_weight = fabsf(average(weight)); float sample_sum = sd->osl_closure.emissive_sample_sum + sample_weight; sc.sample_weight = sample_weight; sc.type = CLOSURE_EMISSION_ID; sd->osl_closure.emissive_sample_sum = sample_sum; /* flag */ sd->flag |= SD_EMISSION; sd->closure[sd->num_closure++] = sc; break; } case ClosurePrimitive::Holdout: if(sd->num_closure == MAX_CLOSURE) return; sc.sample_weight = 0.0f; sc.type = CLOSURE_HOLDOUT_ID; sd->flag |= SD_HOLDOUT; sd->closure[sd->num_closure++] = sc; break; case ClosurePrimitive::BSSRDF: case ClosurePrimitive::Debug: break; /* not implemented */ case ClosurePrimitive::Background: case ClosurePrimitive::Volume: break; /* not relevant */ } } } else if(closure->type == OSL::ClosureColor::MUL) { OSL::ClosureMul *mul = (OSL::ClosureMul*)closure; flatten_surface_closure_tree(sd, no_glossy, mul->closure, TO_FLOAT3(mul->weight) * weight); } else if(closure->type == OSL::ClosureColor::ADD) { OSL::ClosureAdd *add = (OSL::ClosureAdd*)closure; flatten_surface_closure_tree(sd, no_glossy, add->closureA, weight); flatten_surface_closure_tree(sd, no_glossy, add->closureB, weight); } }
static void flatten_surface_closure_tree(ShaderData *sd, int path_flag, const OSL::ClosureColor *closure, float3 weight = make_float3(1.0f, 1.0f, 1.0f)) { /* OSL gives us a closure tree, we flatten it into arrays per * closure type, for evaluation, sampling, etc later on. */ if (closure->type == OSL::ClosureColor::COMPONENT) { OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure; OSL::ClosurePrimitive *prim = (OSL::ClosurePrimitive *)comp->data(); if (prim) { ShaderClosure sc; #ifdef OSL_SUPPORTS_WEIGHTED_CLOSURE_COMPONENTS sc.weight = weight*TO_FLOAT3(comp->w); #else sc.weight = weight; #endif switch (prim->category()) { case OSL::ClosurePrimitive::BSDF: { CBSDFClosure *bsdf = (CBSDFClosure *)prim; int scattering = bsdf->scattering(); /* no caustics option */ if(scattering == LABEL_GLOSSY && (path_flag & PATH_RAY_DIFFUSE)) { KernelGlobals *kg = sd->osl_globals; if(kernel_data.integrator.no_caustics) return; } /* sample weight */ float sample_weight = fabsf(average(weight)); sc.sample_weight = sample_weight; sc.type = bsdf->sc.type; sc.N = bsdf->sc.N; sc.T = bsdf->sc.T; sc.data0 = bsdf->sc.data0; sc.data1 = bsdf->sc.data1; sc.prim = bsdf->sc.prim; /* add */ if(sc.sample_weight > 1e-5f && sd->num_closure < MAX_CLOSURE) { sd->closure[sd->num_closure++] = sc; sd->flag |= bsdf->shaderdata_flag(); } break; } case OSL::ClosurePrimitive::Emissive: { /* sample weight */ float sample_weight = fabsf(average(weight)); sc.sample_weight = sample_weight; sc.type = CLOSURE_EMISSION_ID; sc.data0 = 0.0f; sc.data1 = 0.0f; sc.prim = NULL; /* flag */ if(sd->num_closure < MAX_CLOSURE) { sd->closure[sd->num_closure++] = sc; sd->flag |= SD_EMISSION; } break; } case AmbientOcclusion: { /* sample weight */ float sample_weight = fabsf(average(weight)); sc.sample_weight = sample_weight; sc.type = CLOSURE_AMBIENT_OCCLUSION_ID; sc.data0 = 0.0f; sc.data1 = 0.0f; sc.prim = NULL; if(sd->num_closure < MAX_CLOSURE) { sd->closure[sd->num_closure++] = sc; sd->flag |= SD_AO; } break; } case OSL::ClosurePrimitive::Holdout: { sc.sample_weight = 0.0f; sc.type = CLOSURE_HOLDOUT_ID; sc.data0 = 0.0f; sc.data1 = 0.0f; sc.prim = NULL; if(sd->num_closure < MAX_CLOSURE) { sd->closure[sd->num_closure++] = sc; sd->flag |= SD_HOLDOUT; } break; } case OSL::ClosurePrimitive::BSSRDF: { CBSSRDFClosure *bssrdf = (CBSSRDFClosure *)prim; float sample_weight = fabsf(average(weight)); if(sample_weight > 1e-5f && sd->num_closure+2 < MAX_CLOSURE) { sc.sample_weight = sample_weight; sc.type = bssrdf->sc.type; sc.N = bssrdf->sc.N; sc.data1 = bssrdf->sc.data1; sc.T.x = bssrdf->sc.T.x; sc.prim = NULL; /* disable in case of diffuse ancestor, can't see it well then and * adds considerably noise due to probabilities of continuing path * getting lower and lower */ if(sc.type != CLOSURE_BSSRDF_COMPATIBLE_ID && (path_flag & PATH_RAY_DIFFUSE_ANCESTOR)) bssrdf->radius = make_float3(0.0f, 0.0f, 0.0f); /* create one closure for each color channel */ if(fabsf(weight.x) > 0.0f) { sc.weight = make_float3(weight.x, 0.0f, 0.0f); sc.data0 = bssrdf->radius.x; sd->flag |= bssrdf_setup(&sc, sc.type); sd->closure[sd->num_closure++] = sc; } if(fabsf(weight.y) > 0.0f) { sc.weight = make_float3(0.0f, weight.y, 0.0f); sc.data0 = bssrdf->radius.y; sd->flag |= bssrdf_setup(&sc, sc.type); sd->closure[sd->num_closure++] = sc; } if(fabsf(weight.z) > 0.0f) { sc.weight = make_float3(0.0f, 0.0f, weight.z); sc.data0 = bssrdf->radius.z; sd->flag |= bssrdf_setup(&sc, sc.type); sd->closure[sd->num_closure++] = sc; } } break; } case OSL::ClosurePrimitive::Debug: break; /* not implemented */ case OSL::ClosurePrimitive::Background: case OSL::ClosurePrimitive::Volume: break; /* not relevant */ } } } else if (closure->type == OSL::ClosureColor::MUL) { OSL::ClosureMul *mul = (OSL::ClosureMul *)closure; flatten_surface_closure_tree(sd, path_flag, mul->closure, TO_FLOAT3(mul->weight) * weight); } else if (closure->type == OSL::ClosureColor::ADD) { OSL::ClosureAdd *add = (OSL::ClosureAdd *)closure; flatten_surface_closure_tree(sd, path_flag, add->closureA, weight); flatten_surface_closure_tree(sd, path_flag, add->closureB, weight); } }
static void generic_closure_setup(OSL::RendererServices *, int id, void *data) { assert(data); OSL::ClosurePrimitive *prim = (OSL::ClosurePrimitive *)data; prim->setup(); }