Exemple #1
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. */

	switch(closure->id) {
		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) {
#ifdef OSL_SUPPORTS_WEIGHTED_CLOSURE_COMPONENTS
				weight = weight*TO_FLOAT3(comp->w);
#endif
				prim->setup(sd, 0, weight);
			}
		}
	}
}
Exemple #2
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 (closure->type == OSL::ClosureColor::COMPONENT) {
		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
	}
	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);
}
Exemple #3
0
static void flatten_background_closure_tree(ShaderData *sd,
                                            const OSL::ClosureColor *closure,
                                            float3 weight = make_float3(1.0f, 1.0f, 1.0f))
{
	/* 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 */

	switch(closure->id) {
		case OSL::ClosureColor::MUL: {
			OSL::ClosureMul *mul = (OSL::ClosureMul *)closure;
			flatten_background_closure_tree(sd, mul->closure, weight * TO_FLOAT3(mul->weight));
			break;
		}
		case OSL::ClosureColor::ADD: {
			OSL::ClosureAdd *add = (OSL::ClosureAdd *)closure;

			flatten_background_closure_tree(sd, add->closureA, weight);
			flatten_background_closure_tree(sd, add->closureB, weight);
			break;
		}
		default: {
			OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure;
			CClosurePrimitive *prim = (CClosurePrimitive *)comp->data();

			if(prim) {
#ifdef OSL_SUPPORTS_WEIGHTED_CLOSURE_COMPONENTS
				weight = weight*TO_FLOAT3(comp->w);
#endif
				prim->setup(sd, 0, weight);
			}
			break;
		}
	}
}
Exemple #4
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 (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: {
					/* 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 CClosurePrimitive::Holdout:
					break; /* not implemented */
				case CClosurePrimitive::Background:
				case CClosurePrimitive::BSDF:
				case CClosurePrimitive::Emissive:
				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);
	}
}
Exemple #5
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);
}
float3 OSLShader::emissive_eval(const ShaderData *sd, const ShaderClosure *sc)
{
	OSL::EmissiveClosure *emissive = (OSL::EmissiveClosure *)sc->prim;
	OSL::Color3 emissive_eval = emissive->eval(TO_VEC3(sd->Ng), TO_VEC3(sd->I));

	return TO_FLOAT3(emissive_eval);
}
float3 OSLShader::bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, const float3& omega_in, float& pdf)
{
	OSL::BSDFClosure *bsdf = (OSL::BSDFClosure*)sc->prim;
	OSL::Color3 bsdf_eval;

	if(dot(sd->Ng, omega_in) >= 0.0f)
		bsdf_eval = bsdf->eval_reflect(TO_VEC3(sd->I), TO_VEC3(omega_in), pdf);
	else
		bsdf_eval = bsdf->eval_transmit(TO_VEC3(sd->I), TO_VEC3(omega_in), pdf);
	
	return TO_FLOAT3(bsdf_eval);
}
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);
	}
}
Exemple #9
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);
}
Exemple #10
0
bool OSLRenderServices::trace(TraceOpt &options,
                              OSL::ShaderGlobals *sg,
                              const OSL::Vec3 &P,
                              const OSL::Vec3 &dPdx,
                              const OSL::Vec3 &dPdy,
                              const OSL::Vec3 &R,
                              const OSL::Vec3 &dRdx,
                              const OSL::Vec3 &dRdy)
{
  /* todo: options.shader support, maybe options.traceset */
  ShaderData *sd = (ShaderData *)(sg->renderstate);

  /* setup ray */
  Ray ray;

  ray.P = TO_FLOAT3(P);
  ray.D = TO_FLOAT3(R);
  ray.t = (options.maxdist == 1.0e30f) ? FLT_MAX : options.maxdist - options.mindist;
  ray.time = sd->time;

  if (options.mindist == 0.0f) {
    /* avoid self-intersections */
    if (ray.P == sd->P) {
      bool transmit = (dot(sd->Ng, ray.D) < 0.0f);
      ray.P = ray_offset(sd->P, (transmit) ? -sd->Ng : sd->Ng);
    }
  }
  else {
    /* offset for minimum distance */
    ray.P += options.mindist * ray.D;
  }

  /* ray differentials */
  ray.dP.dx = TO_FLOAT3(dPdx);
  ray.dP.dy = TO_FLOAT3(dPdy);
  ray.dD.dx = TO_FLOAT3(dRdx);
  ray.dD.dy = TO_FLOAT3(dRdy);

  /* allocate trace data */
  OSLTraceData *tracedata = (OSLTraceData *)sg->tracedata;
  tracedata->ray = ray;
  tracedata->setup = false;
  tracedata->init = true;
  tracedata->sd.osl_globals = sd->osl_globals;

  /* Raytrace, leaving out shadow opaque to avoid early exit. */
  uint visibility = PATH_RAY_ALL_VISIBILITY - PATH_RAY_SHADOW_OPAQUE;
  return scene_intersect(sd->osl_globals, ray, visibility, &tracedata->isect);
}
void OSLShader::eval_displacement(KernelGlobals *kg, ShaderData *sd)
{
	/* gather pointers */
	OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl*)kg->osl.ss;
	OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data);
	OSL::ShaderGlobals *globals = &tdata->globals;
	OSL::pvt::ShadingContext *ctx = ssi->get_context(tdata->thread_info);

	/* setup shader globals from shader data */
	sd->osl_ctx = ctx;
	shaderdata_to_shaderglobals(kg, sd, 0, globals);

	/* execute shader */
	int shader = sd->shader & SHADER_MASK;

	if(kg->osl.displacement_state[shader])
		ctx->execute(OSL::pvt::ShadUseSurface, *(kg->osl.displacement_state[shader]), *globals);

	/* get back position */
	sd->P = TO_FLOAT3(globals->P);
}
Exemple #12
0
bool OSLRenderServices::trace(TraceOpt &options, OSL::ShaderGlobals *sg,
	const OSL::Vec3 &P, const OSL::Vec3 &dPdx,
	const OSL::Vec3 &dPdy, const OSL::Vec3 &R,
	const OSL::Vec3 &dRdx, const OSL::Vec3 &dRdy)
{
	/* todo: options.shader support, maybe options.traceset */
	ShaderData *sd = (ShaderData *)(sg->renderstate);

	/* setup ray */
	Ray ray;

	ray.P = TO_FLOAT3(P);
	ray.D = TO_FLOAT3(R);
	ray.t = (options.maxdist == 1.0e30)? FLT_MAX: options.maxdist - options.mindist;
	ray.time = sd->time;

	if(options.mindist == 0.0f) {
		/* avoid self-intersections */
		if(ray.P == sd->P) {
			bool transmit = (dot(sd->Ng, ray.D) < 0.0f);
			ray.P = ray_offset(sd->P, (transmit)? -sd->Ng: sd->Ng);
		}
	}
	else {
		/* offset for minimum distance */
		ray.P += options.mindist*ray.D;
	}

	/* ray differentials */
	ray.dP.dx = TO_FLOAT3(dPdx);
	ray.dP.dy = TO_FLOAT3(dPdy);
	ray.dD.dx = TO_FLOAT3(dRdx);
	ray.dD.dy = TO_FLOAT3(dRdy);

	/* allocate trace data */
	OSLTraceData *tracedata = (OSLTraceData*)sg->tracedata;
	tracedata->ray = ray;
	tracedata->setup = false;
	tracedata->init = true;

	/* raytrace */
#ifdef __HAIR__
	return scene_intersect(sd->osl_globals, &ray, ~0, &tracedata->isect, NULL, 0.0f, 0.0f);
#else
	return scene_intersect(sd->osl_globals, &ray, ~0, &tracedata->isect);
#endif
}
Exemple #13
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 (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::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;

#ifdef __HAIR__
					sc.offset = bsdf->sc.offset;
#endif

					/* 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 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::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 CClosurePrimitive::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 CClosurePrimitive::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(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 CClosurePrimitive::Background:
				case CClosurePrimitive::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);
	}
}
float3 OSLShader::volume_eval_phase(const ShaderClosure *sc, const float3 omega_in, const float3 omega_out)
{
	OSL::VolumeClosure *volume = (OSL::VolumeClosure *)sc->prim;
	OSL::Color3 volume_eval = volume->eval_phase(TO_VEC3(omega_in), TO_VEC3(omega_out));
	return TO_FLOAT3(volume_eval) * sc->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);
	}
}
Exemple #16
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);
}
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);
	}
}
Exemple #18
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);
}
Exemple #19
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);
}