Ejemplo n.º 1
0
int
m_dielectric(	/* color a ray which hit a dielectric interface */
	OBJREC  *m,
	RAY  *r
)
{
	double  cos1, cos2, nratio;
	COLOR  ctrans;
	COLOR  talb;
	int  hastexture;
	int	flatsurface;
	double  refl, trans;
	FVECT  dnorm;
	double  d1, d2;
	RAY  p;
	int  i;

	/* PMAP: skip refracted shadow or ambient ray if accounted for in
	   photon map */
	if (shadowRayInPmap(r) || ambRayInPmap(r))
		return(1);
	
	if (m->oargs.nfargs != (m->otype==MAT_DIELECTRIC ? 5 : 8))
		objerror(m, USER, "bad arguments");

	raytexture(r, m->omod);			/* get modifiers */

	if ( (hastexture = DOT(r->pert,r->pert) > FTINY*FTINY) )
		cos1 = raynormal(dnorm, r);	/* perturb normal */
	else {
		VCOPY(dnorm, r->ron);
		cos1 = r->rod;
	}
	flatsurface = r->ro != NULL && isflat(r->ro->otype) &&
			!hastexture | (r->crtype & AMBIENT);

						/* index of refraction */
	if (m->otype == MAT_DIELECTRIC)
		nratio = m->oargs.farg[3] + m->oargs.farg[4]/MLAMBDA;
	else
		nratio = m->oargs.farg[3] / m->oargs.farg[7];
	
	if (cos1 < 0.0) {			/* inside */
		hastexture = -hastexture;
		cos1 = -cos1;
		dnorm[0] = -dnorm[0];
		dnorm[1] = -dnorm[1];
		dnorm[2] = -dnorm[2];
		setcolor(r->cext, -mylog(m->oargs.farg[0]*colval(r->pcol,RED)),
				 -mylog(m->oargs.farg[1]*colval(r->pcol,GRN)),
				 -mylog(m->oargs.farg[2]*colval(r->pcol,BLU)));
		setcolor(r->albedo, 0., 0., 0.);
		r->gecc = 0.;
		if (m->otype == MAT_INTERFACE) {
			setcolor(ctrans,
				-mylog(m->oargs.farg[4]*colval(r->pcol,RED)),
				-mylog(m->oargs.farg[5]*colval(r->pcol,GRN)),
				-mylog(m->oargs.farg[6]*colval(r->pcol,BLU)));
			setcolor(talb, 0., 0., 0.);
		} else {
			copycolor(ctrans, cextinction);
			copycolor(talb, salbedo);
		}
	} else {				/* outside */
		nratio = 1.0 / nratio;

		setcolor(ctrans, -mylog(m->oargs.farg[0]*colval(r->pcol,RED)),
				 -mylog(m->oargs.farg[1]*colval(r->pcol,GRN)),
				 -mylog(m->oargs.farg[2]*colval(r->pcol,BLU)));
		setcolor(talb, 0., 0., 0.);
		if (m->otype == MAT_INTERFACE) {
			setcolor(r->cext,
				-mylog(m->oargs.farg[4]*colval(r->pcol,RED)),
				-mylog(m->oargs.farg[5]*colval(r->pcol,GRN)),
				-mylog(m->oargs.farg[6]*colval(r->pcol,BLU)));
			setcolor(r->albedo, 0., 0., 0.);
			r->gecc = 0.;
		}
	}

	d2 = 1.0 - nratio*nratio*(1.0 - cos1*cos1);	/* compute cos theta2 */

	if (d2 < FTINY)			/* total reflection */

		refl = 1.0;

	else {				/* refraction occurs */
					/* compute Fresnel's equations */
		cos2 = sqrt(d2);
		d1 = cos1;
		d2 = nratio*cos2;
		d1 = (d1 - d2) / (d1 + d2);
		refl = d1 * d1;

		d1 = 1.0 / cos1;
		d2 = nratio / cos2;
		d1 = (d1 - d2) / (d1 + d2);
		refl += d1 * d1;

		refl *= 0.5;
		trans = 1.0 - refl;

		trans *= nratio*nratio;		/* solid angle ratio */

		setcolor(p.rcoef, trans, trans, trans);

		if (rayorigin(&p, REFRACTED, r, p.rcoef) == 0) {

						/* compute refracted ray */
			d1 = nratio*cos1 - cos2;
			for (i = 0; i < 3; i++)
				p.rdir[i] = nratio*r->rdir[i] + d1*dnorm[i];
						/* accidental reflection? */
			if (hastexture &&
				DOT(p.rdir,r->ron)*hastexture >= -FTINY) {
				d1 *= (double)hastexture;
				for (i = 0; i < 3; i++)	/* ignore texture */
					p.rdir[i] = nratio*r->rdir[i] +
							d1*r->ron[i];
				normalize(p.rdir);	/* not exact */
			} else
				checknorm(p.rdir);
#ifdef  DISPERSE
			if (m->otype != MAT_DIELECTRIC
					|| r->rod > 0.0
					|| r->crtype & SHADOW
					|| !directvis
					|| m->oargs.farg[4] == 0.0
					|| !disperse(m, r, p.rdir,
							trans, ctrans, talb))
#endif
			{
				copycolor(p.cext, ctrans);
				copycolor(p.albedo, talb);
				rayvalue(&p);
				multcolor(p.rcol, p.rcoef);
				addcolor(r->rcol, p.rcol);
						/* virtual distance */
				if (flatsurface ||
					(1.-FTINY <= nratio) &
						(nratio <= 1.+FTINY))
					r->rxt = r->rot + raydistance(&p);
			}
		}
	}
	setcolor(p.rcoef, refl, refl, refl);

	if (!(r->crtype & SHADOW) &&
			rayorigin(&p, REFLECTED, r, p.rcoef) == 0) {

					/* compute reflected ray */
		VSUM(p.rdir, r->rdir, dnorm, 2.*cos1);
					/* accidental penetration? */
		if (hastexture && DOT(p.rdir,r->ron)*hastexture <= FTINY)
			VSUM(p.rdir, r->rdir, r->ron, 2.*r->rod);
		checknorm(p.rdir);
		rayvalue(&p);			/* reflected ray value */

		multcolor(p.rcol, p.rcoef);	/* color contribution */
		copycolor(r->mcol, p.rcol);
		addcolor(r->rcol, p.rcol);
						/* virtual distance */
		r->rmt = r->rot;
		if (flatsurface)
			r->rmt += raydistance(&p);
	}
				/* rayvalue() computes absorption */
	return(1);
}
Ejemplo n.º 2
0
int
m_brdf(			/* color a ray that hit a BRDTfunc material */
	OBJREC  *m,
	RAY  *r
)
{
	int  hitfront = 1;
	BRDFDAT  nd;
	RAY  sr;
	double  mirtest=0, mirdist=0;
	double  transtest=0, transdist=0;
	int  hasrefl, hastrans;
	int  hastexture;
	COLOR  ctmp;
	FVECT  vtmp;
	double  d;
	MFUNC  *mf;
	int  i;
						/* check arguments */
	if ((m->oargs.nsargs < 10) | (m->oargs.nfargs < 9))
		objerror(m, USER, "bad # arguments");
	nd.mp = m;
	nd.pr = r;
						/* dummy values */
	nd.rspec = nd.tspec = 1.0;
	nd.trans = 0.5;
						/* diffuse reflectance */
	if (r->rod > 0.0)
		setcolor(nd.rdiff, m->oargs.farg[0],
				m->oargs.farg[1],
				m->oargs.farg[2]);
	else
		setcolor(nd.rdiff, m->oargs.farg[3],
				m->oargs.farg[4],
				m->oargs.farg[5]);
						/* diffuse transmittance */
	setcolor(nd.tdiff, m->oargs.farg[6],
			m->oargs.farg[7],
			m->oargs.farg[8]);
						/* get modifiers */
	raytexture(r, m->omod);
	hastexture = DOT(r->pert,r->pert) > FTINY*FTINY;
	if (hastexture) {			/* perturb normal */
		nd.pdot = raynormal(nd.pnorm, r);
	} else {
		VCOPY(nd.pnorm, r->ron);
		nd.pdot = r->rod;
	}
	if (r->rod < 0.0) {			/* orient perturbed values */
		nd.pdot = -nd.pdot;
		for (i = 0; i < 3; i++) {
			nd.pnorm[i] = -nd.pnorm[i];
			r->pert[i] = -r->pert[i];
		}
		hitfront = 0;
	}
	copycolor(nd.mcolor, r->pcol);		/* get pattern color */
	multcolor(nd.rdiff, nd.mcolor);		/* modify diffuse values */
	multcolor(nd.tdiff, nd.mcolor);
	hasrefl = bright(nd.rdiff) > FTINY;
	hastrans = bright(nd.tdiff) > FTINY;
						/* load cal file */
	nd.dp = NULL;
	mf = getfunc(m, 9, 0x3f, 0);
						/* compute transmitted ray */
	setbrdfunc(&nd);
	errno = 0;
	setcolor(ctmp, evalue(mf->ep[3]),
			evalue(mf->ep[4]),
			evalue(mf->ep[5]));
	if ((errno == EDOM) | (errno == ERANGE))
		objerror(m, WARNING, "compute error");
	else if (rayorigin(&sr, TRANS, r, ctmp) == 0) {
		if (!(r->crtype & SHADOW) && hastexture) {
						/* perturb direction */
			VSUM(sr.rdir, r->rdir, r->pert, -.75);
			if (normalize(sr.rdir) == 0.0) {
				objerror(m, WARNING, "illegal perturbation");
				VCOPY(sr.rdir, r->rdir);
			}
		} else {
			VCOPY(sr.rdir, r->rdir);
		}
		rayvalue(&sr);
		multcolor(sr.rcol, sr.rcoef);
		addcolor(r->rcol, sr.rcol);
		if (!hastexture) {
			transtest = 2.0*bright(sr.rcol);
			transdist = r->rot + sr.rt;
		}
	}
	if (r->crtype & SHADOW)			/* the rest is shadow */
		return(1);
						/* compute reflected ray */
	setbrdfunc(&nd);
	errno = 0;
	setcolor(ctmp, evalue(mf->ep[0]),
			evalue(mf->ep[1]),
			evalue(mf->ep[2]));
	if ((errno == EDOM) | (errno == ERANGE))
		objerror(m, WARNING, "compute error");
	else if (rayorigin(&sr, REFLECTED, r, ctmp) == 0) {
		VSUM(sr.rdir, r->rdir, nd.pnorm, 2.*nd.pdot);
		checknorm(sr.rdir);
		rayvalue(&sr);
		multcolor(sr.rcol, sr.rcoef);
		addcolor(r->rcol, sr.rcol);
		if (!hastexture && r->ro != NULL && isflat(r->ro->otype)) {
			mirtest = 2.0*bright(sr.rcol);
			mirdist = r->rot + sr.rt;
		}
	}
						/* compute ambient */
	if (hasrefl) {
		if (!hitfront)
			flipsurface(r);
		copycolor(ctmp, nd.rdiff);
		multambient(ctmp, r, nd.pnorm);
		addcolor(r->rcol, ctmp);	/* add to returned color */
		if (!hitfront)
			flipsurface(r);
	}
	if (hastrans) {				/* from other side */
		if (hitfront)
			flipsurface(r);
		vtmp[0] = -nd.pnorm[0];
		vtmp[1] = -nd.pnorm[1];
		vtmp[2] = -nd.pnorm[2];
		copycolor(ctmp, nd.tdiff);
		multambient(ctmp, r, vtmp);
		addcolor(r->rcol, ctmp);
		if (hitfront)
			flipsurface(r);
	}
	if (hasrefl | hastrans || m->oargs.sarg[6][0] != '0')
		direct(r, dirbrdf, &nd);	/* add direct component */

	d = bright(r->rcol);			/* set effective distance */
	if (transtest > d)
		r->rt = transdist;
	else if (mirtest > d)
		r->rt = mirdist;

	return(1);
}
Ejemplo n.º 3
0
int
m_ashikhmin(			/* shade ray that hit something anisotropic */
	OBJREC  *m,
	RAY  *r
)
{
	ASHIKDAT  nd;
	COLOR  ctmp;
	double	fres;
	int  i;
						/* easy shadow test */
	if (r->crtype & SHADOW)
		return(1);

	if (m->oargs.nfargs != 8)
		objerror(m, USER, "bad number of real arguments");
						/* check for back side */
	if (r->rod < 0.0) {
		if (!backvis) {
			raytrans(r);
			return(1);
		}
		raytexture(r, m->omod);
		flipsurface(r);			/* reorient if backvis */
	} else
		raytexture(r, m->omod);
						/* get material color */
	nd.mp = m;
	nd.rp = r;
	setcolor(nd.mcolor, m->oargs.farg[0],
			   m->oargs.farg[1],
			   m->oargs.farg[2]);
	setcolor(nd.scolor, m->oargs.farg[3],
			   m->oargs.farg[4],
			   m->oargs.farg[5]);
						/* get specular power */
	nd.specfl = 0;
	nd.u_power = m->oargs.farg[6];
	nd.v_power = m->oargs.farg[7];

	nd.pdot = raynormal(nd.pnorm, r);	/* perturb normal */
	if (nd.pdot < .001)
		nd.pdot = .001;			/* non-zero for dirashik() */
	multcolor(nd.mcolor, r->pcol);		/* modify diffuse color */

	if (bright(nd.scolor) > FTINY) {	/* adjust specular color */
		nd.specfl |= SPA_REFL;
						/* check threshold */
		if (specthresh >= bright(nd.scolor)-FTINY)
			nd.specfl |= SPA_RBLT;
		fres = schlick_fres(nd.pdot);	/* Schick's Fresnel approx */
		for (i = 0; i < 3; i++)
			colval(nd.scolor,i) += (1.-colval(nd.scolor,i))*fres;
	}
	if (r->ro != NULL && isflat(r->ro->otype))
		nd.specfl |= SPA_FLAT;
						/* set up coordinates */
	getacoords_as(&nd);
						/* specular sampling? */
	if ((nd.specfl & (SPA_REFL|SPA_RBLT)) == SPA_REFL)
		ashiksamp(&nd);
						/* diffuse interreflection */
	if (bright(nd.mcolor) > FTINY) {
		copycolor(ctmp, nd.mcolor);	/* modified by material color */		
		if (nd.specfl & SPA_RBLT)	/* add in specular as well? */
			addcolor(ctmp, nd.scolor);
		multambient(ctmp, r, nd.pnorm);
		addcolor(r->rcol, ctmp);	/* add to returned color */
	}
	direct(r, dirashik, &nd);		/* add direct component */

	return(1);
}
Ejemplo n.º 4
0
static int
redirect(		/* compute n'th ray redirection */
	OBJREC  *m,
	RAY  *r,
	int  n
)
{
	MFUNC  *mf;
	EPNODE  **va;
	FVECT  nsdir;
	RAY  nr;
	double  coef;
	int  j;
					/* set up function */
	mf = getdfunc(m);
	setfunc(m, r);
					/* assign direction variable */
	if (r->rsrc >= 0) {
		SRCREC  *sp = source + source[r->rsrc].sa.sv.sn;

		if (sp->sflags & SDISTANT)
			VCOPY(nsdir, sp->sloc);
		else {
			for (j = 0; j < 3; j++)
				nsdir[j] = sp->sloc[j] - r->rop[j];
			normalize(nsdir);
		}
		multv3(nsdir, nsdir, funcxf.xfm);
		varset("DxA", '=', nsdir[0]/funcxf.sca);
		varset("DyA", '=', nsdir[1]/funcxf.sca);
		varset("DzA", '=', nsdir[2]/funcxf.sca);
	} else {
		varset("DxA", '=', 0.0);
		varset("DyA", '=', 0.0);
		varset("DzA", '=', 0.0);
	}
					/* compute coefficient */
	errno = 0;
	va = mf->ep + 4*n;
	coef = evalue(va[0]);
	if ((errno == EDOM) | (errno == ERANGE))
		goto computerr;
	setcolor(nr.rcoef, coef, coef, coef);
	if (rayorigin(&nr, TRANS, r, nr.rcoef) < 0)
		return(0);
	va++;				/* compute direction */
	for (j = 0; j < 3; j++) {
		nr.rdir[j] = evalue(va[j]);
		if (errno == EDOM || errno == ERANGE)
			goto computerr;
	}
	if (mf->fxp != &unitxf)
		multv3(nr.rdir, nr.rdir, mf->fxp->xfm);
	if (r->rox != NULL)
		multv3(nr.rdir, nr.rdir, r->rox->f.xfm);
	if (normalize(nr.rdir) == 0.0)
		goto computerr;
					/* compute value */
	if (r->rsrc >= 0)
		nr.rsrc = source[r->rsrc].sa.sv.sn;
	rayvalue(&nr);
	multcolor(nr.rcol, nr.rcoef);
	addcolor(r->rcol, nr.rcol);
	if (r->ro != NULL && isflat(r->ro->otype))
		r->rt = r->rot + nr.rt;
	return(1);
computerr:
	objerror(m, WARNING, "compute error");
	return(-1);
}
Ejemplo n.º 5
0
int
m_aniso(			/* shade ray that hit something anisotropic */
	OBJREC  *m,
	RAY  *r
)
{
	ANISODAT  nd;
	COLOR  ctmp;
	int  i;
						/* easy shadow test */
	if (r->crtype & SHADOW)
		return(1);

	if (m->oargs.nfargs != (m->otype == MAT_TRANS2 ? 8 : 6))
		objerror(m, USER, "bad number of real arguments");
						/* check for back side */
	if (r->rod < 0.0) {
		if (!backvis) {
			raytrans(r);
			return(1);
		}
		raytexture(r, m->omod);
		flipsurface(r);			/* reorient if backvis */
	} else
		raytexture(r, m->omod);
						/* get material color */
	nd.mp = m;
	nd.rp = r;
	setcolor(nd.mcolor, m->oargs.farg[0],
			   m->oargs.farg[1],
			   m->oargs.farg[2]);
						/* get roughness */
	nd.specfl = 0;
	nd.u_alpha = m->oargs.farg[4];
	nd.v_alpha = m->oargs.farg[5];
	if ((nd.u_alpha <= FTINY) | (nd.v_alpha <= FTINY))
		objerror(m, USER, "roughness too small");

	nd.pdot = raynormal(nd.pnorm, r);	/* perturb normal */
	if (nd.pdot < .001)
		nd.pdot = .001;			/* non-zero for diraniso() */
	multcolor(nd.mcolor, r->pcol);		/* modify material color */
						/* get specular component */
	if ((nd.rspec = m->oargs.farg[3]) > FTINY) {
		nd.specfl |= SP_REFL;
						/* compute specular color */
		if (m->otype == MAT_METAL2)
			copycolor(nd.scolor, nd.mcolor);
		else
			setcolor(nd.scolor, 1.0, 1.0, 1.0);
		scalecolor(nd.scolor, nd.rspec);
						/* check threshold */
		if (specthresh >= nd.rspec-FTINY)
			nd.specfl |= SP_RBLT;
						/* compute refl. direction */
		VSUM(nd.vrefl, r->rdir, nd.pnorm, 2.0*nd.pdot);
		if (DOT(nd.vrefl, r->ron) <= FTINY)	/* penetration? */
			VSUM(nd.vrefl, r->rdir, r->ron, 2.0*r->rod);
	}
						/* compute transmission */
	if (m->otype == MAT_TRANS2) {
		nd.trans = m->oargs.farg[6]*(1.0 - nd.rspec);
		nd.tspec = nd.trans * m->oargs.farg[7];
		nd.tdiff = nd.trans - nd.tspec;
		if (nd.tspec > FTINY) {
			nd.specfl |= SP_TRAN;
							/* check threshold */
			if (specthresh >= nd.tspec-FTINY)
				nd.specfl |= SP_TBLT;
			if (DOT(r->pert,r->pert) <= FTINY*FTINY) {
				VCOPY(nd.prdir, r->rdir);
			} else {
				for (i = 0; i < 3; i++)		/* perturb */
					nd.prdir[i] = r->rdir[i] - r->pert[i];
				if (DOT(nd.prdir, r->ron) < -FTINY)
					normalize(nd.prdir);	/* OK */
				else
					VCOPY(nd.prdir, r->rdir);
			}
		}
	} else
		nd.tdiff = nd.tspec = nd.trans = 0.0;

						/* diffuse reflection */
	nd.rdiff = 1.0 - nd.trans - nd.rspec;

	if (r->ro != NULL && isflat(r->ro->otype))
		nd.specfl |= SP_FLAT;

	getacoords(&nd);			/* set up coordinates */

	if (nd.specfl & (SP_REFL|SP_TRAN))
		agaussamp(&nd);

	if (nd.rdiff > FTINY) {		/* ambient from this side */
		copycolor(ctmp, nd.mcolor);	/* modified by material color */
		scalecolor(ctmp, nd.rdiff);
		if (nd.specfl & SP_RBLT)	/* add in specular as well? */
			addcolor(ctmp, nd.scolor);
		multambient(ctmp, r, nd.pnorm);
		addcolor(r->rcol, ctmp);	/* add to returned color */
	}
	if (nd.tdiff > FTINY) {		/* ambient from other side */
		FVECT  bnorm;

		flipsurface(r);
		bnorm[0] = -nd.pnorm[0];
		bnorm[1] = -nd.pnorm[1];
		bnorm[2] = -nd.pnorm[2];
		copycolor(ctmp, nd.mcolor);	/* modified by color */
		if (nd.specfl & SP_TBLT)
			scalecolor(ctmp, nd.trans);
		else
			scalecolor(ctmp, nd.tdiff);
		multambient(ctmp, r, bnorm);
		addcolor(r->rcol, ctmp);
		flipsurface(r);
	}
					/* add direct component */
	direct(r, diraniso, &nd);

	return(1);
}