--- ray/src/rt/m_brdf.c 2003/03/05 16:16:53 2.18 +++ ray/src/rt/m_brdf.c 2004/09/09 15:40:02 2.22 @@ -1,5 +1,5 @@ #ifndef lint -static const char RCSid[] = "$Id: m_brdf.c,v 2.18 2003/03/05 16:16:53 greg Exp $"; +static const char RCSid[] = "$Id: m_brdf.c,v 2.22 2004/09/09 15:40:02 greg Exp $"; #endif /* * Shading for materials with arbitrary BRDF's @@ -8,11 +8,11 @@ static const char RCSid[] = "$Id: m_brdf.c,v 2.18 2003 #include "copyright.h" #include "ray.h" - +#include "ambient.h" #include "data.h" - +#include "source.h" #include "otypes.h" - +#include "rtotypes.h" #include "func.h" /* @@ -77,13 +77,19 @@ typedef struct { } BRDFDAT; /* BRDF material data */ +static srcdirf_t dirbrdf; +static int setbrdfunc(BRDFDAT *np); + + static void -dirbrdf(cval, np, ldir, omega) /* compute source contribution */ -COLOR cval; /* returned coefficient */ -register BRDFDAT *np; /* material data */ -FVECT ldir; /* light source direction */ -double omega; /* light source size */ +dirbrdf( /* compute source contribution */ + COLOR cval, /* returned coefficient */ + void *nnp, /* material data */ + FVECT ldir, /* light source direction */ + double omega /* light source size */ +) { + register BRDFDAT *np = nnp; double ldot; double dtmp; COLOR ctmp; @@ -170,7 +176,7 @@ double omega; /* light source size */ /* * Compute reflected non-diffuse component. */ - if (np->mp->otype == MAT_MFUNC | np->mp->otype == MAT_MDATA) + if ((np->mp->otype == MAT_MFUNC) | (np->mp->otype == MAT_MDATA)) multcolor(ctmp, np->mcolor); dtmp = ldot * omega * np->rspec; scalecolor(ctmp, dtmp); @@ -179,7 +185,7 @@ double omega; /* light source size */ /* * Compute transmitted non-diffuse component. */ - if (np->mp->otype == MAT_TFUNC | np->mp->otype == MAT_TDATA) + if ((np->mp->otype == MAT_TFUNC) | (np->mp->otype == MAT_TDATA)) multcolor(ctmp, np->mcolor); dtmp = -ldot * omega * np->tspec; scalecolor(ctmp, dtmp); @@ -189,22 +195,26 @@ double omega; /* light source size */ } -int -m_brdf(m, r) /* color a ray that hit a BRDTfunc material */ -register OBJREC *m; -register RAY *r; +extern int +m_brdf( /* color a ray that hit a BRDTfunc material */ + register OBJREC *m, + register RAY *r +) { int hitfront = 1; BRDFDAT nd; RAY sr; + double mirtest=0, mirdist=0; double transtest, transdist; int hasrefl, hastrans; + int hastexture; COLOR ctmp; FVECT vtmp; + double d; register MFUNC *mf; register int i; /* check arguments */ - if (m->oargs.nsargs < 10 | m->oargs.nfargs < 9) + if ((m->oargs.nsargs < 10) | (m->oargs.nfargs < 9)) objerror(m, USER, "bad # arguments"); nd.mp = m; nd.pr = r; @@ -226,7 +236,13 @@ register RAY *r; m->oargs.farg[8]); /* get modifiers */ raytexture(r, m->omod); - nd.pdot = raynormal(nd.pnorm, r); /* perturb normal */ + 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++) { @@ -245,8 +261,6 @@ register RAY *r; mf = getfunc(m, 9, 0x3f, 0); /* compute transmitted ray */ setbrdfunc(&nd); - transtest = 0; - transdist = r->rot; errno = 0; setcolor(ctmp, evalue(mf->ep[3]), evalue(mf->ep[4]), @@ -254,8 +268,7 @@ register RAY *r; if (errno == EDOM || errno == ERANGE) objerror(m, WARNING, "compute error"); else if (rayorigin(&sr, r, TRANS, bright(ctmp)) == 0) { - if (!(r->crtype & SHADOW) && - DOT(r->pert,r->pert) > FTINY*FTINY) { + if (!(r->crtype & SHADOW) && hastexture) { for (i = 0; i < 3; i++) /* perturb direction */ sr.rdir[i] = r->rdir[i] - .75*r->pert[i]; if (normalize(sr.rdir) == 0.0) { @@ -264,13 +277,14 @@ register RAY *r; } } else { VCOPY(sr.rdir, r->rdir); - transtest = 2; } rayvalue(&sr); multcolor(sr.rcol, ctmp); addcolor(r->rcol, sr.rcol); - transtest *= bright(sr.rcol); - transdist = r->rot + sr.rt; + if (!hastexture) { + transtest = 2.0*bright(sr.rcol); + transdist = r->rot + sr.rt; + } } if (r->crtype & SHADOW) /* the rest is shadow */ return(1); @@ -288,6 +302,10 @@ register RAY *r; rayvalue(&sr); multcolor(sr.rcol, ctmp); 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) { @@ -313,19 +331,23 @@ register RAY *r; } if (hasrefl | hastrans || m->oargs.sarg[6][0] != '0') direct(r, dirbrdf, &nd); /* add direct component */ - /* check distance */ - if (transtest > bright(r->rcol)) + + d = bright(r->rcol); /* set effective distance */ + if (transtest > d) r->rt = transdist; + else if (mirtest > d) + r->rt = mirdist; return(1); } -int -m_brdf2(m, r) /* color a ray that hit a BRDF material */ -register OBJREC *m; -register RAY *r; +extern int +m_brdf2( /* color a ray that hit a BRDF material */ + register OBJREC *m, + register RAY *r +) { BRDFDAT nd; COLOR ctmp; @@ -335,8 +357,8 @@ register RAY *r; if (r->crtype & SHADOW) return(1); /* check arguments */ - if (m->oargs.nsargs < (hasdata(m->otype)?4:2) | m->oargs.nfargs < - (m->otype==MAT_TFUNC|m->otype==MAT_TDATA?6:4)) + if ((m->oargs.nsargs < (hasdata(m->otype)?4:2)) | (m->oargs.nfargs < + ((m->otype==MAT_TFUNC)|(m->otype==MAT_TDATA)?6:4))) objerror(m, USER, "bad # arguments"); /* check for back side */ if (r->rod < 0.0) { @@ -359,7 +381,7 @@ register RAY *r; /* get specular component */ nd.rspec = m->oargs.farg[3]; /* compute transmittance */ - if (m->otype == MAT_TFUNC | m->otype == MAT_TDATA) { + if ((m->otype == MAT_TFUNC) | (m->otype == MAT_TDATA)) { nd.trans = m->oargs.farg[4]*(1.0 - nd.rspec); nd.tspec = nd.trans * m->oargs.farg[5]; dtmp = nd.trans - nd.tspec; @@ -408,9 +430,10 @@ register RAY *r; } -int -setbrdfunc(np) /* set up brdf function and variables */ -register BRDFDAT *np; +static int +setbrdfunc( /* set up brdf function and variables */ + register BRDFDAT *np +) { FVECT vec;