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 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);
	}
}
Example #3
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 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);
	}
}
Example #5
0
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);
	}
}