--- ray/src/rt/aniso.c 1992/01/04 23:36:40 2.2 +++ ray/src/rt/aniso.c 1992/01/15 11:02:43 2.5 @@ -16,6 +16,9 @@ static char SCCSid[] = "$SunId$ LBL"; #include "random.h" +extern double specthresh; /* specular sampling threshold */ +extern double specjitter; /* specular sampling jitter */ + /* * This anisotropic reflection model uses a variant on the * exponential Gaussian used in normal.c. @@ -37,8 +40,10 @@ static char SCCSid[] = "$SunId$ LBL"; #define SP_REFL 01 /* has reflected specular component */ #define SP_TRAN 02 /* has transmitted specular */ #define SP_PURE 010 /* purely specular (zero roughness) */ -#define SP_BADU 020 /* bad u direction calculation */ -#define SP_FLAT 040 /* reflecting surface is flat */ +#define SP_FLAT 020 /* reflecting surface is flat */ +#define SP_RBLT 040 /* reflection below sample threshold */ +#define SP_TBLT 0100 /* transmission below threshold */ +#define SP_BADU 0200 /* bad u direction calculation */ typedef struct { OBJREC *mp; /* material pointer */ @@ -200,6 +205,12 @@ register RAY *r; for (i = 0; i < 3; i++) colval(nd.scolor,i) += (1.0-colval(nd.scolor,i))*dtmp; nd.rspec += (1.0-nd.rspec)*dtmp; + /* check threshold */ + if (specthresh > FTINY && + ((specthresh >= 1.-FTINY || + specthresh + (.1 - .2*urand(8199+samplendx)) + > nd.rspec))) + nd.specfl |= SP_RBLT; if (!(r->crtype & SHADOW) && nd.specfl & SP_PURE) { RAY lr; @@ -220,6 +231,13 @@ register RAY *r; nd.tdiff = nd.trans - nd.tspec; if (nd.tspec > FTINY) { nd.specfl |= SP_TRAN; + /* check threshold */ + if (specthresh > FTINY && + ((specthresh >= 1.-FTINY || + specthresh + + (.1 - .2*urand(7241+samplendx)) + > nd.tspec))) + nd.specfl |= SP_TBLT; if (r->crtype & SHADOW || DOT(r->pert,r->pert) <= FTINY*FTINY) { VCOPY(nd.prdir, r->rdir); @@ -255,6 +273,9 @@ register RAY *r; if (nd.specfl & SP_PURE && nd.rdiff <= FTINY && nd.tdiff <= FTINY) return; /* 100% pure specular */ + if (r->ro->otype == OBJ_FACE || r->ro->otype == OBJ_RING) + nd.specfl |= SP_FLAT; + getacoords(r, &nd); /* set up coordinates */ if (nd.specfl & (SP_REFL|SP_TRAN) && !(nd.specfl & (SP_PURE|SP_BADU))) @@ -262,14 +283,20 @@ register RAY *r; if (nd.rdiff > FTINY) { /* ambient from this side */ ambient(ctmp, r); - scalecolor(ctmp, nd.rdiff); + if (nd.specfl & SP_RBLT) + scalecolor(ctmp, 1.0-nd.trans); + else + scalecolor(ctmp, nd.rdiff); multcolor(ctmp, nd.mcolor); /* modified by material color */ addcolor(r->rcol, ctmp); /* add to returned color */ } if (nd.tdiff > FTINY) { /* ambient from other side */ flipsurface(r); ambient(ctmp, r); - scalecolor(ctmp, nd.tdiff); + if (nd.specfl & SP_TBLT) + scalecolor(ctmp, nd.trans); + else + scalecolor(ctmp, nd.tdiff); multcolor(ctmp, nd.mcolor); /* modified by color */ addcolor(r->rcol, ctmp); flipsurface(r); @@ -320,40 +347,42 @@ register ANISODAT *np; FVECT h; double rv[2]; double d, sinp, cosp; - int confuse; + int ntries; register int i; /* compute reflection */ - if (np->specfl & SP_REFL && + if ((np->specfl & (SP_REFL|SP_RBLT)) == SP_REFL && rayorigin(&sr, r, SPECULAR, np->rspec) == 0) { - confuse = 0; dimlist[ndims++] = (int)np->mp; - refagain: - dimlist[ndims] = confuse += 3601; - d = urand(ilhash(dimlist,ndims+1)+samplendx); - multisamp(rv, 2, d); - d = 2.0*PI * rv[0]; - cosp = np->u_alpha * cos(d); - sinp = np->v_alpha * sin(d); - d = sqrt(cosp*cosp + sinp*sinp); - cosp /= d; - sinp /= d; - if (rv[1] <= FTINY) - d = 1.0; - else - d = sqrt( -log(rv[1]) / - (cosp*cosp/(np->u_alpha*np->u_alpha) + - sinp*sinp/(np->v_alpha*np->v_alpha)) ); - for (i = 0; i < 3; i++) - h[i] = np->pnorm[i] + + for (ntries = 0; ntries < 10; ntries++) { + dimlist[ndims] = ntries * 3601; + d = urand(ilhash(dimlist,ndims+1)+samplendx); + multisamp(rv, 2, d); + d = 2.0*PI * rv[0]; + cosp = np->u_alpha * cos(d); + sinp = np->v_alpha * sin(d); + d = sqrt(cosp*cosp + sinp*sinp); + cosp /= d; + sinp /= d; + rv[1] = 1.0 - specjitter*rv[1]; + if (rv[1] <= FTINY) + d = 1.0; + else + d = sqrt(-log(rv[1]) / + (cosp*cosp/(np->u_alpha*np->u_alpha) + + sinp*sinp/(np->v_alpha*np->v_alpha))); + for (i = 0; i < 3; i++) + h[i] = np->pnorm[i] + d*(cosp*np->u[i] + sinp*np->v[i]); - d = -2.0 * DOT(h, r->rdir) / (1.0 + d*d); - for (i = 0; i < 3; i++) - sr.rdir[i] = r->rdir[i] + d*h[i]; - if (DOT(sr.rdir, r->ron) <= FTINY) /* oops! */ - goto refagain; - rayvalue(&sr); - multcolor(sr.rcol, np->scolor); - addcolor(r->rcol, sr.rcol); + d = -2.0 * DOT(h, r->rdir) / (1.0 + d*d); + for (i = 0; i < 3; i++) + sr.rdir[i] = r->rdir[i] + d*h[i]; + if (DOT(sr.rdir, r->ron) > FTINY) { + rayvalue(&sr); + multcolor(sr.rcol, np->scolor); + addcolor(r->rcol, sr.rcol); + break; + } + } ndims--; } /* compute transmission */