96 |
|
|
97 |
|
#define cvt_sdcolor(cv, svp) ccy2rgb(&(svp)->spec, (svp)->cieY, cv) |
98 |
|
|
99 |
+ |
typedef struct { |
100 |
+ |
double vy; /* brightness (for sorting) */ |
101 |
+ |
FVECT tdir; /* through sample direction (normalized) */ |
102 |
+ |
COLOR vcol; /* BTDF color */ |
103 |
+ |
} PEAKSAMP; /* BTDF peak sample */ |
104 |
+ |
|
105 |
+ |
/* Comparison function to put near-peak values in descending order */ |
106 |
+ |
static int |
107 |
+ |
cmp_psamp(const void *p1, const void *p2) |
108 |
+ |
{ |
109 |
+ |
double diff = (*(const PEAKSAMP *)p1).vy - (*(const PEAKSAMP *)p2).vy; |
110 |
+ |
if (diff > 0) return(-1); |
111 |
+ |
if (diff < 0) return(1); |
112 |
+ |
return(0); |
113 |
+ |
} |
114 |
+ |
|
115 |
|
/* Compute "through" component color for MAT_ABSDF */ |
116 |
|
static void |
117 |
|
compute_through(BSDFDAT *ndp) |
118 |
|
{ |
119 |
< |
#define NDIR2CHECK 13 |
119 |
> |
#define NDIR2CHECK 29 |
120 |
|
static const float dir2check[NDIR2CHECK][2] = { |
121 |
< |
{0, 0}, |
122 |
< |
{-0.8, 0}, |
123 |
< |
{0, 0.8}, |
124 |
< |
{0, -0.8}, |
125 |
< |
{0.8, 0}, |
126 |
< |
{-0.8, 0.8}, |
127 |
< |
{-0.8, -0.8}, |
128 |
< |
{0.8, 0.8}, |
129 |
< |
{0.8, -0.8}, |
130 |
< |
{-1.6, 0}, |
115 |
< |
{0, 1.6}, |
116 |
< |
{0, -1.6}, |
117 |
< |
{1.6, 0}, |
121 |
> |
{0, 0}, {-0.6, 0}, {0, 0.6}, |
122 |
> |
{0, -0.6}, {0.6, 0}, {-0.6, 0.6}, |
123 |
> |
{-0.6, -0.6}, {0.6, 0.6}, {0.6, -0.6}, |
124 |
> |
{-1.2, 0}, {0, 1.2}, {0, -1.2}, |
125 |
> |
{1.2, 0}, {-1.2, 1.2}, {-1.2, -1.2}, |
126 |
> |
{1.2, 1.2}, {1.2, -1.2}, {-1.8, 0}, |
127 |
> |
{0, 1.8}, {0, -1.8}, {1.8, 0}, |
128 |
> |
{-1.8, 1.8}, {-1.8, -1.8}, {1.8, 1.8}, |
129 |
> |
{1.8, -1.8}, {-2.4, 0}, {0, 2.4}, |
130 |
> |
{0, -2.4}, {2.4, 0}, |
131 |
|
}; |
132 |
< |
const double peak_over = 1.3 + .4*frandom(); /* jitter threshold */ |
132 |
> |
const double peak_over = 1.5; |
133 |
> |
PEAKSAMP psamp[NDIR2CHECK]; |
134 |
|
SDSpectralDF *dfp; |
135 |
|
FVECT pdir; |
136 |
|
double tomega, srchrad; |
137 |
< |
COLOR vpeak, vsum; |
138 |
< |
int i; |
137 |
> |
double tomsum; |
138 |
> |
COLOR vpeak; |
139 |
> |
double vypeak, vysum; |
140 |
> |
int i, ns, ntot; |
141 |
|
SDError ec; |
142 |
|
|
143 |
|
if (ndp->pr->rod > 0) |
149 |
|
return; /* no specular transmission */ |
150 |
|
if (bright(ndp->pr->pcol) <= FTINY) |
151 |
|
return; /* pattern is black, here */ |
152 |
< |
srchrad = sqrt(dfp->minProjSA); /* else search for peak */ |
153 |
< |
setcolor(vpeak, 0, 0, 0); |
138 |
< |
setcolor(vsum, 0, 0, 0); |
139 |
< |
pdir[2] = 0.0; |
152 |
> |
srchrad = sqrt(dfp->minProjSA); /* else evaluate peak */ |
153 |
> |
vysum = 0; |
154 |
|
for (i = 0; i < NDIR2CHECK; i++) { |
141 |
– |
FVECT tdir; |
155 |
|
SDValue sv; |
156 |
< |
COLOR vcol; |
157 |
< |
tdir[0] = -ndp->vray[0] + dir2check[i][0]*srchrad; |
158 |
< |
tdir[1] = -ndp->vray[1] + dir2check[i][1]*srchrad; |
159 |
< |
tdir[2] = -ndp->vray[2]; |
160 |
< |
normalize(tdir); |
148 |
< |
ec = SDevalBSDF(&sv, tdir, ndp->vray, ndp->sd); |
156 |
> |
psamp[i].tdir[0] = -ndp->vray[0] + dir2check[i][0]*srchrad; |
157 |
> |
psamp[i].tdir[1] = -ndp->vray[1] + dir2check[i][1]*srchrad; |
158 |
> |
psamp[i].tdir[2] = -ndp->vray[2]; |
159 |
> |
normalize(psamp[i].tdir); |
160 |
> |
ec = SDevalBSDF(&sv, psamp[i].tdir, ndp->vray, ndp->sd); |
161 |
|
if (ec) |
162 |
|
goto baderror; |
163 |
< |
cvt_sdcolor(vcol, &sv); |
164 |
< |
addcolor(vsum, vcol); |
165 |
< |
if (sv.cieY > bright(vpeak)) { |
166 |
< |
copycolor(vpeak, vcol); |
167 |
< |
VCOPY(pdir, tdir); |
163 |
> |
cvt_sdcolor(psamp[i].vcol, &sv); |
164 |
> |
vysum += psamp[i].vy = sv.cieY; |
165 |
> |
} |
166 |
> |
if (vysum <= FTINY) /* zero neighborhood? */ |
167 |
> |
return; |
168 |
> |
qsort(psamp, NDIR2CHECK, sizeof(PEAKSAMP), cmp_psamp); |
169 |
> |
setcolor(vpeak, 0, 0, 0); |
170 |
> |
vypeak = tomsum = 0; /* combine top unique values */ |
171 |
> |
ns = 0; ntot = NDIR2CHECK; |
172 |
> |
for (i = 0; i < NDIR2CHECK; i++) { |
173 |
> |
if (i) { |
174 |
> |
if (psamp[i].vy == psamp[i-1].vy) { |
175 |
> |
vysum -= psamp[i].vy; |
176 |
> |
--ntot; |
177 |
> |
continue; /* assume duplicate sample */ |
178 |
> |
} |
179 |
> |
if (vypeak > 8.*psamp[i].vy*ns) |
180 |
> |
continue; /* peak cut-off */ |
181 |
|
} |
182 |
+ |
ec = SDsizeBSDF(&tomega, psamp[i].tdir, ndp->vray, |
183 |
+ |
SDqueryMin, ndp->sd); |
184 |
+ |
if (ec) |
185 |
+ |
goto baderror; |
186 |
+ |
if (tomega > 1.5*dfp->minProjSA) { |
187 |
+ |
if (!i) return; /* not really a peak? */ |
188 |
+ |
continue; |
189 |
+ |
} |
190 |
+ |
scalecolor(psamp[i].vcol, tomega); |
191 |
+ |
addcolor(vpeak, psamp[i].vcol); |
192 |
+ |
tomsum += tomega; |
193 |
+ |
vypeak += psamp[i].vy; |
194 |
+ |
++ns; |
195 |
|
} |
196 |
< |
if (pdir[2] == 0.0) |
197 |
< |
return; /* zero neighborhood */ |
198 |
< |
ec = SDsizeBSDF(&tomega, pdir, ndp->vray, SDqueryMin, ndp->sd); |
161 |
< |
if (ec) |
162 |
< |
goto baderror; |
163 |
< |
if (tomega > 1.5*dfp->minProjSA) |
164 |
< |
return; /* not really a peak? */ |
165 |
< |
if ((bright(vpeak) - ndp->sd->tLamb.cieY*(1./PI))*tomega <= .001) |
196 |
> |
if (vypeak*(ntot-ns) < peak_over*(vysum-vypeak)*ns) |
197 |
> |
return; /* peak not peaky enough */ |
198 |
> |
if ((vypeak/ns - ndp->sd->tLamb.cieY*(1./PI))*tomsum <= .001) |
199 |
|
return; /* < 0.1% transmission */ |
200 |
< |
for (i = 3; i--; ) /* remove peak from average */ |
168 |
< |
colval(vsum,i) -= colval(vpeak,i); |
169 |
< |
if (peak_over*bright(vsum) >= (NDIR2CHECK-1)*bright(vpeak)) |
170 |
< |
return; /* not peaky enough */ |
171 |
< |
copycolor(ndp->cthru, vpeak); /* else use it */ |
172 |
< |
scalecolor(ndp->cthru, tomega); |
200 |
> |
copycolor(ndp->cthru, vpeak); /* already scaled by omega */ |
201 |
|
multcolor(ndp->cthru, ndp->pr->pcol); /* modify by pattern */ |
202 |
|
return; |
203 |
|
baderror: |
313 |
|
if (tomega2 < .12*tomega) |
314 |
|
continue; /* not safe to include */ |
315 |
|
cvt_sdcolor(csmp, &sv); |
316 |
< |
|
317 |
< |
if (sf < 2.5*tsr) { /* weight by Y for small sources */ |
316 |
> |
#if 0 |
317 |
> |
if (sf < 2.5*tsr) { /* weight by BSDF for small sources */ |
318 |
|
scalecolor(csmp, sv.cieY); |
319 |
|
wtot += sv.cieY; |
320 |
|
} else |
321 |
< |
wtot += 1.; |
321 |
> |
#endif |
322 |
> |
wtot += 1.; |
323 |
|
addcolor(cval, csmp); |
324 |
|
} |
325 |
|
if (wtot <= FTINY) /* no valid specular samples? */ |