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; CClosurePrimitive *prim = (CClosurePrimitive *)comp->data(); if (prim) { ShaderClosure sc; #ifdef OSL_SUPPORTS_WEIGHTED_CLOSURE_COMPONENTS weight = weight*TO_FLOAT3(comp->w); #endif sc.weight = weight; prim->setup(); switch (prim->category) { case CClosurePrimitive::Volume: { CVolumeClosure *volume = (CVolumeClosure *)prim; /* sample weight */ float sample_weight = fabsf(average(weight)); sc.sample_weight = sample_weight; sc.type = volume->sc.type; sc.data0 = volume->sc.data0; sc.data1 = volume->sc.data1; /* add */ if((sc.sample_weight > CLOSURE_WEIGHT_CUTOFF) && (sd->num_closure < MAX_CLOSURE)) { sd->closure[sd->num_closure++] = sc; sd->flag |= volume->shaderdata_flag(); } break; } case CClosurePrimitive::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 CClosurePrimitive::Holdout: break; /* not implemented */ case CClosurePrimitive::Background: case CClosurePrimitive::BSDF: case CClosurePrimitive::BSSRDF: case CClosurePrimitive::AmbientOcclusion: 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 us a closure tree, we flatten it into arrays per * closure type, for evaluation, sampling, etc later on. */ #if OSL_LIBRARY_VERSION_CODE < 10700 switch(closure->type) { #else switch(closure->id) { #endif case OSL::ClosureColor::MUL: { OSL::ClosureMul *mul = (OSL::ClosureMul *)closure; flatten_volume_closure_tree(sd, mul->closure, TO_FLOAT3(mul->weight) * weight); break; } case 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); break; } default: { OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure; CClosurePrimitive *prim = (CClosurePrimitive *)comp->data(); if(prim) { ShaderClosure sc; #ifdef OSL_SUPPORTS_WEIGHTED_CLOSURE_COMPONENTS weight = weight*TO_FLOAT3(comp->w); #endif sc.weight = weight; prim->setup(); switch(prim->category) { case CClosurePrimitive::Volume: { CVolumeClosure *volume = (CVolumeClosure *)prim; /* sample weight */ float sample_weight = fabsf(average(weight)); sc.sample_weight = sample_weight; sc.type = volume->sc.type; sc.data0 = volume->sc.data0; sc.data1 = volume->sc.data1; /* add */ if((sc.sample_weight > CLOSURE_WEIGHT_CUTOFF) && (sd->num_closure < MAX_CLOSURE)) { sd->closure[sd->num_closure++] = sc; sd->flag |= volume->shaderdata_flag(); } break; } case CClosurePrimitive::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 CClosurePrimitive::Holdout: break; /* not implemented */ case CClosurePrimitive::Background: case CClosurePrimitive::BSDF: case CClosurePrimitive::BSSRDF: case CClosurePrimitive::AmbientOcclusion: break; /* not relevant */ } } } } } void OSLShader::eval_volume(KernelGlobals *kg, ShaderData *sd, PathState *state, int path_flag, ShaderContext ctx) { /* setup shader globals from shader data */ OSLThreadData *tdata = kg->osl_tdata; shaderdata_to_shaderglobals(kg, sd, state, path_flag, tdata); /* execute shader */ OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss; OSL::ShaderGlobals *globals = &tdata->globals; OSL::ShadingContext *octx = tdata->context[(int)ctx]; int shader = sd->shader & SHADER_MASK; if(kg->osl->volume_state[shader]) { #if OSL_LIBRARY_VERSION_CODE < 10600 ss->execute(*octx, *(kg->osl->volume_state[shader]), *globals); #else ss->execute(octx, *(kg->osl->volume_state[shader]), *globals); #endif } /* flatten closure tree */ if(globals->Ci) flatten_volume_closure_tree(sd, globals->Ci); }