ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/ashikhmin.c
Revision: 2.6
Committed: Wed Sep 2 18:59:01 2015 UTC (8 years, 8 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R4, rad5R2, rad5R0, rad5R1, rad5R3
Changes since 2.5: +3 -2 lines
Log Message:
Had to reinstate ambRayInPmap() macro to avoid over-counting bug

File Contents

# User Rev Content
1 greg 2.1 #ifndef lint
2 greg 2.6 static const char RCSid[] = "$Id: ashikhmin.c,v 2.5 2015/05/21 05:54:54 greg Exp $";
3 greg 2.1 #endif
4     /*
5     * Shading functions for Ashikhmin-Shirley anisotropic materials.
6     */
7    
8     #include "copyright.h"
9    
10     #include "ray.h"
11     #include "ambient.h"
12     #include "otypes.h"
13     #include "rtotypes.h"
14     #include "source.h"
15     #include "func.h"
16     #include "random.h"
17 greg 2.6 #include "pmapmat.h"
18 greg 2.1
19     #ifndef MAXITER
20     #define MAXITER 10 /* maximum # specular ray attempts */
21     #endif
22    
23     /*
24     * Ashikhmin-Shirley model
25     *
26     * Arguments for MAT_ASHIKHMIN are:
27     * 4+ ux uy uz funcfile [transform...]
28     * 0
29     * 8 dred dgrn dblu sred sgrn sblu u-power v-power
30     */
31    
32     /* specularity flags */
33     #define SPA_REFL 01 /* has reflected specular component */
34     #define SPA_FLAT 02 /* reflecting surface is flat */
35     #define SPA_RBLT 010 /* reflection below sample threshold */
36    
37     typedef struct {
38     OBJREC *mp; /* material pointer */
39     RAY *rp; /* ray pointer */
40     short specfl; /* specularity flags, defined above */
41     COLOR mcolor; /* color of this material */
42     COLOR scolor; /* color of specular component */
43     FVECT u, v; /* u and v vectors orienting anisotropy */
44     double u_power; /* u power */
45     double v_power; /* v power */
46     FVECT pnorm; /* perturbed surface normal */
47     double pdot; /* perturbed dot product */
48     } ASHIKDAT; /* anisotropic material data */
49    
50 greg 2.2 static void getacoords_as(ASHIKDAT *np);
51     static void ashiksamp(ASHIKDAT *np);
52 greg 2.1
53 greg 2.2 #undef MAX
54     #define MAX(a,b) ((a)>(b) ? (a) : (b))
55 greg 2.1
56    
57     static double
58     schlick_fres(double dprod)
59     {
60     double pf = 1. - dprod;
61    
62     return(pf*pf*pf*pf*pf);
63     }
64    
65    
66     static void
67     dirashik( /* compute source contribution */
68     COLOR cval, /* returned coefficient */
69     void *nnp, /* material data */
70     FVECT ldir, /* light source direction */
71     double omega /* light source size */
72     )
73     {
74     ASHIKDAT *np = nnp;
75     double ldot;
76     double dtmp, dtmp1, dtmp2;
77     FVECT h;
78     COLOR ctmp;
79    
80     setcolor(cval, 0.0, 0.0, 0.0);
81    
82     ldot = DOT(np->pnorm, ldir);
83    
84     if (ldot < 0.0)
85     return; /* wrong side */
86    
87     /*
88     * Compute and add diffuse reflected component to returned
89     * color.
90     */
91     copycolor(ctmp, np->mcolor);
92     dtmp = ldot * omega * (1.0/PI) * (1. - schlick_fres(ldot));
93     scalecolor(ctmp, dtmp);
94     addcolor(cval, ctmp);
95    
96 greg 2.6 if (!(np->specfl & SPA_REFL) || ambRayInPmap(np->rp))
97 greg 2.1 return;
98     /*
99     * Compute specular reflection coefficient
100     */
101     /* half vector */
102     VSUB(h, ldir, np->rp->rdir);
103     normalize(h);
104     /* ellipse */
105     dtmp1 = DOT(np->u, h);
106     dtmp1 *= dtmp1 * np->u_power;
107     dtmp2 = DOT(np->v, h);
108     dtmp2 *= dtmp2 * np->v_power;
109     /* Ashikhmin-Shirley model*/
110     dtmp = DOT(np->pnorm, h);
111     dtmp = pow(dtmp, (dtmp1+dtmp2)/(1.-dtmp*dtmp));
112     dtmp *= sqrt((np->u_power+1.)*(np->v_power+1.));
113 greg 2.2 dtmp /= 8.*PI * DOT(ldir,h) * MAX(ldot,np->pdot);
114 greg 2.1 /* worth using? */
115     if (dtmp > FTINY) {
116     copycolor(ctmp, np->scolor);
117     dtmp *= ldot * omega;
118     scalecolor(ctmp, dtmp);
119     addcolor(cval, ctmp);
120     }
121     }
122    
123    
124     int
125     m_ashikhmin( /* shade ray that hit something anisotropic */
126     OBJREC *m,
127     RAY *r
128     )
129     {
130     ASHIKDAT nd;
131     COLOR ctmp;
132     double fres;
133     int i;
134     /* easy shadow test */
135     if (r->crtype & SHADOW)
136     return(1);
137    
138     if (m->oargs.nfargs != 8)
139     objerror(m, USER, "bad number of real arguments");
140     /* check for back side */
141     if (r->rod < 0.0) {
142     if (!backvis) {
143     raytrans(r);
144     return(1);
145     }
146     raytexture(r, m->omod);
147     flipsurface(r); /* reorient if backvis */
148     } else
149     raytexture(r, m->omod);
150     /* get material color */
151     nd.mp = m;
152     nd.rp = r;
153     setcolor(nd.mcolor, m->oargs.farg[0],
154     m->oargs.farg[1],
155     m->oargs.farg[2]);
156     setcolor(nd.scolor, m->oargs.farg[3],
157     m->oargs.farg[4],
158     m->oargs.farg[5]);
159     /* get specular power */
160     nd.specfl = 0;
161     nd.u_power = m->oargs.farg[6];
162     nd.v_power = m->oargs.farg[7];
163    
164     nd.pdot = raynormal(nd.pnorm, r); /* perturb normal */
165     if (nd.pdot < .001)
166     nd.pdot = .001; /* non-zero for dirashik() */
167     multcolor(nd.mcolor, r->pcol); /* modify diffuse color */
168    
169     if (bright(nd.scolor) > FTINY) { /* adjust specular color */
170     nd.specfl |= SPA_REFL;
171     /* check threshold */
172     if (specthresh >= bright(nd.scolor)-FTINY)
173     nd.specfl |= SPA_RBLT;
174     fres = schlick_fres(nd.pdot); /* Schick's Fresnel approx */
175     for (i = 0; i < 3; i++)
176     colval(nd.scolor,i) += (1.-colval(nd.scolor,i))*fres;
177     }
178     if (r->ro != NULL && isflat(r->ro->otype))
179     nd.specfl |= SPA_FLAT;
180     /* set up coordinates */
181 greg 2.2 getacoords_as(&nd);
182 greg 2.1 /* specular sampling? */
183     if ((nd.specfl & (SPA_REFL|SPA_RBLT)) == SPA_REFL)
184 greg 2.2 ashiksamp(&nd);
185 greg 2.1 /* diffuse interreflection */
186     if (bright(nd.mcolor) > FTINY) {
187     copycolor(ctmp, nd.mcolor); /* modified by material color */
188     if (nd.specfl & SPA_RBLT) /* add in specular as well? */
189     addcolor(ctmp, nd.scolor);
190     multambient(ctmp, r, nd.pnorm);
191     addcolor(r->rcol, ctmp); /* add to returned color */
192     }
193     direct(r, dirashik, &nd); /* add direct component */
194    
195     return(1);
196     }
197    
198    
199     static void
200     getacoords_as( /* set up coordinate system */
201     ASHIKDAT *np
202     )
203     {
204     MFUNC *mf;
205     int i;
206    
207     mf = getfunc(np->mp, 3, 0x7, 1);
208 greg 2.2 setfunc(np->mp, np->rp);
209 greg 2.1 errno = 0;
210     for (i = 0; i < 3; i++)
211     np->u[i] = evalue(mf->ep[i]);
212 greg 2.4 if ((errno == EDOM) | (errno == ERANGE))
213     np->u[0] = np->u[1] = np->u[2] = 0.0;
214 greg 2.1 if (mf->fxp != &unitxf)
215     multv3(np->u, np->u, mf->fxp->xfm);
216     fcross(np->v, np->pnorm, np->u);
217     if (normalize(np->v) == 0.0) {
218 greg 2.4 if (fabs(np->u_power - np->v_power) > 0.1)
219     objerror(np->mp, WARNING, "bad orientation vector");
220 greg 2.5 getperpendicular(np->u, np->pnorm, 1); /* punting */
221 greg 2.4 fcross(np->v, np->pnorm, np->u);
222     np->u_power = np->v_power =
223     2./(1./(np->u_power+1e-5) + 1./(np->v_power+1e-5));
224     } else
225     fcross(np->u, np->v, np->pnorm);
226 greg 2.1 }
227    
228    
229     static void
230     ashiksamp( /* sample anisotropic Ashikhmin-Shirley specular */
231     ASHIKDAT *np
232     )
233     {
234     RAY sr;
235     FVECT h;
236     double rv[2], dtmp;
237     double cosph, sinph, costh, sinth;
238     int maxiter, ntrials, nstarget, nstaken;
239     int i;
240    
241 greg 2.4 if (rayorigin(&sr, SPECULAR, np->rp, np->scolor) < 0)
242 greg 2.1 return;
243    
244     nstarget = 1;
245     if (specjitter > 1.5) { /* multiple samples? */
246 greg 2.2 nstarget = specjitter*np->rp->rweight + .5;
247 greg 2.1 if (sr.rweight <= minweight*nstarget)
248     nstarget = sr.rweight/minweight;
249     if (nstarget > 1) {
250     dtmp = 1./nstarget;
251     scalecolor(sr.rcoef, dtmp);
252     sr.rweight *= dtmp;
253     } else
254     nstarget = 1;
255     }
256     dimlist[ndims++] = (int)(size_t)np->mp;
257     maxiter = MAXITER*nstarget;
258     for (nstaken = ntrials = 0; nstaken < nstarget &&
259     ntrials < maxiter; ntrials++) {
260     if (ntrials)
261     dtmp = frandom();
262     else
263 greg 2.2 dtmp = urand(ilhash(dimlist,ndims)+647+samplendx);
264 greg 2.1 multisamp(rv, 2, dtmp);
265     dtmp = 2.*PI * rv[0];
266 greg 2.2 cosph = sqrt(np->v_power + 1.) * tcos(dtmp);
267     sinph = sqrt(np->u_power + 1.) * tsin(dtmp);
268     dtmp = 1./sqrt(cosph*cosph + sinph*sinph);
269 greg 2.1 cosph *= dtmp;
270     sinph *= dtmp;
271     costh = pow(rv[1], 1./(np->u_power*cosph*cosph+np->v_power*sinph*sinph+1.));
272     if (costh <= FTINY)
273     continue;
274     sinth = sqrt(1. - costh*costh);
275     for (i = 0; i < 3; i++)
276     h[i] = cosph*sinth*np->u[i] + sinph*sinth*np->v[i] + costh*np->pnorm[i];
277    
278     if (nstaken)
279     rayclear(&sr);
280 greg 2.2 dtmp = -2.*DOT(h, np->rp->rdir);
281     VSUM(sr.rdir, np->rp->rdir, h, dtmp);
282 greg 2.1 /* sample rejection test */
283 greg 2.2 if (DOT(sr.rdir, np->rp->ron) <= FTINY)
284 greg 2.1 continue;
285 greg 2.2 checknorm(sr.rdir);
286 greg 2.1 rayvalue(&sr);
287     multcolor(sr.rcol, sr.rcoef);
288 greg 2.2 addcolor(np->rp->rcol, sr.rcol);
289 greg 2.1 ++nstaken;
290     }
291     ndims--;
292     }