| 80 |
|
register NORMDAT *np = nnp; |
| 81 |
|
double ldot; |
| 82 |
|
double lrdiff, ltdiff; |
| 83 |
< |
double dtmp, d2; |
| 83 |
> |
double dtmp, d2, d3, d4; |
| 84 |
|
FVECT vtmp; |
| 85 |
|
COLOR ctmp; |
| 86 |
|
|
| 115 |
|
if (ldot > FTINY && (np->specfl&(SP_REFL|SP_PURE)) == SP_REFL) { |
| 116 |
|
/* |
| 117 |
|
* Compute specular reflection coefficient using |
| 118 |
< |
* gaussian distribution model. |
| 118 |
> |
* Gaussian distribution model. |
| 119 |
|
*/ |
| 120 |
|
/* roughness */ |
| 121 |
|
dtmp = np->alpha2; |
| 128 |
|
vtmp[2] = ldir[2] - np->rp->rdir[2]; |
| 129 |
|
d2 = DOT(vtmp, np->pnorm); |
| 130 |
|
d2 *= d2; |
| 131 |
< |
d2 = (DOT(vtmp,vtmp) - d2) / d2; |
| 132 |
< |
/* gaussian */ |
| 133 |
< |
dtmp = exp(-d2/dtmp)/(4.*PI * np->pdot * dtmp); |
| 131 |
> |
d3 = DOT(vtmp,vtmp); |
| 132 |
> |
d4 = (d3 - d2) / d2; |
| 133 |
> |
/* new W-G-M-D model */ |
| 134 |
> |
dtmp = exp(-d4/dtmp) * d3 / (PI * d2*d2 * dtmp); |
| 135 |
|
/* worth using? */ |
| 136 |
|
if (dtmp > FTINY) { |
| 137 |
|
copycolor(ctmp, np->scolor); |
| 138 |
< |
dtmp *= omega; |
| 138 |
> |
dtmp *= ldot * omega; |
| 139 |
|
scalecolor(ctmp, dtmp); |
| 140 |
|
addcolor(cval, ctmp); |
| 141 |
|
} |
| 156 |
|
*/ |
| 157 |
|
/* roughness + source */ |
| 158 |
|
dtmp = np->alpha2 + omega*(1.0/PI); |
| 159 |
< |
/* gaussian */ |
| 160 |
< |
dtmp = exp((2.*DOT(np->prdir,ldir)-2.)/dtmp) / |
| 160 |
< |
(PI*np->pdot*dtmp); |
| 159 |
> |
/* Gaussian */ |
| 160 |
> |
dtmp = exp((2.*DOT(np->prdir,ldir)-2.)/dtmp)/(PI*dtmp); |
| 161 |
|
/* worth using? */ |
| 162 |
|
if (dtmp > FTINY) { |
| 163 |
|
copycolor(ctmp, np->mcolor); |
| 164 |
< |
dtmp *= np->tspec * omega; |
| 164 |
> |
dtmp *= np->tspec * omega * sqrt(-ldot/np->pdot); |
| 165 |
|
scalecolor(ctmp, dtmp); |
| 166 |
|
addcolor(cval, ctmp); |
| 167 |
|
} |
| 294 |
|
if (!(nd.specfl & SP_PURE) && specthresh >= nd.rspec-FTINY) |
| 295 |
|
nd.specfl |= SP_RBLT; |
| 296 |
|
/* compute reflected ray */ |
| 297 |
< |
for (i = 0; i < 3; i++) |
| 298 |
< |
nd.vrefl[i] = r->rdir[i] + 2.*nd.pdot*nd.pnorm[i]; |
| 297 |
> |
VSUM(nd.vrefl, r->rdir, nd.pnorm, 2.*nd.pdot); |
| 298 |
|
/* penetration? */ |
| 299 |
|
if (hastexture && DOT(nd.vrefl, r->ron) <= FTINY) |
| 300 |
< |
for (i = 0; i < 3; i++) /* safety measure */ |
| 301 |
< |
nd.vrefl[i] = r->rdir[i] + 2.*r->rod*r->ron[i]; |
| 300 |
> |
VSUM(nd.vrefl, r->rdir, r->ron, 2.*r->rod); |
| 301 |
> |
checknorm(nd.vrefl); |
| 302 |
|
} |
| 303 |
|
/* reflected ray */ |
| 304 |
|
if ((nd.specfl&(SP_REFL|SP_PURE|SP_RBLT)) == (SP_REFL|SP_PURE)) { |
| 364 |
|
|
| 365 |
|
|
| 366 |
|
static void |
| 367 |
< |
gaussamp( /* sample gaussian specular */ |
| 367 |
> |
gaussamp( /* sample Gaussian specular */ |
| 368 |
|
RAY *r, |
| 369 |
|
register NORMDAT *np |
| 370 |
|
) |
| 373 |
|
FVECT u, v, h; |
| 374 |
|
double rv[2]; |
| 375 |
|
double d, sinp, cosp; |
| 376 |
< |
int niter; |
| 376 |
> |
COLOR scol; |
| 377 |
> |
int niter, ns2go; |
| 378 |
|
register int i; |
| 379 |
|
/* quick test */ |
| 380 |
|
if ((np->specfl & (SP_REFL|SP_RBLT)) != SP_REFL && |
| 392 |
|
/* compute reflection */ |
| 393 |
|
if ((np->specfl & (SP_REFL|SP_RBLT)) == SP_REFL && |
| 394 |
|
rayorigin(&sr, SPECULAR, r, np->scolor) == 0) { |
| 395 |
+ |
copycolor(scol, np->scolor); |
| 396 |
+ |
ns2go = 1; |
| 397 |
+ |
if (specjitter > 1.5) { /* multiple samples? */ |
| 398 |
+ |
ns2go = specjitter*r->rweight + .5; |
| 399 |
+ |
if (sr.rweight <= minweight*ns2go) |
| 400 |
+ |
ns2go = sr.rweight/minweight; |
| 401 |
+ |
if (ns2go > 1) { |
| 402 |
+ |
d = 1./ns2go; |
| 403 |
+ |
scalecolor(scol, d); |
| 404 |
+ |
sr.rweight *= d; |
| 405 |
+ |
} else |
| 406 |
+ |
ns2go = 1; |
| 407 |
+ |
} |
| 408 |
|
dimlist[ndims++] = (int)np->mp; |
| 409 |
< |
for (niter = 0; niter < MAXITER; niter++) { |
| 410 |
< |
if (niter) |
| 409 |
> |
for (niter = ns2go*MAXITER; (ns2go > 0) & (niter > 0); niter--) { |
| 410 |
> |
if (specjitter > 1.5) |
| 411 |
|
d = frandom(); |
| 412 |
|
else |
| 413 |
|
d = urand(ilhash(dimlist,ndims)+samplendx); |
| 415 |
|
d = 2.0*PI * rv[0]; |
| 416 |
|
cosp = tcos(d); |
| 417 |
|
sinp = tsin(d); |
| 418 |
< |
rv[1] = 1.0 - specjitter*rv[1]; |
| 418 |
> |
if ((0. <= specjitter) & (specjitter < 1.)) |
| 419 |
> |
rv[1] = 1.0 - specjitter*rv[1]; |
| 420 |
|
if (rv[1] <= FTINY) |
| 421 |
|
d = 1.0; |
| 422 |
|
else |
| 424 |
|
for (i = 0; i < 3; i++) |
| 425 |
|
h[i] = np->pnorm[i] + d*(cosp*u[i] + sinp*v[i]); |
| 426 |
|
d = -2.0 * DOT(h, r->rdir) / (1.0 + d*d); |
| 427 |
< |
for (i = 0; i < 3; i++) |
| 428 |
< |
sr.rdir[i] = r->rdir[i] + d*h[i]; |
| 429 |
< |
if (DOT(sr.rdir, r->ron) > FTINY) { |
| 430 |
< |
rayvalue(&sr); |
| 431 |
< |
multcolor(sr.rcol, sr.rcoef); |
| 432 |
< |
addcolor(r->rcol, sr.rcol); |
| 433 |
< |
break; |
| 427 |
> |
if (d <= np->pdot + FTINY) |
| 428 |
> |
continue; |
| 429 |
> |
VSUM(sr.rdir, r->rdir, h, d); |
| 430 |
> |
if (DOT(sr.rdir, r->ron) <= FTINY) |
| 431 |
> |
continue; |
| 432 |
> |
checknorm(sr.rdir); |
| 433 |
> |
if (specjitter > 1.5) { /* adjusted W-G-M-D weight */ |
| 434 |
> |
d = 2.*(1. - np->pdot/d); |
| 435 |
> |
copycolor(sr.rcoef, scol); |
| 436 |
> |
scalecolor(sr.rcoef, d); |
| 437 |
> |
rayclear(&sr); |
| 438 |
|
} |
| 439 |
+ |
rayvalue(&sr); |
| 440 |
+ |
multcolor(sr.rcol, sr.rcoef); |
| 441 |
+ |
addcolor(r->rcol, sr.rcol); |
| 442 |
+ |
--ns2go; |
| 443 |
|
} |
| 444 |
|
ndims--; |
| 445 |
|
} |
| 448 |
|
scalecolor(sr.rcoef, np->tspec); |
| 449 |
|
if ((np->specfl & (SP_TRAN|SP_TBLT)) == SP_TRAN && |
| 450 |
|
rayorigin(&sr, SPECULAR, r, sr.rcoef) == 0) { |
| 451 |
+ |
ns2go = 1; |
| 452 |
+ |
if (specjitter > 1.5) { /* multiple samples? */ |
| 453 |
+ |
ns2go = specjitter*r->rweight + .5; |
| 454 |
+ |
if (sr.rweight <= minweight*ns2go) |
| 455 |
+ |
ns2go = sr.rweight/minweight; |
| 456 |
+ |
if (ns2go > 1) { |
| 457 |
+ |
d = 1./ns2go; |
| 458 |
+ |
scalecolor(sr.rcoef, d); |
| 459 |
+ |
sr.rweight *= d; |
| 460 |
+ |
} else |
| 461 |
+ |
ns2go = 1; |
| 462 |
+ |
} |
| 463 |
|
dimlist[ndims++] = (int)np->mp; |
| 464 |
< |
for (niter = 0; niter < MAXITER; niter++) { |
| 465 |
< |
if (niter) |
| 464 |
> |
for (niter = ns2go*MAXITER; (ns2go > 0) & (niter > 0); niter--) { |
| 465 |
> |
if (specjitter > 1.5) |
| 466 |
|
d = frandom(); |
| 467 |
|
else |
| 468 |
|
d = urand(ilhash(dimlist,ndims)+1823+samplendx); |
| 470 |
|
d = 2.0*PI * rv[0]; |
| 471 |
|
cosp = tcos(d); |
| 472 |
|
sinp = tsin(d); |
| 473 |
< |
rv[1] = 1.0 - specjitter*rv[1]; |
| 473 |
> |
if ((0. <= specjitter) & (specjitter < 1.)) |
| 474 |
> |
rv[1] = 1.0 - specjitter*rv[1]; |
| 475 |
|
if (rv[1] <= FTINY) |
| 476 |
|
d = 1.0; |
| 477 |
|
else |
| 478 |
|
d = sqrt( np->alpha2 * -log(rv[1]) ); |
| 479 |
|
for (i = 0; i < 3; i++) |
| 480 |
|
sr.rdir[i] = np->prdir[i] + d*(cosp*u[i] + sinp*v[i]); |
| 481 |
< |
if (DOT(sr.rdir, r->ron) < -FTINY) { |
| 482 |
< |
normalize(sr.rdir); /* OK, normalize */ |
| 483 |
< |
rayvalue(&sr); |
| 484 |
< |
multcolor(sr.rcol, sr.rcoef); |
| 485 |
< |
addcolor(r->rcol, sr.rcol); |
| 486 |
< |
break; |
| 487 |
< |
} |
| 481 |
> |
if (DOT(sr.rdir, r->ron) >= -FTINY) |
| 482 |
> |
continue; |
| 483 |
> |
normalize(sr.rdir); /* OK, normalize */ |
| 484 |
> |
if (specjitter > 1.5) /* multi-sampling */ |
| 485 |
> |
rayclear(&sr); |
| 486 |
> |
rayvalue(&sr); |
| 487 |
> |
multcolor(sr.rcol, sr.rcoef); |
| 488 |
> |
addcolor(r->rcol, sr.rcol); |
| 489 |
> |
--ns2go; |
| 490 |
|
} |
| 491 |
|
ndims--; |
| 492 |
|
} |