CCL_NAMESPACE_BEGIN /* Threads */ void OSLShader::thread_init(KernelGlobals *kg, KernelGlobals *kernel_globals, OSLGlobals *osl_globals) { /* no osl used? */ if(!osl_globals->use) { kg->osl = NULL; return; } /* per thread kernel data init*/ kg->osl = osl_globals; kg->osl->services->thread_init(kernel_globals, osl_globals->ts); OSL::ShadingSystem *ss = kg->osl->ss; OSLThreadData *tdata = new OSLThreadData(); memset(&tdata->globals, 0, sizeof(OSL::ShaderGlobals)); tdata->globals.tracedata = &tdata->tracedata; tdata->globals.flipHandedness = false; tdata->osl_thread_info = ss->create_thread_info(); for(int i = 0; i < SHADER_CONTEXT_NUM; i++) tdata->context[i] = ss->get_context(tdata->osl_thread_info); tdata->oiio_thread_info = osl_globals->ts->get_perthread_info(); kg->osl_ss = (OSLShadingSystem*)ss; kg->osl_tdata = tdata; }
void OSLShader::eval_displacement(KernelGlobals *kg, ShaderData *sd, ShaderContext ctx) { /* setup shader globals from shader data */ OSLThreadData *tdata = kg->osl_tdata; PathState state = {0}; shaderdata_to_shaderglobals(kg, sd, &state, 0, 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->displacement_state[shader]) { #if OSL_LIBRARY_VERSION_CODE < 10600 ss->execute(*octx, *(kg->osl->displacement_state[shader]), *globals); #else ss->execute(octx, *(kg->osl->displacement_state[shader]), *globals); #endif } /* get back position */ sd->P = TO_FLOAT3(globals->P); }
void ShaderGroup::get_shadergroup_globals_info(OSL::ShadingSystem& shading_system) { // Assume the shader group uses all globals. m_flags |= UsesAllGlobals; int num_globals = 0; if (!shading_system.getattribute( impl->m_shader_group_ref.get(), "num_globals_needed", num_globals)) { RENDERER_LOG_WARNING( "getattribute: num_globals_needed call failed for shader group \"%s\"; " "assuming shader group uses all globals.", get_path().c_str()); return; } if (num_globals != 0) { OIIO::ustring* globals = 0; if (!shading_system.getattribute( impl->m_shader_group_ref.get(), "globals_needed", OIIO::TypeDesc::PTR, &globals)) { RENDERER_LOG_WARNING( "getattribute: globals_needed call failed for shader group \"%s\"; " "assuming shader group uses all globals.", get_path().c_str()); return; } // Clear all globals flags. m_flags &= ~UsesAllGlobals; // Set the globals flags. for (int i = 0; i < num_globals; ++i) { if (globals[i] == g_dPdtime_str) m_flags |= UsesdPdTime; } } else { // The shader group uses no globals. m_flags &= ~UsesAllGlobals; } }
void OSLShader::thread_free(KernelGlobals *kg) { if(!kg->osl) return; OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss; OSLThreadData *tdata = kg->osl_tdata; ss->release_context(tdata->context); ss->destroy_thread_info(tdata->osl_thread_info); delete tdata; kg->osl = NULL; kg->osl_ss = NULL; kg->osl_tdata = NULL; }
void OSLShader::eval_volume(KernelGlobals *kg, ShaderData *sd, float randb, int path_flag, ShaderContext ctx) { /* setup shader globals from shader data */ OSLThreadData *tdata = kg->osl_tdata; shaderdata_to_shaderglobals(kg, sd, 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]) ss->execute(*octx, *(kg->osl->volume_state[shader]), *globals); if (globals->Ci) flatten_volume_closure_tree(sd, globals->Ci); }
void OSLShader::thread_free(KernelGlobals *kg) { if(!kg->osl) return; OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss; OSLThreadData *tdata = kg->osl_tdata; for(int i = 0; i < SHADER_CONTEXT_NUM; i++) ss->release_context(tdata->context[i]); ss->destroy_thread_info(tdata->osl_thread_info); delete tdata; kg->osl = NULL; kg->osl_ss = NULL; kg->osl_tdata = NULL; }
void OSLShader::eval_background(KernelGlobals *kg, ShaderData *sd, PathState *state, int path_flag) { /* setup shader globals from shader data */ OSLThreadData *tdata = kg->osl_tdata; shaderdata_to_shaderglobals(kg, sd, state, path_flag, tdata); /* execute shader for this point */ OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss; OSL::ShaderGlobals *globals = &tdata->globals; OSL::ShadingContext *octx = tdata->context; if(kg->osl->background_state) { ss->execute(octx, *(kg->osl->background_state), *globals); } /* return background color immediately */ if(globals->Ci) flatten_background_closure_tree(sd, globals->Ci); }
void ShaderGroup::get_shadergroup_globals_info(OSL::ShadingSystem& shading_system) { m_uses_dPdtime = true; int num_globals = 0; if (!shading_system.getattribute( impl->m_shader_group_ref.get(), "num_globals_needed", num_globals)) { RENDERER_LOG_WARNING( "getattribute: num_globals_needed call failed for shader group %s; " "assuming shader group uses all globals.", get_name()); return; } if (num_globals != 0) { OIIO::ustring* globals = 0; if (!shading_system.getattribute( impl->m_shader_group_ref.get(), "globals_needed", OIIO::TypeDesc::PTR, &globals)) { RENDERER_LOG_WARNING( "getattribute: globals_needed call failed for shader group %s; " "assuming shader group uses all globals.", get_name()); return; } m_uses_dPdtime = false; for (int i = 0; i < num_globals; ++i) { if (globals[i] == g_dPdtime_str) m_uses_dPdtime = true; } } }
float3 OSLShader::eval_background(KernelGlobals *kg, ShaderData *sd, int path_flag, ShaderContext ctx) { /* setup shader globals from shader data */ OSLThreadData *tdata = kg->osl_tdata; shaderdata_to_shaderglobals(kg, sd, path_flag, tdata); /* execute shader for this point */ OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss; OSL::ShaderGlobals *globals = &tdata->globals; OSL::ShadingContext *octx = tdata->context[(int)ctx]; if (kg->osl->background_state) ss->execute(*octx, *(kg->osl->background_state), *globals); /* return background color immediately */ if (globals->Ci) return flatten_background_closure_tree(globals->Ci); return make_float3(0.0f, 0.0f, 0.0f); }
void OSLShader::eval_displacement(KernelGlobals *kg, ShaderData *sd, PathState *state) { /* setup shader globals from shader data */ OSLThreadData *tdata = kg->osl_tdata; shaderdata_to_shaderglobals(kg, sd, state, 0, tdata); /* execute shader */ OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss; OSL::ShaderGlobals *globals = &tdata->globals; OSL::ShadingContext *octx = tdata->context; int shader = sd->shader & SHADER_MASK; if(kg->osl->displacement_state[shader]) { ss->execute(octx, *(kg->osl->displacement_state[shader]), *globals); } /* get back position */ sd->P = TO_FLOAT3(globals->P); }
ShadingContext::ShadingContext( const Intersector& intersector, Tracer& tracer, TextureCache& texture_cache, #ifdef WITH_OSL OSL::ShadingSystem& shading_system, #endif ILightingEngine* lighting_engine, const float transparency_threshold, const size_t max_iterations) : m_intersector(intersector) , m_tracer(tracer) , m_texture_cache(texture_cache) , m_lighting_engine(lighting_engine) , m_transparency_threshold(transparency_threshold) , m_max_iterations(max_iterations) #ifdef WITH_OSL , m_osl_shading_system(shading_system) , m_osl_thread_info(shading_system.create_thread_info()) , m_osl_shading_context(shading_system.get_context(m_osl_thread_info)) #endif { }
void OSLShader::eval_surface(KernelGlobals *kg, ShaderData *sd, float randb, int path_flag, ShaderContext ctx) { /* setup shader globals from shader data */ OSLThreadData *tdata = kg->osl_tdata; shaderdata_to_shaderglobals(kg, sd, path_flag, tdata); /* execute shader for this point */ 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->surface_state[shader]) ss->execute(*octx, *(kg->osl->surface_state[shader]), *globals); /* flatten closure tree */ sd->num_closure = 0; sd->randb_closure = randb; if (globals->Ci) { bool no_glossy = (path_flag & PATH_RAY_DIFFUSE) && kernel_data.integrator.no_caustics; flatten_surface_closure_tree(sd, no_glossy, globals->Ci); } }
bool ShaderConnection::add(OSL::ShadingSystem& shading_system) { if (!shading_system.ConnectShaders( get_src_layer(), get_src_param(), get_dst_layer(), get_dst_param())) { RENDERER_LOG_ERROR( "error connecting shaders %s::%s -> %s::%s.", get_src_layer(), get_src_param(), get_dst_layer(), get_dst_param()); return false; } return true; }
bool Shader::add(OSL::ShadingSystem& shading_system) { for (each<ShaderParamContainer> i = impl->m_params; i; ++i) { if (!i->add(shading_system)) return false; } // For some reason, OSL only supports the surface shader usage. // So, we ignore the user shader type specified in the XML file, // and hardcode "surface" here. TODO: research this... //if (!shading_system.Shader(get_type(), get_shader(), get_layer())) if (!shading_system.Shader("surface", get_shader(), get_layer())) { RENDERER_LOG_ERROR("error adding shader %s, %s.", get_shader(), get_layer()); return false; } return true; }
OSLShaderGroupExec::OSLShaderGroupExec(OSL::ShadingSystem& shading_system) : m_osl_shading_system(shading_system) , m_osl_thread_info(shading_system.create_thread_info()) , m_osl_shading_context(shading_system.get_context(m_osl_thread_info)) { }
void ShaderGroup::get_shadergroup_closures_info(OSL::ShadingSystem& shading_system) { // Assume the shader group has all closure types. m_flags |= HasAllClosures; int num_unknown_closures = 0; if (!shading_system.getattribute( impl->m_shader_group_ref.get(), "unknown_closures_needed", num_unknown_closures)) { RENDERER_LOG_WARNING( "getattribute: unknown_closures_needed call failed for shader group \"%s\"; " "assuming shader group has all kinds of closures.", get_path().c_str()); return; } if (num_unknown_closures != 0) { RENDERER_LOG_WARNING( "shader group \"%s\" has unknown closures; " "assuming shader group has all kinds of closures.", get_path().c_str()); return; } int num_closures = 0; if (!shading_system.getattribute( impl->m_shader_group_ref.get(), "num_closures_needed", num_closures)) { RENDERER_LOG_WARNING( "getattribute: num_closures_needed call failed for shader group \"%s\"; " "assuming shader group has all kinds of closures.", get_path().c_str()); } if (num_closures != 0) { OIIO::ustring* closures = 0; if (!shading_system.getattribute( impl->m_shader_group_ref.get(), "closures_needed", OIIO::TypeDesc::PTR, &closures)) { RENDERER_LOG_WARNING( "getattribute: closures_needed call failed for shader group \"%s\"; " "assuming shader group has all kinds of closures.", get_path().c_str()); return; } // Clear all closure flags. m_flags &= ~HasAllClosures; // Set the closure flags. for (int i = 0; i < num_closures; ++i) { if (closures[i] == g_emission_str) m_flags |= HasEmission; else if (closures[i] == g_transparent_str) m_flags |= HasTransparency; else if (closures[i] == g_subsurface_str) m_flags |= HasSubsurface; else if (closures[i] == g_holdout_str) m_flags |= HasHoldout; else if (closures[i] == g_debug_str) m_flags |= HasDebug; else m_flags |= HasBSDFs; } } else { // Shader group uses no closures. m_flags &= ~HasAllClosures; } }
// We probably want to reuse OSL macros to declare closure params // and register the closures. We can use them only inside the OSL namespace. OSL_NAMESPACE_ENTER void register_appleseed_closures(OSL::ShadingSystem& shading_system) { // Describe the memory layout of each closure type to the OSL runtime. const size_t MaxParams = 32; struct BuiltinClosures { const char* name; int id; ClosureParam params[MaxParams]; }; static const BuiltinClosures builtins[] = { { "as_ashikhmin_shirley", AshikhminShirleyID, { CLOSURE_VECTOR_PARAM(AshikhminShirleyClosureParams, N), CLOSURE_VECTOR_PARAM(AshikhminShirleyClosureParams, T), CLOSURE_FLOAT_PARAM(AshikhminShirleyClosureParams, kd), CLOSURE_COLOR_PARAM(AshikhminShirleyClosureParams, Cd), CLOSURE_FLOAT_PARAM(AshikhminShirleyClosureParams, ks), CLOSURE_COLOR_PARAM(AshikhminShirleyClosureParams, Cs), CLOSURE_FLOAT_PARAM(AshikhminShirleyClosureParams, nu), CLOSURE_FLOAT_PARAM(AshikhminShirleyClosureParams, nv), CLOSURE_FINISH_PARAM(AshikhminShirleyClosureParams) } }, { "as_microfacet_blinn", MicrofacetBlinnID, { CLOSURE_VECTOR_PARAM(MicrofacetBRDFClosureParams, N), CLOSURE_FLOAT_PARAM(MicrofacetBRDFClosureParams, glossiness), CLOSURE_FINISH_PARAM(MicrofacetBRDFClosureParams) } }, { "as_microfacet_ward", MicrofacetWardID, { CLOSURE_VECTOR_PARAM(MicrofacetBRDFClosureParams, N), CLOSURE_FLOAT_PARAM(MicrofacetBRDFClosureParams, glossiness), CLOSURE_FINISH_PARAM(MicrofacetBRDFClosureParams) } }, { "background", BackgroundID, { CLOSURE_FINISH_PARAM(EmptyClosureParams) } }, { "debug", DebugID, { CLOSURE_STRING_PARAM(DebugClosureParams, tag), CLOSURE_FINISH_PARAM(DebugClosureParams) } }, { "diffuse", LambertID, { CLOSURE_VECTOR_PARAM(LambertClosureParams, N), CLOSURE_FINISH_PARAM(LambertClosureParams) } }, { "emission", EmissionID, { CLOSURE_FLOAT_PARAM(EmissionClosureParams, inner_angle), CLOSURE_FLOAT_PARAM(EmissionClosureParams, outer_angle), CLOSURE_FINISH_PARAM(EmissionClosureParams) } }, { "holdout", HoldoutID, { CLOSURE_FINISH_PARAM(EmptyClosureParams) } }, { "microfacet_beckmann", MicrofacetBeckmannID, { CLOSURE_VECTOR_PARAM(MicrofacetBRDFClosureParams, N), CLOSURE_FLOAT_PARAM(MicrofacetBRDFClosureParams, glossiness), CLOSURE_FINISH_PARAM(MicrofacetBRDFClosureParams) } }, { "microfacet_ggx", MicrofacetGGXID, { CLOSURE_VECTOR_PARAM(MicrofacetBRDFClosureParams, N), CLOSURE_FLOAT_PARAM(MicrofacetBRDFClosureParams, glossiness), CLOSURE_FINISH_PARAM(MicrofacetBRDFClosureParams) } }, { "reflection", ReflectionID, { CLOSURE_VECTOR_PARAM(ReflectionClosureParams, N), CLOSURE_FINISH_PARAM(ReflectionClosureParams) } }, { "refraction", RefractionID, { CLOSURE_VECTOR_PARAM(RefractionClosureParams, N), CLOSURE_FLOAT_PARAM(RefractionClosureParams, from_ior), CLOSURE_FLOAT_PARAM(RefractionClosureParams, to_ior), CLOSURE_FINISH_PARAM(RefractionClosureParams) } }, { "translucent", TranslucentID, { CLOSURE_VECTOR_PARAM(LambertClosureParams, N), CLOSURE_FINISH_PARAM(LambertClosureParams) } }, { "transparency", TransparentID, { CLOSURE_FINISH_PARAM(EmptyClosureParams) } }, { 0, 0, {} } // mark end of the array }; for (size_t i = 0; builtins[i].name != 0; ++i) { shading_system.register_closure( builtins[i].name, builtins[i].id, builtins[i].params, 0, 0); RENDERER_LOG_INFO("registered OSL closure %s.", builtins[i].name); } }
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 OSL_LIBRARY_VERSION_CODE < 10700 switch(closure->type) { #else switch(closure->id) { #endif case OSL::ClosureColor::MUL: { OSL::ClosureMul *mul = (OSL::ClosureMul *)closure; return TO_FLOAT3(mul->weight) * flatten_background_closure_tree(mul->closure); } case OSL::ClosureColor::ADD: { OSL::ClosureAdd *add = (OSL::ClosureAdd *)closure; return flatten_background_closure_tree(add->closureA) + flatten_background_closure_tree(add->closureB); } default: { OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure; CClosurePrimitive *prim = (CClosurePrimitive *)comp->data(); if(prim && prim->category == CClosurePrimitive::Background) #ifdef OSL_SUPPORTS_WEIGHTED_CLOSURE_COMPONENTS return TO_FLOAT3(comp->w); #else return make_float3(1.0f, 1.0f, 1.0f); #endif } } return make_float3(0.0f, 0.0f, 0.0f); } float3 OSLShader::eval_background(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 for this point */ OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss; OSL::ShaderGlobals *globals = &tdata->globals; OSL::ShadingContext *octx = tdata->context[(int)ctx]; if(kg->osl->background_state) { #if OSL_LIBRARY_VERSION_CODE < 10600 ss->execute(*octx, *(kg->osl->background_state), *globals); #else ss->execute(octx, *(kg->osl->background_state), *globals); #endif } /* return background color immediately */ if(globals->Ci) return flatten_background_closure_tree(globals->Ci); return make_float3(0.0f, 0.0f, 0.0f); }
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 OSL_LIBRARY_VERSION_CODE < 10700 switch(closure->type) { #else switch(closure->id) { #endif case OSL::ClosureColor::MUL: { OSL::ClosureMul *mul = (OSL::ClosureMul *)closure; flatten_surface_closure_tree(sd, path_flag, mul->closure, TO_FLOAT3(mul->weight) * weight); break; } case 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); 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::BSDF: { CBSDFClosure *bsdf = (CBSDFClosure *)prim; int scattering = bsdf->scattering(); /* caustic options */ if((scattering & LABEL_GLOSSY) && (path_flag & PATH_RAY_DIFFUSE)) { KernelGlobals *kg = sd->osl_globals; if((!kernel_data.integrator.caustics_reflective && (scattering & LABEL_REFLECT)) || (!kernel_data.integrator.caustics_refractive && (scattering & LABEL_TRANSMIT))) { 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.data2 = bsdf->sc.data2; sc.prim = bsdf->sc.prim; /* add */ if(sc.sample_weight > CLOSURE_WEIGHT_CUTOFF && sd->num_closure < MAX_CLOSURE) { sd->closure[sd->num_closure++] = sc; sd->flag |= bsdf->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.data2 = 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::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.data2 = 0.0f; sc.prim = NULL; if(sd->num_closure < MAX_CLOSURE) { sd->closure[sd->num_closure++] = sc; sd->flag |= SD_AO; } break; } case CClosurePrimitive::Holdout: { sc.sample_weight = 0.0f; sc.type = CLOSURE_HOLDOUT_ID; sc.data0 = 0.0f; sc.data1 = 0.0f; sc.data2 = 0.0f; sc.prim = NULL; if(sd->num_closure < MAX_CLOSURE) { sd->closure[sd->num_closure++] = sc; sd->flag |= SD_HOLDOUT; } break; } case CClosurePrimitive::BSSRDF: { CBSSRDFClosure *bssrdf = (CBSSRDFClosure *)prim; float sample_weight = fabsf(average(weight)); if(sample_weight > CLOSURE_WEIGHT_CUTOFF && 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(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; sc.data1 = 0.0f; 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; sc.data1 = 0.0f; 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; sc.data1 = 0.0f; sd->flag |= bssrdf_setup(&sc, sc.type); sd->closure[sd->num_closure++] = sc; } } break; } case CClosurePrimitive::Background: case CClosurePrimitive::Volume: break; /* not relevant */ } } break; } } } void OSLShader::eval_surface(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 for this point */ 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->surface_state[shader]) { #if OSL_LIBRARY_VERSION_CODE < 10600 ss->execute(*octx, *(kg->osl->surface_state[shader]), *globals); #else ss->execute(octx, *(kg->osl->surface_state[shader]), *globals); #endif } /* flatten closure tree */ if(globals->Ci) flatten_surface_closure_tree(sd, path_flag, globals->Ci); }
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); }
// We probably want to reuse OSL macros to declare closure params // and register the closures. We can use them only inside the OSL namespace. OSL_NAMESPACE_ENTER void register_appleseed_closures(OSL::ShadingSystem& shading_system) { // Describe the memory layout of each closure type to the OSL runtime. const size_t MaxParams = 32; struct BuiltinClosures { const char* name; int id; ClosureParam params[MaxParams]; }; static const BuiltinClosures builtins[] = { { "as_ashikhmin_shirley", AshikhminShirleyID, { CLOSURE_VECTOR_PARAM(AshikhminShirleyBRDFClosureParams, N), CLOSURE_VECTOR_PARAM(AshikhminShirleyBRDFClosureParams, T), CLOSURE_FLOAT_PARAM(AshikhminShirleyBRDFClosureParams, kd), CLOSURE_COLOR_PARAM(AshikhminShirleyBRDFClosureParams, Cd), CLOSURE_FLOAT_PARAM(AshikhminShirleyBRDFClosureParams, ks), CLOSURE_COLOR_PARAM(AshikhminShirleyBRDFClosureParams, Cs), CLOSURE_FLOAT_PARAM(AshikhminShirleyBRDFClosureParams, nu), CLOSURE_FLOAT_PARAM(AshikhminShirleyBRDFClosureParams, nv), CLOSURE_FINISH_PARAM(AshikhminShirleyBRDFClosureParams) } }, { "as_disney", DisneyID, { CLOSURE_VECTOR_PARAM(DisneyBRDFClosureParams, N), CLOSURE_VECTOR_PARAM(DisneyBRDFClosureParams, T), CLOSURE_COLOR_PARAM(DisneyBRDFClosureParams, base_color), CLOSURE_FLOAT_PARAM(DisneyBRDFClosureParams, subsurface), CLOSURE_FLOAT_PARAM(DisneyBRDFClosureParams, metallic), CLOSURE_FLOAT_PARAM(DisneyBRDFClosureParams, specular), CLOSURE_FLOAT_PARAM(DisneyBRDFClosureParams, specular_tint), CLOSURE_FLOAT_PARAM(DisneyBRDFClosureParams, anisotropic), CLOSURE_FLOAT_PARAM(DisneyBRDFClosureParams, roughness), CLOSURE_FLOAT_PARAM(DisneyBRDFClosureParams, sheen), CLOSURE_FLOAT_PARAM(DisneyBRDFClosureParams, sheen_tint), CLOSURE_FLOAT_PARAM(DisneyBRDFClosureParams, clearcoat), CLOSURE_FLOAT_PARAM(DisneyBRDFClosureParams, clearcoat_gloss), CLOSURE_FINISH_PARAM(DisneyBRDFClosureParams) } }, { "as_oren_nayar", OrenNayarID, { CLOSURE_VECTOR_PARAM(OrenNayarBRDFClosureParams, N), CLOSURE_FLOAT_PARAM(OrenNayarBRDFClosureParams, roughness), CLOSURE_FINISH_PARAM(OrenNayarBRDFClosureParams) } }, { "background", BackgroundID, { CLOSURE_FINISH_PARAM(EmptyClosureParams) } }, { "debug", DebugID, { CLOSURE_STRING_PARAM(DebugClosureParams, tag), CLOSURE_FINISH_PARAM(DebugClosureParams) } }, { "diffuse", LambertID, { CLOSURE_VECTOR_PARAM(DiffuseBSDFClosureParams, N), CLOSURE_FINISH_PARAM(DiffuseBSDFClosureParams) } }, { "emission", EmissionID, { CLOSURE_FLOAT_PARAM(EmissionClosureParams, inner_angle), CLOSURE_FLOAT_PARAM(EmissionClosureParams, outer_angle), CLOSURE_FINISH_PARAM(EmissionClosureParams) } }, { "holdout", HoldoutID, { CLOSURE_FINISH_PARAM(EmptyClosureParams) } }, { "microfacet", MicrofacetID, { CLOSURE_STRING_PARAM(MicrofacetClosureParams, dist), CLOSURE_VECTOR_PARAM(MicrofacetClosureParams, N), CLOSURE_VECTOR_PARAM(MicrofacetClosureParams, T), CLOSURE_FLOAT_PARAM(MicrofacetClosureParams, xalpha), CLOSURE_FLOAT_PARAM(MicrofacetClosureParams, yalpha), CLOSURE_FLOAT_PARAM(MicrofacetClosureParams, eta), CLOSURE_INT_PARAM(MicrofacetClosureParams, refract), CLOSURE_FINISH_PARAM(MicrofacetClosureParams) } }, { "reflection", ReflectionID, { CLOSURE_VECTOR_PARAM(ReflectionBRDFClosureParams, N), CLOSURE_FINISH_PARAM(ReflectionBRDFClosureParams) } }, { "refraction", RefractionID, { CLOSURE_VECTOR_PARAM(RefractionBTDFClosureParams, N), CLOSURE_FLOAT_PARAM(RefractionBTDFClosureParams, eta), CLOSURE_FINISH_PARAM(RefractionBTDFClosureParams) } }, { "translucent", TranslucentID, { CLOSURE_VECTOR_PARAM(DiffuseBSDFClosureParams, N), CLOSURE_FINISH_PARAM(DiffuseBSDFClosureParams) } }, { "transparent", TransparentID, { CLOSURE_FINISH_PARAM(EmptyClosureParams) } }, { 0, 0, {} } // mark end of the array }; for (size_t i = 0; builtins[i].name != 0; ++i) { shading_system.register_closure( builtins[i].name, builtins[i].id, builtins[i].params, 0, 0); RENDERER_LOG_INFO("registered OSL closure %s.", builtins[i].name); } }
void OSLShader::eval_surface(KernelGlobals *kg, ShaderData *sd, PathState *state, int path_flag) { /* setup shader globals from shader data */ OSLThreadData *tdata = kg->osl_tdata; shaderdata_to_shaderglobals(kg, sd, state, path_flag, tdata); /* execute shader for this point */ OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss; OSL::ShaderGlobals *globals = &tdata->globals; OSL::ShadingContext *octx = tdata->context; int shader = sd->shader & SHADER_MASK; /* automatic bump shader */ if(kg->osl->bump_state[shader]) { /* save state */ float3 P = sd->P; float3 dPdx = sd->dP.dx; float3 dPdy = sd->dP.dy; /* set state as if undisplaced */ if(sd->flag & SD_HAS_DISPLACEMENT) { float data[9]; bool found = kg->osl->services->get_attribute(sd, true, OSLRenderServices::u_empty, TypeDesc::TypeVector, OSLRenderServices::u_geom_undisplaced, data); (void)found; assert(found); memcpy(&sd->P, data, sizeof(float)*3); memcpy(&sd->dP.dx, data+3, sizeof(float)*3); memcpy(&sd->dP.dy, data+6, sizeof(float)*3); object_position_transform(kg, sd, &sd->P); object_dir_transform(kg, sd, &sd->dP.dx); object_dir_transform(kg, sd, &sd->dP.dy); globals->P = TO_VEC3(sd->P); globals->dPdx = TO_VEC3(sd->dP.dx); globals->dPdy = TO_VEC3(sd->dP.dy); } /* execute bump shader */ ss->execute(octx, *(kg->osl->bump_state[shader]), *globals); /* reset state */ sd->P = P; sd->dP.dx = dPdx; sd->dP.dy = dPdy; globals->P = TO_VEC3(P); globals->dPdx = TO_VEC3(dPdx); globals->dPdy = TO_VEC3(dPdy); } /* surface shader */ if(kg->osl->surface_state[shader]) { ss->execute(octx, *(kg->osl->surface_state[shader]), *globals); } /* flatten closure tree */ if(globals->Ci) flatten_surface_closure_tree(sd, path_flag, globals->Ci); }
void ShaderGroup::get_shadergroup_closures_info(OSL::ShadingSystem& shading_system) { m_has_emission = true; m_has_transparency = true; m_has_subsurface = true; m_has_holdout = true; m_has_debug = true; int num_unknown_closures = 0; if (!shading_system.getattribute( impl->m_shader_group_ref.get(), "unknown_closures_needed", num_unknown_closures)) { RENDERER_LOG_WARNING( "getattribute: unknown_closures_needed call failed for shader group %s; " "assuming shader group has all kinds of closures.", get_name()); return; } if (num_unknown_closures != 0) { RENDERER_LOG_WARNING( "shader group %s has unknown closures; " "assuming shader group has all kinds of closures.", get_name()); return; } int num_closures = 0; if (!shading_system.getattribute( impl->m_shader_group_ref.get(), "num_closures_needed", num_closures)) { RENDERER_LOG_WARNING( "getattribute: num_closures_needed call failed for shader group %s; " "assuming shader group has all kinds of closures.", get_name()); } if (num_closures != 0) { OIIO::ustring* closures = 0; if (!shading_system.getattribute( impl->m_shader_group_ref.get(), "closures_needed", OIIO::TypeDesc::PTR, &closures)) { RENDERER_LOG_WARNING( "getattribute: closures_needed call failed for shader group %s; " "assuming shader group has all kinds of closures.", get_name()); return; } m_has_emission = false; m_has_transparency = false; m_has_subsurface = false; m_has_holdout = false; m_has_debug = false; for (int i = 0; i < num_closures; ++i) { if (closures[i] == g_emission_str) m_has_emission = true; if (closures[i] == g_transparent_str) m_has_transparency = true; if (closures[i] == g_subsurface_str) m_has_subsurface = true; if (closures[i] == g_holdout_str) m_has_holdout = true; if (closures[i] == g_debug_str) m_has_debug = true; } } }
bool ShaderGroup::create_optimized_osl_shader_group( OSL::ShadingSystem& shading_system, IAbortSwitch* abort_switch) { if (is_valid()) return true; RENDERER_LOG_DEBUG("setting up shader group %s...", get_name()); try { OSL::ShaderGroupRef shader_group_ref = shading_system.ShaderGroupBegin(get_name()); if (shader_group_ref.get() == 0) { RENDERER_LOG_ERROR("failed to setup shader group %s: ShaderGroupBegin() call failed.", get_name()); return false; } for (each<ShaderContainer> i = impl->m_shaders; i; ++i) { if (is_aborted(abort_switch)) { shading_system.ShaderGroupEnd(); return true; } if (!i->add(shading_system)) return false; } for (each<ShaderConnectionContainer> i = impl->m_connections; i; ++i) { if (is_aborted(abort_switch)) { shading_system.ShaderGroupEnd(); return true; } if (!i->add(shading_system)) return false; } if (!shading_system.ShaderGroupEnd()) { RENDERER_LOG_ERROR("failed to setup shader group %s: ShaderGroupEnd() call failed.", get_name()); return false; } impl->m_shader_group_ref = shader_group_ref; get_shadergroup_closures_info(shading_system); report_has_closure("emission", m_has_emission); report_has_closure("transparent", m_has_transparency); report_has_closure("subsurface", m_has_subsurface); report_has_closure("holdout", m_has_holdout); report_has_closure("debug", m_has_debug); get_shadergroup_globals_info(shading_system); report_uses_global("dPdtime", m_uses_dPdtime); return true; } catch (const exception& e) { RENDERER_LOG_ERROR("failed to setup shader group %s: %s.", get_name(), e.what()); return false; } }