--- ray/src/rt/m_bsdf.c 2011/08/22 16:00:47 2.15 +++ ray/src/rt/m_bsdf.c 2015/05/26 13:21:07 2.28 @@ -1,5 +1,5 @@ #ifndef lint -static const char RCSid[] = "$Id: m_bsdf.c,v 2.15 2011/08/22 16:00:47 greg Exp $"; +static const char RCSid[] = "$Id: m_bsdf.c,v 2.28 2015/05/26 13:21:07 greg Exp $"; #endif /* * Shading for materials with BSDFs taken from XML data files @@ -109,20 +109,22 @@ direct_bsdf_OK(COLOR cval, FVECT ldir, double omega, B /* transform source direction */ if (SDmapDir(vsrc, ndp->toloc, ldir) != SDEnone) return(0); + /* assign number of samples */ + ec = SDsizeBSDF(&tomega, ndp->vray, vsrc, SDqueryMin, ndp->sd); + if (ec) + goto baderror; /* check indirect over-counting */ if (ndp->thick != 0 && ndp->pr->crtype & (SPECULAR|AMBIENT) && vsrc[2] > 0 ^ ndp->vray[2] > 0) { double dx = vsrc[0] + ndp->vray[0]; double dy = vsrc[1] + ndp->vray[1]; - if (dx*dx + dy*dy <= omega*(1./PI)) + if (dx*dx + dy*dy <= omega+tomega) return(0); } - /* assign number of samples */ - ec = SDsizeBSDF(&tomega, ndp->vray, vsrc, SDqueryMin, ndp->sd); - if (ec) - goto baderror; sf = specjitter * ndp->pr->rweight; - if (25.*tomega <= omega) + if (tomega <= .0) + nsamp = 1; + else if (25.*tomega <= omega) nsamp = 100.*sf + .5; else nsamp = 4.*sf*omega/tomega + .5; @@ -157,6 +159,7 @@ direct_bsdf_OK(COLOR cval, FVECT ldir, double omega, B return(ok); baderror: objerror(ndp->mp, USER, transSDError(ec)); + return(0); /* gratis return */ } /* Compute source contribution for BSDF (reflected & transmitted) */ @@ -379,7 +382,10 @@ sample_sdf(BSDFDAT *ndp, int sflags) if (sflags == SDsampSpT) { unsc = ndp->tunsamp; - dfp = ndp->sd->tf; + if (ndp->pr->rod > 0) + dfp = (ndp->sd->tf != NULL) ? ndp->sd->tf : ndp->sd->tb; + else + dfp = (ndp->sd->tb != NULL) ? ndp->sd->tb : ndp->sd->tf; cvt_sdcolor(unsc, &ndp->sd->tLamb); } else /* sflags == SDsampSpR */ { unsc = ndp->runsamp; @@ -440,6 +446,7 @@ m_bsdf(OBJREC *m, RAY *r) hitfront = (r->rod > 0); /* load cal file */ mf = getfunc(m, 5, 0x1d, 1); + setfunc(m, r); /* get thickness */ nd.thick = evalue(mf->ep[0]); if ((-FTINY <= nd.thick) & (nd.thick <= FTINY)) @@ -450,6 +457,11 @@ m_bsdf(OBJREC *m, RAY *r) raytrans(r); /* pass-through */ return(1); /* or shadow */ } + /* check backface visibility */ + if (!hitfront & !backvis) { + raytrans(r); + return(1); + } /* check other rays to pass */ if (nd.thick != 0 && (!(r->crtype & (SPECULAR|AMBIENT)) || nd.thick > 0 ^ hitfront)) { @@ -467,15 +479,9 @@ m_bsdf(OBJREC *m, RAY *r) m->oargs.farg[1], m->oargs.farg[2]); } else { - if (m->oargs.nfargs < 6) { /* check invisible backside */ - if (!backvis && (nd.sd->rb == NULL) & - (nd.sd->tf == NULL)) { - SDfreeCache(nd.sd); - raytrans(r); - return(1); - } + if (m->oargs.nfargs < 6) setcolor(nd.rdiff, .0, .0, .0); - } else + else setcolor(nd.rdiff, m->oargs.farg[3], m->oargs.farg[4], m->oargs.farg[5]); @@ -499,10 +505,14 @@ m_bsdf(OBJREC *m, RAY *r) upvec[1] = evalue(mf->ep[2]); upvec[2] = evalue(mf->ep[3]); /* return to world coords */ - if (mf->f != &unitxf) { - multv3(upvec, upvec, mf->f->xfm); - nd.thick *= mf->f->sca; + if (mf->fxp != &unitxf) { + multv3(upvec, upvec, mf->fxp->xfm); + nd.thick *= mf->fxp->sca; } + if (r->rox != NULL) { + multv3(upvec, upvec, r->rox->f.xfm); + nd.thick *= r->rox->f.sca; + } raynormal(nd.pnorm, r); /* compute local BSDF xform */ ec = SDcompXform(nd.toloc, nd.pnorm, upvec); @@ -514,15 +524,15 @@ m_bsdf(OBJREC *m, RAY *r) } if (!ec) ec = SDinvXform(nd.fromloc, nd.toloc); - /* determine BSDF resolution */ - if (!ec) - ec = SDsizeBSDF(nd.sr_vpsa, nd.vray, NULL, - SDqueryMin+SDqueryMax, nd.sd); if (ec) { - objerror(m, WARNING, transSDError(ec)); - SDfreeCache(nd.sd); + objerror(m, WARNING, "Illegal orientation vector"); return(1); } + /* determine BSDF resolution */ + ec = SDsizeBSDF(nd.sr_vpsa, nd.vray, NULL, SDqueryMin+SDqueryMax, nd.sd); + if (ec) + objerror(m, USER, transSDError(ec)); + nd.sr_vpsa[0] = sqrt(nd.sr_vpsa[0]); nd.sr_vpsa[1] = sqrt(nd.sr_vpsa[1]); if (!hitfront) { /* perturb normal towards hit */ @@ -556,7 +566,7 @@ m_bsdf(OBJREC *m, RAY *r) bnorm[2] = -nd.pnorm[2]; if (nd.thick != 0) { /* proxy with offset? */ VCOPY(vtmp, r->rop); - VSUM(r->rop, vtmp, r->ron, -nd.thick); + VSUM(r->rop, vtmp, r->ron, nd.thick); multambient(ctmp, r, bnorm); VCOPY(r->rop, vtmp); } else @@ -566,7 +576,8 @@ m_bsdf(OBJREC *m, RAY *r) flipsurface(r); } /* add direct component */ - if ((bright(nd.tdiff) <= FTINY) & (nd.sd->tf == NULL)) { + if ((bright(nd.tdiff) <= FTINY) & (nd.sd->tf == NULL) & + (nd.sd->tb == NULL)) { direct(r, dir_brdf, &nd); /* reflection only */ } else if (nd.thick == 0) { direct(r, dir_bsdf, &nd); /* thin surface scattering */