96 |
|
normalize(vres); |
97 |
|
} |
98 |
|
|
99 |
+ |
/* Evaluate BSDF for direct component, returning true if OK to proceed */ |
100 |
+ |
static int |
101 |
+ |
direct_bsdf_OK(COLOR cval, FVECT ldir, BSDFDAT *ndp) |
102 |
+ |
{ |
103 |
+ |
FVECT vsrc, vjit; |
104 |
+ |
SDValue sv; |
105 |
+ |
SDError ec; |
106 |
+ |
/* transform source direction */ |
107 |
+ |
if (SDmapDir(vsrc, ndp->toloc, ldir) != SDEnone) |
108 |
+ |
return(0); |
109 |
+ |
/* jitter query direction */ |
110 |
+ |
bsdf_jitter(vjit, ndp); |
111 |
+ |
/* avoid indirect over-counting */ |
112 |
+ |
if (ndp->thick != .0 && ndp->pr->crtype & (SPECULAR|AMBIENT) && |
113 |
+ |
vsrc[2] > .0 ^ vjit[2] > .0) { |
114 |
+ |
double dx = vsrc[0] + vjit[0]; |
115 |
+ |
double dy = vsrc[1] + vjit[1]; |
116 |
+ |
if (dx*dx + dy*dy <= ndp->sr_vpsa*ndp->sr_vpsa) |
117 |
+ |
return(0); |
118 |
+ |
} |
119 |
+ |
ec = SDevalBSDF(&sv, vjit, vsrc, ndp->sd); |
120 |
+ |
if (ec) |
121 |
+ |
objerror(ndp->mp, USER, transSDError(ec)); |
122 |
+ |
|
123 |
+ |
if (sv.cieY <= FTINY) /* not worth using? */ |
124 |
+ |
return(0); |
125 |
+ |
/* else we're good to go */ |
126 |
+ |
cvt_sdcolor(cval, &sv); |
127 |
+ |
return(1); |
128 |
+ |
} |
129 |
+ |
|
130 |
|
/* Compute source contribution for BSDF (reflected & transmitted) */ |
131 |
|
static void |
132 |
|
dir_bsdf( |
137 |
|
) |
138 |
|
{ |
139 |
|
BSDFDAT *np = (BSDFDAT *)nnp; |
109 |
– |
SDError ec; |
110 |
– |
SDValue sv; |
111 |
– |
FVECT vsrc; |
112 |
– |
FVECT vjit; |
140 |
|
double ldot; |
141 |
|
double dtmp; |
142 |
|
COLOR ctmp; |
168 |
|
/* |
169 |
|
* Compute scattering coefficient using BSDF. |
170 |
|
*/ |
171 |
< |
if (SDmapDir(vsrc, np->toloc, ldir) != SDEnone) |
171 |
> |
if (!direct_bsdf_OK(ctmp, ldir, np)) |
172 |
|
return; |
146 |
– |
bsdf_jitter(vjit, np); |
147 |
– |
ec = SDevalBSDF(&sv, vjit, vsrc, np->sd); |
148 |
– |
if (ec) |
149 |
– |
objerror(np->mp, USER, transSDError(ec)); |
150 |
– |
|
151 |
– |
if (sv.cieY <= FTINY) /* not worth using? */ |
152 |
– |
return; |
153 |
– |
cvt_sdcolor(ctmp, &sv); |
173 |
|
if (ldot > .0) { /* pattern only diffuse reflection */ |
174 |
|
COLOR ctmp1, ctmp2; |
175 |
|
dtmp = (np->pr->rod > .0) ? np->sd->rLambFront.cieY |
176 |
|
: np->sd->rLambBack.cieY; |
177 |
< |
dtmp /= PI * sv.cieY; /* diffuse fraction */ |
177 |
> |
/* diffuse fraction */ |
178 |
> |
dtmp /= PI * bright(ctmp); |
179 |
|
copycolor(ctmp2, np->pr->pcol); |
180 |
|
scalecolor(ctmp2, dtmp); |
181 |
|
setcolor(ctmp1, 1.-dtmp, 1.-dtmp, 1.-dtmp); |
200 |
|
) |
201 |
|
{ |
202 |
|
BSDFDAT *np = (BSDFDAT *)nnp; |
183 |
– |
SDError ec; |
184 |
– |
SDValue sv; |
185 |
– |
FVECT vsrc; |
186 |
– |
FVECT vjit; |
203 |
|
double ldot; |
204 |
|
double dtmp; |
205 |
|
COLOR ctmp, ctmp1, ctmp2; |
223 |
|
/* |
224 |
|
* Compute reflection coefficient using BSDF. |
225 |
|
*/ |
226 |
< |
if (SDmapDir(vsrc, np->toloc, ldir) != SDEnone) |
226 |
> |
if (!direct_bsdf_OK(ctmp, ldir, np)) |
227 |
|
return; |
212 |
– |
bsdf_jitter(vjit, np); |
213 |
– |
ec = SDevalBSDF(&sv, vjit, vsrc, np->sd); |
214 |
– |
if (ec) |
215 |
– |
objerror(np->mp, USER, transSDError(ec)); |
216 |
– |
|
217 |
– |
if (sv.cieY <= FTINY) /* not worth using? */ |
218 |
– |
return; |
219 |
– |
cvt_sdcolor(ctmp, &sv); |
228 |
|
/* pattern only diffuse reflection */ |
229 |
|
dtmp = (np->pr->rod > .0) ? np->sd->rLambFront.cieY |
230 |
|
: np->sd->rLambBack.cieY; |
231 |
< |
dtmp /= PI * sv.cieY; /* diffuse fraction */ |
231 |
> |
dtmp /= PI * bright(ctmp); /* diffuse fraction */ |
232 |
|
copycolor(ctmp2, np->pr->pcol); |
233 |
|
scalecolor(ctmp2, dtmp); |
234 |
|
setcolor(ctmp1, 1.-dtmp, 1.-dtmp, 1.-dtmp); |
249 |
|
) |
250 |
|
{ |
251 |
|
BSDFDAT *np = (BSDFDAT *)nnp; |
244 |
– |
SDError ec; |
245 |
– |
SDValue sv; |
246 |
– |
FVECT vsrc; |
247 |
– |
FVECT vjit; |
252 |
|
double ldot; |
253 |
|
double dtmp; |
254 |
|
COLOR ctmp; |
272 |
|
/* |
273 |
|
* Compute scattering coefficient using BSDF. |
274 |
|
*/ |
275 |
< |
if (SDmapDir(vsrc, np->toloc, ldir) != SDEnone) |
275 |
> |
if (!direct_bsdf_OK(ctmp, ldir, np)) |
276 |
|
return; |
273 |
– |
bsdf_jitter(vjit, np); |
274 |
– |
ec = SDevalBSDF(&sv, vjit, vsrc, np->sd); |
275 |
– |
if (ec) |
276 |
– |
objerror(np->mp, USER, transSDError(ec)); |
277 |
– |
|
278 |
– |
if (sv.cieY <= FTINY) /* not worth using? */ |
279 |
– |
return; |
280 |
– |
cvt_sdcolor(ctmp, &sv); |
277 |
|
/* full pattern on transmission */ |
278 |
|
multcolor(ctmp, np->pr->pcol); |
279 |
|
dtmp = -ldot * omega; |
397 |
|
int |
398 |
|
m_bsdf(OBJREC *m, RAY *r) |
399 |
|
{ |
400 |
+ |
int hitfront; |
401 |
|
COLOR ctmp; |
402 |
|
SDError ec; |
403 |
|
FVECT upvec, vtmp; |
407 |
|
if ((m->oargs.nsargs < 6) | (m->oargs.nfargs > 9) | |
408 |
|
(m->oargs.nfargs % 3)) |
409 |
|
objerror(m, USER, "bad # arguments"); |
410 |
< |
|
410 |
> |
/* record surface struck */ |
411 |
> |
hitfront = (r->rod > .0); |
412 |
|
/* load cal file */ |
413 |
|
mf = getfunc(m, 5, 0x1d, 1); |
414 |
|
/* get thickness */ |
422 |
|
return(1); /* or shadow */ |
423 |
|
} |
424 |
|
/* check other rays to pass */ |
425 |
< |
if (nd.thick != 0 && (!(r->crtype & (SPECULAR|AMBIENT)) || |
426 |
< |
nd.thick > .0 ^ r->rod > .0)) { |
425 |
> |
if (nd.thick != .0 && (!(r->crtype & (SPECULAR|AMBIENT)) || |
426 |
> |
nd.thick > .0 ^ hitfront)) { |
427 |
|
raytrans(r); /* hide our proxy */ |
428 |
|
return(1); |
429 |
|
} |
430 |
|
/* get BSDF data */ |
431 |
|
nd.sd = loadBSDF(m->oargs.sarg[1]); |
432 |
|
/* diffuse reflectance */ |
433 |
< |
if (r->rod > .0) { |
433 |
> |
if (hitfront) { |
434 |
|
if (m->oargs.nfargs < 3) |
435 |
|
setcolor(nd.rdiff, .0, .0, .0); |
436 |
|
else |
495 |
|
SDfreeCache(nd.sd); |
496 |
|
return(1); |
497 |
|
} |
498 |
< |
if (r->rod < .0) { /* perturb normal towards hit */ |
498 |
> |
if (!hitfront) { /* perturb normal towards hit */ |
499 |
|
nd.pnorm[0] = -nd.pnorm[0]; |
500 |
|
nd.pnorm[1] = -nd.pnorm[1]; |
501 |
|
nd.pnorm[2] = -nd.pnorm[2]; |
508 |
|
copycolor(ctmp, nd.rdiff); |
509 |
|
addcolor(ctmp, nd.runsamp); |
510 |
|
if (bright(ctmp) > FTINY) { /* ambient from reflection */ |
511 |
< |
if (r->rod < .0) |
511 |
> |
if (!hitfront) |
512 |
|
flipsurface(r); |
513 |
|
multambient(ctmp, r, nd.pnorm); |
514 |
|
addcolor(r->rcol, ctmp); |
515 |
< |
if (r->rod < .0) |
515 |
> |
if (!hitfront) |
516 |
|
flipsurface(r); |
517 |
|
} |
518 |
|
copycolor(ctmp, nd.tdiff); |
519 |
|
addcolor(ctmp, nd.tunsamp); |
520 |
|
if (bright(ctmp) > FTINY) { /* ambient from other side */ |
521 |
|
FVECT bnorm; |
522 |
< |
if (r->rod > .0) |
522 |
> |
if (hitfront) |
523 |
|
flipsurface(r); |
524 |
|
bnorm[0] = -nd.pnorm[0]; |
525 |
|
bnorm[1] = -nd.pnorm[1]; |
532 |
|
} else |
533 |
|
multambient(ctmp, r, bnorm); |
534 |
|
addcolor(r->rcol, ctmp); |
535 |
< |
if (r->rod > .0) |
535 |
> |
if (hitfront) |
536 |
|
flipsurface(r); |
537 |
|
} |
538 |
|
/* add direct component */ |
544 |
|
direct(r, dir_brdf, &nd); /* reflection first */ |
545 |
|
VCOPY(vtmp, r->rop); /* offset for transmitted */ |
546 |
|
VSUM(r->rop, vtmp, r->ron, -nd.thick); |
547 |
< |
direct(r, dir_btdf, &nd); |
547 |
> |
direct(r, dir_btdf, &nd); /* separate transmission */ |
548 |
|
VCOPY(r->rop, vtmp); |
549 |
|
} |
550 |
|
/* clean up */ |