ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/ashikhmin.c
Revision: 2.3
Committed: Wed Aug 7 05:10:09 2013 UTC (10 years, 8 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad4R2P2, rad4R2, rad4R2P1
Changes since 2.2: +1 -2 lines
Log Message:
Eliminated a number of minor warnings (all innocuous)

File Contents

# User Rev Content
1 greg 2.1 #ifndef lint
2 greg 2.3 static const char RCSid[] = "$Id: ashikhmin.c,v 2.2 2012/07/29 21:56:16 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    
18     #ifndef MAXITER
19     #define MAXITER 10 /* maximum # specular ray attempts */
20     #endif
21    
22     /*
23     * Ashikhmin-Shirley model
24     *
25     * Arguments for MAT_ASHIKHMIN are:
26     * 4+ ux uy uz funcfile [transform...]
27     * 0
28     * 8 dred dgrn dblu sred sgrn sblu u-power v-power
29     */
30    
31     /* specularity flags */
32     #define SPA_REFL 01 /* has reflected specular component */
33     #define SPA_FLAT 02 /* reflecting surface is flat */
34     #define SPA_RBLT 010 /* reflection below sample threshold */
35     #define SPA_BADU 020 /* bad u direction calculation */
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     if ((np->specfl & (SPA_REFL|SPA_BADU)) != SPA_REFL)
97     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     if ((errno == EDOM) | (errno == ERANGE)) {
213     objerror(np->mp, WARNING, "compute error");
214     np->specfl |= SPA_BADU;
215     return;
216     }
217     if (mf->fxp != &unitxf)
218     multv3(np->u, np->u, mf->fxp->xfm);
219     fcross(np->v, np->pnorm, np->u);
220     if (normalize(np->v) == 0.0) {
221     objerror(np->mp, WARNING, "illegal orientation vector");
222     np->specfl |= SPA_BADU;
223     return;
224     }
225     fcross(np->u, np->v, np->pnorm);
226     }
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     if (np->specfl & SPA_BADU ||
242 greg 2.2 rayorigin(&sr, SPECULAR, np->rp, np->scolor) < 0)
243 greg 2.1 return;
244    
245     nstarget = 1;
246     if (specjitter > 1.5) { /* multiple samples? */
247 greg 2.2 nstarget = specjitter*np->rp->rweight + .5;
248 greg 2.1 if (sr.rweight <= minweight*nstarget)
249     nstarget = sr.rweight/minweight;
250     if (nstarget > 1) {
251     dtmp = 1./nstarget;
252     scalecolor(sr.rcoef, dtmp);
253     sr.rweight *= dtmp;
254     } else
255     nstarget = 1;
256     }
257     dimlist[ndims++] = (int)(size_t)np->mp;
258     maxiter = MAXITER*nstarget;
259     for (nstaken = ntrials = 0; nstaken < nstarget &&
260     ntrials < maxiter; ntrials++) {
261     if (ntrials)
262     dtmp = frandom();
263     else
264 greg 2.2 dtmp = urand(ilhash(dimlist,ndims)+647+samplendx);
265 greg 2.1 multisamp(rv, 2, dtmp);
266     dtmp = 2.*PI * rv[0];
267 greg 2.2 cosph = sqrt(np->v_power + 1.) * tcos(dtmp);
268     sinph = sqrt(np->u_power + 1.) * tsin(dtmp);
269     dtmp = 1./sqrt(cosph*cosph + sinph*sinph);
270 greg 2.1 cosph *= dtmp;
271     sinph *= dtmp;
272     costh = pow(rv[1], 1./(np->u_power*cosph*cosph+np->v_power*sinph*sinph+1.));
273     if (costh <= FTINY)
274     continue;
275     sinth = sqrt(1. - costh*costh);
276     for (i = 0; i < 3; i++)
277     h[i] = cosph*sinth*np->u[i] + sinph*sinth*np->v[i] + costh*np->pnorm[i];
278    
279     if (nstaken)
280     rayclear(&sr);
281 greg 2.2 dtmp = -2.*DOT(h, np->rp->rdir);
282     VSUM(sr.rdir, np->rp->rdir, h, dtmp);
283 greg 2.1 /* sample rejection test */
284 greg 2.2 if (DOT(sr.rdir, np->rp->ron) <= FTINY)
285 greg 2.1 continue;
286 greg 2.2 checknorm(sr.rdir);
287 greg 2.1 rayvalue(&sr);
288     multcolor(sr.rcol, sr.rcoef);
289 greg 2.2 addcolor(np->rp->rcol, sr.rcol);
290 greg 2.1 ++nstaken;
291     }
292     ndims--;
293     }