Beispiel #1
0
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;
}
Beispiel #2
0
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);
}
Beispiel #3
0
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;
    }
}
Beispiel #4
0
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;
}
Beispiel #5
0
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);
}
Beispiel #6
0
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;
}
Beispiel #7
0
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);
}
Beispiel #8
0
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;
        }
    }
}
Beispiel #9
0
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);
}
Beispiel #10
0
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);
}
Beispiel #11
0
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);
	}
}
Beispiel #13
0
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;
}
Beispiel #14
0
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))
{
}
Beispiel #16
0
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;
    }
}
Beispiel #17
0
// 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);
    }
}
Beispiel #18
0
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);
}
Beispiel #19
0
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);
}
Beispiel #20
0
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);
}
Beispiel #21
0
// 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);
    }
}
Beispiel #22
0
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);
}
Beispiel #23
0
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;
        }
    }
}
Beispiel #24
0
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;
    }
}