예제 #1
0
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);
}
예제 #2
0
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);
}
예제 #3
0
static void shaderdata_to_shaderglobals(KernelGlobals *kg, ShaderData *sd, PathState *state,
                                        int path_flag, OSLThreadData *tdata)
{
	OSL::ShaderGlobals *globals = &tdata->globals;

	/* copy from shader data to shader globals */
	globals->P = TO_VEC3(sd->P);
	globals->dPdx = TO_VEC3(sd->dP.dx);
	globals->dPdy = TO_VEC3(sd->dP.dy);
	globals->I = TO_VEC3(sd->I);
	globals->dIdx = TO_VEC3(sd->dI.dx);
	globals->dIdy = TO_VEC3(sd->dI.dy);
	globals->N = TO_VEC3(sd->N);
	globals->Ng = TO_VEC3(sd->Ng);
	globals->u = sd->u;
	globals->dudx = sd->du.dx;
	globals->dudy = sd->du.dy;
	globals->v = sd->v;
	globals->dvdx = sd->dv.dx;
	globals->dvdy = sd->dv.dy;
	globals->dPdu = TO_VEC3(sd->dPdu);
	globals->dPdv = TO_VEC3(sd->dPdv);
	globals->surfacearea = (sd->object == OBJECT_NONE) ? 1.0f : object_surface_area(kg, sd->object);
	globals->time = sd->time;

	/* booleans */
	globals->raytype = path_flag;
	globals->backfacing = (sd->flag & SD_BACKFACING);

	/* shader data to be used in services callbacks */
	globals->renderstate = sd; 

	/* hacky, we leave it to services to fetch actual object matrix */
	globals->shader2common = sd;
	globals->object2common = sd;

	/* must be set to NULL before execute */
	globals->Ci = NULL;

	/* clear trace data */
	tdata->tracedata.init = false;

	/* used by renderservices */
	sd->osl_globals = kg;
	sd->osl_path_state = state;
}
예제 #4
0
static void shaderdata_to_shaderglobals(KernelGlobals *kg, ShaderData *sd,
	int path_flag, OSL::ShaderGlobals *globals)
{
	/* copy from shader data to shader globals */
	globals->P = TO_VEC3(sd->P);
	globals->dPdx = TO_VEC3(sd->dP.dx);
	globals->dPdy = TO_VEC3(sd->dP.dy);
	globals->I = TO_VEC3(sd->I);
	globals->dIdx = TO_VEC3(sd->dI.dx);
	globals->dIdy = TO_VEC3(sd->dI.dy);
	globals->N = TO_VEC3(sd->N);
	globals->Ng = TO_VEC3(sd->Ng);
	globals->u = sd->u;
	globals->dudx = sd->du.dx;
	globals->dudy = sd->du.dy;
	globals->v = sd->v;
	globals->dvdx = sd->dv.dx;
	globals->dvdy = sd->dv.dy;
	globals->dPdu = TO_VEC3(sd->dPdu);
	globals->dPdv = TO_VEC3(sd->dPdv);
	globals->surfacearea = (sd->object == ~0)? 1.0f: object_surface_area(kg, sd->object);

	/* booleans */
	globals->raytype = path_flag; /* todo: add our own ray types */
	globals->backfacing = (sd->flag & SD_BACKFACING);

	/* don't know yet if we need this */
	globals->flipHandedness = false;
	
	/* shader data to be used in services callbacks */
	globals->renderstate = sd; 

	/* hacky, we leave it to services to fetch actual object matrix */
	globals->shader2common = sd;
	globals->object2common = sd;

	/* must be set to NULL before execute */
	globals->Ci = NULL;
}
예제 #5
0
int OSLShader::bsdf_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3& eval, float3& omega_in, differential3& domega_in, float& pdf)
{
	OSL::BSDFClosure *sample_bsdf = (OSL::BSDFClosure*)sc->prim;
	int label = LABEL_NONE;

	pdf = 0.0f;

	/* sample BSDF closure */
	ustring ulabel;

	ulabel = sample_bsdf->sample(TO_VEC3(sd->Ng),
		TO_VEC3(sd->I), TO_VEC3(sd->dI.dx), TO_VEC3(sd->dI.dy),
		randu, randv,
		TO_VEC3(omega_in), TO_VEC3(domega_in.dx), TO_VEC3(domega_in.dy),
		pdf, TO_COLOR3(eval));

	/* convert OSL label */
	if(ulabel == OSL::Labels::REFLECT)
		label = LABEL_REFLECT;
	else if(ulabel == OSL::Labels::TRANSMIT)
		label = LABEL_TRANSMIT;
	else
		return LABEL_NONE; /* sampling failed */

	/* convert scattering to our bitflag label */
	ustring uscattering = sample_bsdf->scattering();

	if(uscattering == OSL::Labels::DIFFUSE)
		label |= LABEL_DIFFUSE;
	else if(uscattering == OSL::Labels::GLOSSY)
		label |= LABEL_GLOSSY;
	else if(uscattering == OSL::Labels::SINGULAR)
		label |= LABEL_SINGULAR;
	else
		label |= LABEL_TRANSPARENT;

	return label;
}
예제 #6
0
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;
}
예제 #7
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);
	}
}
예제 #8
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);
}