--- ray/src/rt/m_bsdf.c 2021/08/25 16:12:21 2.64 +++ ray/src/rt/m_bsdf.c 2024/09/18 19:52:35 2.74 @@ -1,5 +1,5 @@ #ifndef lint -static const char RCSid[] = "$Id: m_bsdf.c,v 2.64 2021/08/25 16:12:21 greg Exp $"; +static const char RCSid[] = "$Id: m_bsdf.c,v 2.74 2024/09/18 19:52:35 greg Exp $"; #endif /* * Shading for materials with BSDFs taken from XML data files @@ -17,7 +17,7 @@ static const char RCSid[] = "$Id: m_bsdf.c,v 2.64 2021 #include "pmapmat.h" /* - * Arguments to this material include optional diffuse colors. + * Arguments to this material include optional diffuse colors. * String arguments include the BSDF and function files. * For the MAT_BSDF type, a non-zero thickness causes the useful behavior * of translating transmitted rays this distance beneath the surface @@ -86,21 +86,21 @@ typedef struct { RREAL toloc[3][3]; /* world to local BSDF coords */ RREAL fromloc[3][3]; /* local BSDF coords to world */ double thick; /* surface thickness */ - COLOR cthru; /* "through" component for MAT_ABSDF */ - COLOR cthru_surr; /* surround for "through" component */ + SCOLOR cthru; /* "through" component for MAT_ABSDF */ + SCOLOR cthru_surr; /* surround for "through" component */ SDData *sd; /* loaded BSDF data */ - COLOR rdiff; /* diffuse reflection */ - COLOR runsamp; /* BSDF hemispherical reflection */ - COLOR tdiff; /* diffuse transmission */ - COLOR tunsamp; /* BSDF hemispherical transmission */ + SCOLOR rdiff; /* diffuse reflection */ + SCOLOR runsamp; /* BSDF hemispherical reflection */ + SCOLOR tdiff; /* diffuse transmission */ + SCOLOR tunsamp; /* BSDF hemispherical transmission */ } BSDFDAT; /* BSDF material data */ -#define cvt_sdcolor(cv, svp) ccy2rgb(&(svp)->spec, (svp)->cieY, cv) +#define cvt_sdcolor(scv, svp) ccy2scolor(&(svp)->spec, (svp)->cieY, scv) typedef struct { double vy; /* brightness (for sorting) */ FVECT tdir; /* through sample direction (normalized) */ - COLOR vcol; /* BTDF color */ + SCOLOR vcol; /* BTDF color */ } PEAKSAMP; /* BTDF peak sample */ /* Comparison function to put near-peak values in descending order */ @@ -130,18 +130,14 @@ compute_through(BSDFDAT *ndp) {1.8, -1.8}, {-2.4, 0}, {0, 2.4}, {0, -2.4}, {2.4, 0}, }; -#define neighbors(i,j) \ - ((dir2check[i][0]-dir2check[j][0])*(dir2check[i][0]-dir2check[j][0]) + \ - (dir2check[i][1]-dir2check[j][1])*(dir2check[i][1]-dir2check[j][1]) <= 0.73) - const double peak_over = 1.5; PEAKSAMP psamp[NDIR2CHECK]; SDSpectralDF *dfp; FVECT pdir; double tomega, srchrad; double tomsum, tomsurr; - COLOR vpeak, vsurr; + SCOLOR vpeak, vsurr, btdiff; double vypeak; - int i, j, ns; + int i, ns; SDError ec; if (ndp->pr->rod > 0) @@ -151,7 +147,7 @@ compute_through(BSDFDAT *ndp) if (dfp == NULL) return; /* no specular transmission */ - if (bright(ndp->pr->pcol) <= FTINY) + if (sintens(ndp->pr->pcol) <= FTINY) return; /* pattern is black, here */ srchrad = sqrt(dfp->minProjSA); /* else evaluate peak */ for (i = 0; i < NDIR2CHECK; i++) { @@ -160,7 +156,7 @@ compute_through(BSDFDAT *ndp) psamp[i].tdir[1] = -ndp->vray[1] + dir2check[i][1]*srchrad; psamp[i].tdir[2] = -ndp->vray[2]; normalize(psamp[i].tdir); - ec = SDevalBSDF(&sv, psamp[i].tdir, ndp->vray, ndp->sd); + ec = SDevalBSDF(&sv, ndp->vray, psamp[i].tdir, ndp->sd); if (ec) goto baderror; cvt_sdcolor(psamp[i].vcol, &sv); @@ -168,53 +164,57 @@ compute_through(BSDFDAT *ndp) } qsort(psamp, NDIR2CHECK, sizeof(PEAKSAMP), cmp_psamp); if (psamp[0].vy <= FTINY) - return; /* zero area */ - setcolor(vpeak, 0, 0, 0); - setcolor(vsurr, 0, 0, 0); + return; /* zero BTDF here */ + scolorblack(vpeak); + scolorblack(vsurr); vypeak = tomsum = tomsurr = 0; /* combine top unique values */ ns = 0; for (i = 0; i < NDIR2CHECK; i++) { - for (j = i; j--; ) /* check for duplicate sample */ - if (psamp[j].vy == psamp[i].vy && neighbors(i,j)) - break; - if (j >= 0) - continue; /* skip duplicate */ + if (i && psamp[i].vy == psamp[i-1].vy) + continue; /* assume duplicate sample */ - ec = SDsizeBSDF(&tomega, psamp[i].tdir, ndp->vray, + ec = SDsizeBSDF(&tomega, ndp->vray, psamp[i].tdir, SDqueryMin, ndp->sd); if (ec) goto baderror; - /* not really a peak? */ + + scalescolor(psamp[i].vcol, tomega); + /* not part of peak? */ if (tomega > 1.5*dfp->minProjSA || vypeak > 8.*psamp[i].vy*ns) { if (!i) return; /* abort */ - scalecolor(psamp[i].vcol, tomega); - addcolor(vsurr, psamp[i].vcol); + saddscolor(vsurr, psamp[i].vcol); tomsurr += tomega; continue; } - scalecolor(psamp[i].vcol, tomega); - addcolor(vpeak, psamp[i].vcol); + saddscolor(vpeak, psamp[i].vcol); tomsum += tomega; vypeak += psamp[i].vy; ++ns; } - if (vypeak*tomsurr < peak_over*bright(vsurr)*ns) - return; /* peak not peaky enough */ - if ((vypeak/ns - (ndp->vray[2] > 0 ? ndp->sd->tLambFront.cieY - : ndp->sd->tLambBack.cieY)*(1./PI))*tomsum <= .001) - return; /* < 0.1% transmission */ - copycolor(ndp->cthru, vpeak); /* already scaled by omega */ - multcolor(ndp->cthru, ndp->pr->pcol); /* modify by pattern */ - if (tomsurr > FTINY) { /* surround contribution? */ - scalecolor(vsurr, 1./tomsurr); /* this one is avg. BTDF */ - copycolor(ndp->cthru_surr, vsurr); - multcolor(ndp->cthru_surr, ndp->pr->pcol); + if (tomsurr < 0.2*tomsum) /* insufficient surround? */ + return; + scalescolor(vsurr, 1./tomsurr); /* surround is avg. BTDF */ + if (ndp->vray[2] > 0) /* get diffuse BTDF */ + cvt_sdcolor(btdiff, &ndp->sd->tLambFront); + else + cvt_sdcolor(btdiff, &ndp->sd->tLambBack); + scalescolor(btdiff, (1./PI)); + for (i = NCSAMP; i--; ) { /* remove diffuse contrib. */ + if ((vpeak[i] -= tomsum*btdiff[i]) < 0) + vpeak[i] = 0; + if ((vsurr[i] -= btdiff[i]) < 0) + vsurr[i] = 0; } + if (pbright(vpeak) < .0005) /* < 0.05% specular? */ + return; + smultscolor(vsurr, ndp->pr->pcol); /* modify by pattern */ + smultscolor(vpeak, ndp->pr->pcol); + copyscolor(ndp->cthru_surr, vsurr); + copyscolor(ndp->cthru, vpeak); return; baderror: objerror(ndp->mp, USER, transSDError(ec)); -#undef neighbors #undef NDIR2CHECK } @@ -234,23 +234,40 @@ bsdf_jitter(FVECT vres, BSDFDAT *ndp, double sr_psa) /* Get BSDF specular for direct component, returning true if OK to proceed */ static int -direct_specular_OK(COLOR cval, FVECT ldir, double omega, BSDFDAT *ndp) +direct_specular_OK(SCOLOR scval, FVECT ldir, double omega, BSDFDAT *ndp) { - int nsamp; - double wtot = 0; - FVECT vsrc, vsmp, vjit; + int nsamp = 1; + int scnt = 0; + FVECT vsrc; double tomega, tomega2; - double sf, tsr, sd[2]; - COLOR csmp, cdiff; + double tsr, sd[2]; + SCOLOR csmp, cdiff; double diffY; SDValue sv; SDError ec; int i; /* in case we fail */ - setcolor(cval, 0, 0, 0); + scolorblack(scval); /* transform source direction */ if (SDmapDir(vsrc, ndp->toloc, ldir) != SDEnone) return(0); + /* check indirect over-counting */ + if ((vsrc[2] > 0) ^ (ndp->vray[2] > 0) && sintens(ndp->cthru) > FTINY) { + double dx = vsrc[0] + ndp->vray[0]; + double dy = vsrc[1] + ndp->vray[1]; + SDSpectralDF *dfp = (ndp->pr->rod > 0) ? + ((ndp->sd->tf != NULL) ? ndp->sd->tf : ndp->sd->tb) : + ((ndp->sd->tb != NULL) ? ndp->sd->tb : ndp->sd->tf) ; + + tomega = omega*fabs(vsrc[2]); + if (dx*dx + dy*dy <= (2.5*4./PI)*(tomega + dfp->minProjSA + + 2.*sqrt(tomega*dfp->minProjSA))) { + if (sintens(ndp->cthru_surr) <= FTINY) + return(0); + copyscolor(scval, ndp->cthru_surr); + return(1); /* return non-zero surround BTDF */ + } + } /* will discount diffuse portion */ switch ((vsrc[2] > 0)<<1 | (ndp->vray[2] > 0)) { case 3: @@ -279,80 +296,45 @@ direct_specular_OK(COLOR cval, FVECT ldir, double omeg cvt_sdcolor(cdiff, &sv); } else { diffY = 0; - setcolor(cdiff, 0, 0, 0); + scolorblack(cdiff); } - /* need projected solid angle */ - omega *= fabs(vsrc[2]); - /* check indirect over-counting */ - if ((vsrc[2] > 0) ^ (ndp->vray[2] > 0) && bright(ndp->cthru) > FTINY) { - double dx = vsrc[0] + ndp->vray[0]; - double dy = vsrc[1] + ndp->vray[1]; - SDSpectralDF *dfp = (ndp->pr->rod > 0) ? - ((ndp->sd->tf != NULL) ? ndp->sd->tf : ndp->sd->tb) : - ((ndp->sd->tb != NULL) ? ndp->sd->tb : ndp->sd->tf) ; - - if (dx*dx + dy*dy <= (2.5*4./PI)*(omega + dfp->minProjSA + - 2.*sqrt(omega*dfp->minProjSA))) { - if (bright(ndp->cthru_surr) <= FTINY) - return(0); - copycolor(cval, ndp->cthru_surr); - return(1); /* return non-zero surround BTDF */ - } - } ec = SDsizeBSDF(&tomega, ndp->vray, vsrc, SDqueryMin, ndp->sd); if (ec) goto baderror; - /* assign number of samples */ - sf = specjitter * ndp->pr->rweight; - if (tomega <= 0) - nsamp = 1; - else if (25.*tomega <= omega) - nsamp = 100.*sf + .5; - else - nsamp = 4.*sf*omega/tomega + .5; - nsamp += !nsamp; - sf = sqrt(omega); /* sample our source area */ - tsr = sqrt(tomega); - for (i = nsamp; i--; ) { - VCOPY(vsmp, vsrc); /* jitter query directions */ - if (nsamp > 1) { - multisamp(sd, 2, (i + frandom())/(double)nsamp); - vsmp[0] += (sd[0] - .5)*sf; - vsmp[1] += (sd[1] - .5)*sf; - normalize(vsmp); - } + /* check if sampling BSDF */ + if ((tsr = sqrt(tomega)) > 0) { + nsamp = 4.*specjitter*ndp->pr->rweight + .5; + nsamp += !nsamp; + } + for (i = nsamp; i--; ) { /* jitter to fuzz BSDF cells */ + FVECT vjit; bsdf_jitter(vjit, ndp, tsr); /* compute BSDF */ - ec = SDevalBSDF(&sv, vjit, vsmp, ndp->sd); + ec = SDevalBSDF(&sv, vjit, vsrc, ndp->sd); if (ec) goto baderror; - if (sv.cieY - diffY <= FTINY) - continue; /* no specular part */ + if (sv.cieY - diffY <= FTINY) { + ++scnt; /* still counts as 0 contribution */ + continue; + } /* check for variable resolution */ - ec = SDsizeBSDF(&tomega2, vjit, vsmp, SDqueryMin, ndp->sd); + ec = SDsizeBSDF(&tomega2, vjit, vsrc, SDqueryMin, ndp->sd); if (ec) goto baderror; if (tomega2 < .12*tomega) continue; /* not safe to include */ cvt_sdcolor(csmp, &sv); -#if 0 - if (sf < 2.5*tsr) { /* weight by BSDF for small sources */ - scalecolor(csmp, sv.cieY); - wtot += sv.cieY; - } else -#endif - wtot += 1.; - addcolor(cval, csmp); + saddscolor(scval, csmp); + ++scnt; } - if (wtot <= FTINY) /* no valid specular samples? */ + if (!scnt) /* no valid specular samples? */ return(0); - sf = 1./wtot; /* weighted average BSDF */ - scalecolor(cval, sf); + scalescolor(scval, 1./scnt); /* weighted average BSDF */ /* subtract diffuse contribution */ - for (i = 3*(diffY > FTINY); i--; ) - if ((colval(cval,i) -= colval(cdiff,i)) < 0) - colval(cval,i) = 0; + for (i = NCSAMP*(diffY > FTINY); i--; ) + if ((scval[i] -= cdiff[i]) < 0) + scval[i] = 0; return(1); baderror: objerror(ndp->mp, USER, transSDError(ec)); @@ -362,7 +344,7 @@ baderror: /* Compute source contribution for BSDF (reflected & transmitted) */ static void dir_bsdf( - COLOR cval, /* returned coefficient */ + SCOLOR scval, /* returned coefficient */ void *nnp, /* material data */ FVECT ldir, /* light source direction */ double omega /* light source size */ @@ -371,52 +353,52 @@ dir_bsdf( BSDFDAT *np = (BSDFDAT *)nnp; double ldot; double dtmp; - COLOR ctmp; + SCOLOR sctmp; - setcolor(cval, 0, 0, 0); + scolorblack(scval); ldot = DOT(np->pnorm, ldir); if ((-FTINY <= ldot) & (ldot <= FTINY)) return; - if (ldot > 0 && bright(np->rdiff) > FTINY) { + if (ldot > 0 && sintens(np->rdiff) > FTINY) { /* * Compute diffuse reflected component */ - copycolor(ctmp, np->rdiff); + copyscolor(sctmp, np->rdiff); dtmp = ldot * omega * (1./PI); - scalecolor(ctmp, dtmp); - addcolor(cval, ctmp); + scalescolor(sctmp, dtmp); + saddscolor(scval, sctmp); } - if (ldot < 0 && bright(np->tdiff) > FTINY) { + if (ldot < 0 && sintens(np->tdiff) > FTINY) { /* * Compute diffuse transmission */ - copycolor(ctmp, np->tdiff); - dtmp = -ldot * omega * (1.0/PI); - scalecolor(ctmp, dtmp); - addcolor(cval, ctmp); + copyscolor(sctmp, np->tdiff); + dtmp = -ldot * omega * (1./PI); + scalescolor(sctmp, dtmp); + saddscolor(scval, sctmp); } if (ambRayInPmap(np->pr)) return; /* specular already in photon map */ /* * Compute specular scattering coefficient using BSDF */ - if (!direct_specular_OK(ctmp, ldir, omega, np)) + if (!direct_specular_OK(sctmp, ldir, omega, np)) return; if (ldot < 0) { /* pattern for specular transmission */ - multcolor(ctmp, np->pr->pcol); + smultscolor(sctmp, np->pr->pcol); dtmp = -ldot * omega; } else dtmp = ldot * omega; - scalecolor(ctmp, dtmp); - addcolor(cval, ctmp); + scalescolor(sctmp, dtmp); + saddscolor(scval, sctmp); } /* Compute source contribution for BSDF (reflected only) */ static void dir_brdf( - COLOR cval, /* returned coefficient */ + SCOLOR scval, /* returned coefficient */ void *nnp, /* material data */ FVECT ldir, /* light source direction */ double omega /* light source size */ @@ -425,40 +407,40 @@ dir_brdf( BSDFDAT *np = (BSDFDAT *)nnp; double ldot; double dtmp; - COLOR ctmp, ctmp1, ctmp2; + SCOLOR sctmp; - setcolor(cval, 0, 0, 0); + scolorblack(scval); ldot = DOT(np->pnorm, ldir); if (ldot <= FTINY) return; - if (bright(np->rdiff) > FTINY) { + if (sintens(np->rdiff) > FTINY) { /* * Compute diffuse reflected component */ - copycolor(ctmp, np->rdiff); + copyscolor(sctmp, np->rdiff); dtmp = ldot * omega * (1./PI); - scalecolor(ctmp, dtmp); - addcolor(cval, ctmp); + scalescolor(sctmp, dtmp); + saddscolor(scval, sctmp); } if (ambRayInPmap(np->pr)) return; /* specular already in photon map */ /* * Compute specular reflection coefficient using BSDF */ - if (!direct_specular_OK(ctmp, ldir, omega, np)) + if (!direct_specular_OK(sctmp, ldir, omega, np)) return; dtmp = ldot * omega; - scalecolor(ctmp, dtmp); - addcolor(cval, ctmp); + scalescolor(sctmp, dtmp); + saddscolor(scval, sctmp); } /* Compute source contribution for BSDF (transmitted only) */ static void dir_btdf( - COLOR cval, /* returned coefficient */ + SCOLOR scval, /* returned coefficient */ void *nnp, /* material data */ FVECT ldir, /* light source direction */ double omega /* light source size */ @@ -467,36 +449,36 @@ dir_btdf( BSDFDAT *np = (BSDFDAT *)nnp; double ldot; double dtmp; - COLOR ctmp; + SCOLOR sctmp; - setcolor(cval, 0, 0, 0); + scolorblack(scval); ldot = DOT(np->pnorm, ldir); if (ldot >= -FTINY) return; - if (bright(np->tdiff) > FTINY) { + if (sintens(np->tdiff) > FTINY) { /* * Compute diffuse transmission */ - copycolor(ctmp, np->tdiff); - dtmp = -ldot * omega * (1.0/PI); - scalecolor(ctmp, dtmp); - addcolor(cval, ctmp); + copyscolor(sctmp, np->tdiff); + dtmp = -ldot * omega * (1./PI); + scalescolor(sctmp, dtmp); + saddscolor(scval, sctmp); } if (ambRayInPmap(np->pr)) return; /* specular already in photon map */ /* * Compute specular scattering coefficient using BSDF */ - if (!direct_specular_OK(ctmp, ldir, omega, np)) + if (!direct_specular_OK(sctmp, ldir, omega, np)) return; /* full pattern on transmission */ - multcolor(ctmp, np->pr->pcol); + smultscolor(sctmp, np->pr->pcol); dtmp = -ldot * omega; - scalecolor(ctmp, dtmp); - addcolor(cval, ctmp); + scalescolor(sctmp, dtmp); + saddscolor(scval, sctmp); } /* Sample separate BSDF component */ @@ -505,7 +487,7 @@ sample_sdcomp(BSDFDAT *ndp, SDComponent *dcp, int xmit { const int hasthru = (xmit && !(ndp->pr->crtype & (SPECULAR|AMBIENT)) - && bright(ndp->cthru) > FTINY); + && sintens(ndp->cthru) > FTINY); int nstarget = 1; int nsent = 0; int n; @@ -550,11 +532,11 @@ sample_sdcomp(BSDFDAT *ndp, SDComponent *dcp, int xmit bsv.cieY /= (double)nstarget; cvt_sdcolor(sr.rcoef, &bsv); /* use sample color */ if (xmit) /* apply pattern on transmit */ - multcolor(sr.rcoef, ndp->pr->pcol); - if (rayorigin(&sr, SPECULAR, ndp->pr, sr.rcoef) < 0) { + smultscolor(sr.rcoef, ndp->pr->pcol); + if (rayorigin(&sr, xmit ? TSPECULAR : RSPECULAR, ndp->pr, sr.rcoef) < 0) { if (!n & (nstarget > 1)) { n = nstarget; /* avoid infinitue loop */ - nstarget = nstarget*sr.rweight/minweight; + nstarget = nstarget*sr.rweight/(minweight + 1e-20); if (n == nstarget) break; n = -1; /* moved target */ } @@ -563,8 +545,8 @@ sample_sdcomp(BSDFDAT *ndp, SDComponent *dcp, int xmit if (xmit && ndp->thick != 0) /* need to offset origin? */ VSUM(sr.rorg, sr.rorg, ndp->pr->ron, -ndp->thick); rayvalue(&sr); /* send & evaluate sample */ - multcolor(sr.rcol, sr.rcoef); - addcolor(ndp->pr->rcol, sr.rcol); + smultscolor(sr.rcol, sr.rcoef); + saddscolor(ndp->pr->rcol, sr.rcol); ++nsent; } return(nsent); @@ -576,7 +558,7 @@ sample_sdf(BSDFDAT *ndp, int sflags) { int hasthru = (sflags == SDsampSpT && !(ndp->pr->crtype & (SPECULAR|AMBIENT)) - && bright(ndp->cthru) > FTINY); + && sintens(ndp->cthru) > FTINY); int n, ntotal = 0; double b = 0; SDSpectralDF *dfp; @@ -595,7 +577,7 @@ sample_sdf(BSDFDAT *ndp, int sflags) else dfp = ndp->sd->rb; } - setcolor(unsc, 0, 0, 0); + scolorblack(unsc); if (dfp == NULL) /* no specular component? */ return(0); @@ -604,11 +586,11 @@ sample_sdf(BSDFDAT *ndp, int sflags) if (rayorigin(&tr, TRANS, ndp->pr, ndp->cthru) == 0) { VCOPY(tr.rdir, ndp->pr->rdir); rayvalue(&tr); - multcolor(tr.rcol, tr.rcoef); - addcolor(ndp->pr->rcol, tr.rcol); + smultscolor(tr.rcol, tr.rcoef); + saddscolor(ndp->pr->rcol, tr.rcol); ndp->pr->rxt = ndp->pr->rot + raydistance(&tr); ++ntotal; - b = bright(ndp->cthru); + b = pbright(ndp->cthru); } else hasthru = 0; } @@ -618,15 +600,15 @@ sample_sdf(BSDFDAT *ndp, int sflags) FVECT vjit; bsdf_jitter(vjit, ndp, ndp->sr_vpsa[1]); b = SDdirectHemi(vjit, sflags, ndp->sd) - b; - if (b < 0) b = 0; + b *= (b > 0); } if (b <= specthresh+FTINY) { /* below sampling threshold? */ if (b > FTINY) { /* XXX no color from BSDF */ if (sflags == SDsampSpT) { - copycolor(unsc, ndp->pr->pcol); - scalecolor(unsc, b); + copyscolor(unsc, ndp->pr->pcol); + scalescolor(unsc, b); } else /* no pattern on reflection */ - setcolor(unsc, b, b, b); + setscolor(unsc, b, b, b); } return(ntotal); } @@ -646,7 +628,7 @@ m_bsdf(OBJREC *m, RAY *r) { int hasthick = (m->otype == MAT_BSDF); int hitfront; - COLOR ctmp; + SCOLOR sctmp; SDError ec; FVECT upvec, vtmp; MFUNC *mf; @@ -694,33 +676,33 @@ m_bsdf(OBJREC *m, RAY *r) if (hitfront) { cvt_sdcolor(nd.rdiff, &nd.sd->rLambFront); if (m->oargs.nfargs >= 3) { - setcolor(ctmp, m->oargs.farg[0], + setscolor(sctmp, m->oargs.farg[0], m->oargs.farg[1], m->oargs.farg[2]); - addcolor(nd.rdiff, ctmp); + saddscolor(nd.rdiff, sctmp); } cvt_sdcolor(nd.tdiff, &nd.sd->tLambFront); } else { cvt_sdcolor(nd.rdiff, &nd.sd->rLambBack); if (m->oargs.nfargs >= 6) { - setcolor(ctmp, m->oargs.farg[3], + setscolor(sctmp, m->oargs.farg[3], m->oargs.farg[4], m->oargs.farg[5]); - addcolor(nd.rdiff, ctmp); + saddscolor(nd.rdiff, sctmp); } cvt_sdcolor(nd.tdiff, &nd.sd->tLambBack); } if (m->oargs.nfargs >= 9) { /* add diffuse transmittance? */ - setcolor(ctmp, m->oargs.farg[6], + setscolor(sctmp, m->oargs.farg[6], m->oargs.farg[7], m->oargs.farg[8]); - addcolor(nd.tdiff, ctmp); + saddscolor(nd.tdiff, sctmp); } /* get modifiers */ raytexture(r, m->omod); /* modify diffuse values */ - multcolor(nd.rdiff, r->pcol); - multcolor(nd.tdiff, r->pcol); + smultscolor(nd.rdiff, r->pcol); + smultscolor(nd.tdiff, r->pcol); /* get up vector */ upvec[0] = evalue(mf->ep[hasthick+0]); upvec[1] = evalue(mf->ep[hasthick+1]); @@ -748,8 +730,8 @@ m_bsdf(OBJREC *m, RAY *r) SDfreeCache(nd.sd); return(1); } - setcolor(nd.cthru, 0, 0, 0); /* consider through component */ - setcolor(nd.cthru_surr, 0, 0, 0); + scolorblack(nd.cthru); /* consider through component */ + scolorblack(nd.cthru_surr); if (m->otype == MAT_ABSDF) { compute_through(&nd); if (r->crtype & SHADOW) { @@ -759,8 +741,8 @@ m_bsdf(OBJREC *m, RAY *r) return(1); /* no through component */ VCOPY(tr.rdir, r->rdir); rayvalue(&tr); /* transmit with scaling */ - multcolor(tr.rcol, tr.rcoef); - copycolor(r->rcol, tr.rcol); + smultscolor(tr.rcol, tr.rcoef); + copyscolor(r->rcol, tr.rcol); return(1); /* we're done */ } } @@ -783,39 +765,31 @@ m_bsdf(OBJREC *m, RAY *r) /* sample transmission */ sample_sdf(&nd, SDsampSpT); /* compute indirect diffuse */ - copycolor(ctmp, nd.rdiff); - addcolor(ctmp, nd.runsamp); - if (bright(ctmp) > FTINY) { /* ambient from reflection */ - if (!hitfront) - flipsurface(r); - multambient(ctmp, r, nd.pnorm); - addcolor(r->rcol, ctmp); - if (!hitfront) - flipsurface(r); + copyscolor(sctmp, nd.rdiff); + saddscolor(sctmp, nd.runsamp); + if (sintens(sctmp) > FTINY) { /* ambient from reflection */ + multambient(sctmp, r, nd.pnorm); + saddscolor(r->rcol, sctmp); } - copycolor(ctmp, nd.tdiff); - addcolor(ctmp, nd.tunsamp); - if (bright(ctmp) > FTINY) { /* ambient from other side */ + copyscolor(sctmp, nd.tdiff); + saddscolor(sctmp, nd.tunsamp); + if (sintens(sctmp) > FTINY) { /* ambient from other side */ FVECT bnorm; - if (hitfront) - flipsurface(r); bnorm[0] = -nd.pnorm[0]; bnorm[1] = -nd.pnorm[1]; bnorm[2] = -nd.pnorm[2]; if (nd.thick != 0) { /* proxy with offset? */ VCOPY(vtmp, r->rop); VSUM(r->rop, vtmp, r->ron, nd.thick); - multambient(ctmp, r, bnorm); + multambient(sctmp, r, bnorm); VCOPY(r->rop, vtmp); } else - multambient(ctmp, r, bnorm); - addcolor(r->rcol, ctmp); - if (hitfront) - flipsurface(r); + multambient(sctmp, r, bnorm); + saddscolor(r->rcol, sctmp); } /* add direct component */ - if ((bright(nd.tdiff) <= FTINY) & (nd.sd->tf == NULL) & - (nd.sd->tb == NULL)) { + if ((nd.sd->tf == NULL) & (nd.sd->tb == NULL) && + sintens(nd.tdiff) <= FTINY) { direct(r, dir_brdf, &nd); /* reflection only */ } else if (nd.thick == 0) { direct(r, dir_bsdf, &nd); /* thin surface scattering */