ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/ashikhmin.c
Revision: 2.1
Committed: Sun Jul 29 19:01:39 2012 UTC (11 years, 9 months ago) by greg
Content type: text/plain
Branch: MAIN
Log Message:
Added ashik2 type for anisotropic Ashikhmin-Shirley BRDF model

File Contents

# User Rev Content
1 greg 2.1 #ifndef lint
2     static const char RCSid[] = "$Id$";
3     #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     static void getacoords_as(RAY *r, ASHIKDAT *np);
51     static void ashiksamp(RAY *r, ASHIKDAT *np);
52    
53    
54     static double
55     max(double a, double b) {
56     if (a > b)
57     return(a);
58     return(b);
59     }
60    
61    
62     static double
63     schlick_fres(double dprod)
64     {
65     double pf = 1. - dprod;
66    
67     return(pf*pf*pf*pf*pf);
68     }
69    
70    
71     static void
72     dirashik( /* compute source contribution */
73     COLOR cval, /* returned coefficient */
74     void *nnp, /* material data */
75     FVECT ldir, /* light source direction */
76     double omega /* light source size */
77     )
78     {
79     ASHIKDAT *np = nnp;
80     double ldot;
81     double dtmp, dtmp1, dtmp2;
82     FVECT h;
83     COLOR ctmp;
84    
85     setcolor(cval, 0.0, 0.0, 0.0);
86    
87     ldot = DOT(np->pnorm, ldir);
88    
89     if (ldot < 0.0)
90     return; /* wrong side */
91    
92     /*
93     * Compute and add diffuse reflected component to returned
94     * color.
95     */
96     copycolor(ctmp, np->mcolor);
97     dtmp = ldot * omega * (1.0/PI) * (1. - schlick_fres(ldot));
98     scalecolor(ctmp, dtmp);
99     addcolor(cval, ctmp);
100    
101     if ((np->specfl & (SPA_REFL|SPA_BADU)) != SPA_REFL)
102     return;
103     /*
104     * Compute specular reflection coefficient
105     */
106     /* half vector */
107     VSUB(h, ldir, np->rp->rdir);
108     normalize(h);
109     /* ellipse */
110     dtmp1 = DOT(np->u, h);
111     dtmp1 *= dtmp1 * np->u_power;
112     dtmp2 = DOT(np->v, h);
113     dtmp2 *= dtmp2 * np->v_power;
114     /* Ashikhmin-Shirley model*/
115     dtmp = DOT(np->pnorm, h);
116     dtmp = pow(dtmp, (dtmp1+dtmp2)/(1.-dtmp*dtmp));
117     dtmp *= sqrt((np->u_power+1.)*(np->v_power+1.));
118     dtmp /= 8.*PI * DOT(ldir,h) * max(ldot,np->pdot);
119     /* worth using? */
120     if (dtmp > FTINY) {
121     copycolor(ctmp, np->scolor);
122     dtmp *= ldot * omega;
123     scalecolor(ctmp, dtmp);
124     addcolor(cval, ctmp);
125     }
126     }
127    
128    
129     int
130     m_ashikhmin( /* shade ray that hit something anisotropic */
131     OBJREC *m,
132     RAY *r
133     )
134     {
135     ASHIKDAT nd;
136     COLOR ctmp;
137     double fres;
138     int i;
139     /* easy shadow test */
140     if (r->crtype & SHADOW)
141     return(1);
142    
143     if (m->oargs.nfargs != 8)
144     objerror(m, USER, "bad number of real arguments");
145     /* check for back side */
146     if (r->rod < 0.0) {
147     if (!backvis) {
148     raytrans(r);
149     return(1);
150     }
151     raytexture(r, m->omod);
152     flipsurface(r); /* reorient if backvis */
153     } else
154     raytexture(r, m->omod);
155     /* get material color */
156     nd.mp = m;
157     nd.rp = r;
158     setcolor(nd.mcolor, m->oargs.farg[0],
159     m->oargs.farg[1],
160     m->oargs.farg[2]);
161     setcolor(nd.scolor, m->oargs.farg[3],
162     m->oargs.farg[4],
163     m->oargs.farg[5]);
164     /* get specular power */
165     nd.specfl = 0;
166     nd.u_power = m->oargs.farg[6];
167     nd.v_power = m->oargs.farg[7];
168    
169     nd.pdot = raynormal(nd.pnorm, r); /* perturb normal */
170     if (nd.pdot < .001)
171     nd.pdot = .001; /* non-zero for dirashik() */
172     multcolor(nd.mcolor, r->pcol); /* modify diffuse color */
173    
174     if (bright(nd.scolor) > FTINY) { /* adjust specular color */
175     nd.specfl |= SPA_REFL;
176     /* check threshold */
177     if (specthresh >= bright(nd.scolor)-FTINY)
178     nd.specfl |= SPA_RBLT;
179     fres = schlick_fres(nd.pdot); /* Schick's Fresnel approx */
180     for (i = 0; i < 3; i++)
181     colval(nd.scolor,i) += (1.-colval(nd.scolor,i))*fres;
182     }
183     if (r->ro != NULL && isflat(r->ro->otype))
184     nd.specfl |= SPA_FLAT;
185     /* set up coordinates */
186     getacoords_as(r, &nd);
187     /* specular sampling? */
188     if ((nd.specfl & (SPA_REFL|SPA_RBLT)) == SPA_REFL)
189     ashiksamp(r, &nd);
190     /* diffuse interreflection */
191     if (bright(nd.mcolor) > FTINY) {
192     copycolor(ctmp, nd.mcolor); /* modified by material color */
193     if (nd.specfl & SPA_RBLT) /* add in specular as well? */
194     addcolor(ctmp, nd.scolor);
195     multambient(ctmp, r, nd.pnorm);
196     addcolor(r->rcol, ctmp); /* add to returned color */
197     }
198     direct(r, dirashik, &nd); /* add direct component */
199    
200     return(1);
201     }
202    
203    
204     static void
205     getacoords_as( /* set up coordinate system */
206     RAY *r,
207     ASHIKDAT *np
208     )
209     {
210     MFUNC *mf;
211     int i;
212    
213     mf = getfunc(np->mp, 3, 0x7, 1);
214     setfunc(np->mp, r);
215     errno = 0;
216     for (i = 0; i < 3; i++)
217     np->u[i] = evalue(mf->ep[i]);
218     if ((errno == EDOM) | (errno == ERANGE)) {
219     objerror(np->mp, WARNING, "compute error");
220     np->specfl |= SPA_BADU;
221     return;
222     }
223     if (mf->fxp != &unitxf)
224     multv3(np->u, np->u, mf->fxp->xfm);
225     fcross(np->v, np->pnorm, np->u);
226     if (normalize(np->v) == 0.0) {
227     objerror(np->mp, WARNING, "illegal orientation vector");
228     np->specfl |= SPA_BADU;
229     return;
230     }
231     fcross(np->u, np->v, np->pnorm);
232     }
233    
234    
235     static void
236     ashiksamp( /* sample anisotropic Ashikhmin-Shirley specular */
237     RAY *r,
238     ASHIKDAT *np
239     )
240     {
241     RAY sr;
242     FVECT h;
243     double rv[2], dtmp;
244     double cosph, sinph, costh, sinth;
245     COLOR scol;
246     int maxiter, ntrials, nstarget, nstaken;
247     int i;
248    
249     if (np->specfl & SPA_BADU ||
250     rayorigin(&sr, SPECULAR, r, np->scolor) < 0)
251     return;
252    
253     nstarget = 1;
254     if (specjitter > 1.5) { /* multiple samples? */
255     nstarget = specjitter*r->rweight + .5;
256     if (sr.rweight <= minweight*nstarget)
257     nstarget = sr.rweight/minweight;
258     if (nstarget > 1) {
259     dtmp = 1./nstarget;
260     scalecolor(sr.rcoef, dtmp);
261     sr.rweight *= dtmp;
262     } else
263     nstarget = 1;
264     }
265     dimlist[ndims++] = (int)(size_t)np->mp;
266     maxiter = MAXITER*nstarget;
267     for (nstaken = ntrials = 0; nstaken < nstarget &&
268     ntrials < maxiter; ntrials++) {
269     if (ntrials)
270     dtmp = frandom();
271     else
272     dtmp = urand(ilhash(dimlist,ndims)+1823+samplendx);
273     multisamp(rv, 2, dtmp);
274     dtmp = 2.*PI * rv[0];
275     cosph = sqrt(np->u_power + 1.) * tcos(dtmp);
276     sinph = sqrt(np->v_power + 1.) * tsin(dtmp);
277     dtmp = 1./(cosph*cosph + sinph*sinph);
278     cosph *= dtmp;
279     sinph *= dtmp;
280     costh = pow(rv[1], 1./(np->u_power*cosph*cosph+np->v_power*sinph*sinph+1.));
281     if (costh <= FTINY)
282     continue;
283     sinth = sqrt(1. - costh*costh);
284     for (i = 0; i < 3; i++)
285     h[i] = cosph*sinth*np->u[i] + sinph*sinth*np->v[i] + costh*np->pnorm[i];
286    
287     if (nstaken)
288     rayclear(&sr);
289     dtmp = -2.*DOT(h, r->rdir);
290     VSUM(sr.rdir, r->rdir, h, dtmp);
291     /* sample rejection test */
292     if (DOT(sr.rdir, r->ron) <= FTINY)
293     continue;
294     rayvalue(&sr);
295     multcolor(sr.rcol, sr.rcoef);
296     addcolor(r->rcol, sr.rcol);
297     ++nstaken;
298     }
299     ndims--;
300     }