ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/aniso.c
Revision: 2.1
Committed: Sat Jan 4 19:52:49 1992 UTC (32 years, 3 months ago) by greg
Content type: text/plain
Branch: MAIN
Log Message:
Initial revision

File Contents

# User Rev Content
1 greg 2.1 /* Copyright (c) 1992 Regents of the University of California */
2    
3     #ifndef lint
4     static char SCCSid[] = "$SunId$ LBL";
5     #endif
6    
7     /*
8     * Shading functions for anisotropic materials.
9     */
10    
11     #include "ray.h"
12    
13     #include "otypes.h"
14    
15     #include "func.h"
16    
17     #include "random.h"
18    
19     /*
20     * This anisotropic reflection model uses a variant on the
21     * exponential Gaussian used in normal.c.
22     * We orient the surface towards the incoming ray, so a single
23     * surface can be used to represent an infinitely thin object.
24     *
25     * Arguments for MAT_PLASTIC2 and MAT_METAL2 are:
26     * 4+ ux uy uz funcfile [transform...]
27     * 0
28     * 6 red grn blu specular-frac. u-facet-slope v-facet-slope
29     *
30     * Real arguments for MAT_TRANS2 are:
31     * 8 red grn blu rspec u-rough v-rough trans tspec
32     */
33    
34     #define BSPEC(m) (6.0) /* specularity parameter b */
35    
36     /* specularity flags */
37     #define SP_REFL 01 /* has reflected specular component */
38     #define SP_TRAN 02 /* has transmitted specular */
39     #define SP_PURE 010 /* purely specular (zero roughness) */
40     #define SP_BADU 020 /* bad u direction calculation */
41    
42     typedef struct {
43     RAY *rp; /* ray pointer */
44     OBJREC *mp; /* material pointer */
45     short specfl; /* specularity flags, defined above */
46     COLOR mcolor; /* color of this material */
47     COLOR scolor; /* color of specular component */
48     FVECT prdir; /* vector in transmitted direction */
49     FVECT u, v; /* u and v vectors orienting anisotropy */
50     double u_alpha; /* u roughness */
51     double v_alpha; /* v roughness */
52     double rdiff, rspec; /* reflected specular, diffuse */
53     double trans; /* transmissivity */
54     double tdiff, tspec; /* transmitted specular, diffuse */
55     FVECT pnorm; /* perturbed surface normal */
56     double pdot; /* perturbed dot product */
57     } ANISODAT; /* anisotropic material data */
58    
59    
60     diraniso(cval, np, ldir, omega) /* compute source contribution */
61     COLOR cval; /* returned coefficient */
62     register ANISODAT *np; /* material data */
63     FVECT ldir; /* light source direction */
64     double omega; /* light source size */
65     {
66     double ldot;
67     double dtmp, dtmp2;
68     FVECT h;
69     double au2, av2;
70     COLOR ctmp;
71    
72     setcolor(cval, 0.0, 0.0, 0.0);
73    
74     ldot = DOT(np->pnorm, ldir);
75    
76     if (ldot < 0.0 ? np->trans <= FTINY : np->trans >= 1.0-FTINY)
77     return; /* wrong side */
78    
79     if (ldot > FTINY && np->rdiff > FTINY) {
80     /*
81     * Compute and add diffuse reflected component to returned
82     * color. The diffuse reflected component will always be
83     * modified by the color of the material.
84     */
85     copycolor(ctmp, np->mcolor);
86     dtmp = ldot * omega * np->rdiff / PI;
87     scalecolor(ctmp, dtmp);
88     addcolor(cval, ctmp);
89     }
90     if (ldot > FTINY && (np->specfl&(SP_REFL|SP_PURE|SP_BADU)) == SP_REFL) {
91     /*
92     * Compute specular reflection coefficient using
93     * anisotropic gaussian distribution model.
94     */
95     /* roughness + source */
96     au2 = av2 = omega/(4.0*PI);
97     au2 += np->u_alpha * np->u_alpha;
98     av2 += np->v_alpha * np->v_alpha;
99     /* half vector */
100     h[0] = ldir[0] - np->rp->rdir[0];
101     h[1] = ldir[1] - np->rp->rdir[1];
102     h[2] = ldir[2] - np->rp->rdir[2];
103     normalize(h);
104     /* ellipse */
105     dtmp = DOT(np->u, h);
106     dtmp *= dtmp / au2;
107     dtmp2 = DOT(np->v, h);
108     dtmp2 *= dtmp2 / av2;
109     /* gaussian */
110     dtmp = (dtmp + dtmp2) / (1.0 + DOT(np->pnorm, h));
111     dtmp = exp(-2.0*dtmp) / (4.0*PI * sqrt(au2*av2));
112     /* worth using? */
113     if (dtmp > FTINY) {
114     copycolor(ctmp, np->scolor);
115     dtmp *= omega / np->pdot;
116     scalecolor(ctmp, dtmp);
117     addcolor(cval, ctmp);
118     }
119     }
120     if (ldot < -FTINY && np->tdiff > FTINY) {
121     /*
122     * Compute diffuse transmission.
123     */
124     copycolor(ctmp, np->mcolor);
125     dtmp = -ldot * omega * np->tdiff / PI;
126     scalecolor(ctmp, dtmp);
127     addcolor(cval, ctmp);
128     }
129     if (ldot < -FTINY && (np->specfl&(SP_TRAN|SP_PURE|SP_BADU)) == SP_TRAN) {
130     /*
131     * Compute specular transmission. Specular transmission
132     * is always modified by material color.
133     */
134     /* roughness + source */
135     /* gaussian */
136     dtmp = 0.0;
137     /* worth using? */
138     if (dtmp > FTINY) {
139     copycolor(ctmp, np->mcolor);
140     dtmp *= np->tspec * omega / np->pdot;
141     scalecolor(ctmp, dtmp);
142     addcolor(cval, ctmp);
143     }
144     }
145     }
146    
147    
148     m_aniso(m, r) /* shade ray that hit something anisotropic */
149     register OBJREC *m;
150     register RAY *r;
151     {
152     ANISODAT nd;
153     double transtest, transdist;
154     double dtmp;
155     COLOR ctmp;
156     register int i;
157     /* easy shadow test */
158     if (r->crtype & SHADOW && m->otype != MAT_TRANS2)
159     return;
160    
161     if (m->oargs.nfargs != (m->otype == MAT_TRANS2 ? 8 : 6))
162     objerror(m, USER, "bad number of real arguments");
163     nd.rp = r;
164     nd.mp = m;
165     /* get material color */
166     setcolor(nd.mcolor, m->oargs.farg[0],
167     m->oargs.farg[1],
168     m->oargs.farg[2]);
169     /* get roughness */
170     nd.specfl = 0;
171     nd.u_alpha = m->oargs.farg[4];
172     nd.v_alpha = m->oargs.farg[5];
173     if (nd.u_alpha <= FTINY || nd.v_alpha <= FTINY)
174     nd.specfl |= SP_PURE;
175     /* reorient if necessary */
176     if (r->rod < 0.0)
177     flipsurface(r);
178     /* get modifiers */
179     raytexture(r, m->omod);
180     nd.pdot = raynormal(nd.pnorm, r); /* perturb normal */
181     if (nd.pdot < .001)
182     nd.pdot = .001; /* non-zero for diraniso() */
183     multcolor(nd.mcolor, r->pcol); /* modify material color */
184     transtest = 0;
185     /* get specular component */
186     if ((nd.rspec = m->oargs.farg[3]) > FTINY) {
187     nd.specfl |= SP_REFL;
188     /* compute specular color */
189     if (m->otype == MAT_METAL2)
190     copycolor(nd.scolor, nd.mcolor);
191     else
192     setcolor(nd.scolor, 1.0, 1.0, 1.0);
193     scalecolor(nd.scolor, nd.rspec);
194     /* improved model */
195     dtmp = exp(-BSPEC(m)*nd.pdot);
196     for (i = 0; i < 3; i++)
197     colval(nd.scolor,i) += (1.0-colval(nd.scolor,i))*dtmp;
198     nd.rspec += (1.0-nd.rspec)*dtmp;
199    
200     if (!(r->crtype & SHADOW) && nd.specfl & SP_PURE) {
201     RAY lr;
202     if (rayorigin(&lr, r, REFLECTED, nd.rspec) == 0) {
203     for (i = 0; i < 3; i++)
204     lr.rdir[i] = r->rdir[i] +
205     2.0*nd.pdot*nd.pnorm[i];
206     rayvalue(&lr);
207     multcolor(lr.rcol, nd.scolor);
208     addcolor(r->rcol, lr.rcol);
209     }
210     }
211     }
212     /* compute transmission */
213     if (m->otype == MAT_TRANS) {
214     nd.trans = m->oargs.farg[6]*(1.0 - nd.rspec);
215     nd.tspec = nd.trans * m->oargs.farg[7];
216     nd.tdiff = nd.trans - nd.tspec;
217     if (nd.tspec > FTINY) {
218     nd.specfl |= SP_TRAN;
219     if (r->crtype & SHADOW ||
220     DOT(r->pert,r->pert) <= FTINY*FTINY) {
221     VCOPY(nd.prdir, r->rdir);
222     transtest = 2;
223     } else {
224     for (i = 0; i < 3; i++) /* perturb */
225     nd.prdir[i] = r->rdir[i] -
226     .75*r->pert[i];
227     normalize(nd.prdir);
228     }
229     }
230     } else
231     nd.tdiff = nd.tspec = nd.trans = 0.0;
232     /* transmitted ray */
233     if ((nd.specfl&(SP_TRAN|SP_PURE)) == (SP_TRAN|SP_PURE)) {
234     RAY lr;
235     if (rayorigin(&lr, r, TRANS, nd.tspec) == 0) {
236     VCOPY(lr.rdir, nd.prdir);
237     rayvalue(&lr);
238     scalecolor(lr.rcol, nd.tspec);
239     multcolor(lr.rcol, nd.mcolor); /* modified by color */
240     addcolor(r->rcol, lr.rcol);
241     transtest *= bright(lr.rcol);
242     transdist = r->rot + lr.rt;
243     }
244     }
245    
246     if (r->crtype & SHADOW) /* the rest is shadow */
247     return;
248     /* diffuse reflection */
249     nd.rdiff = 1.0 - nd.trans - nd.rspec;
250    
251     if (nd.specfl & SP_PURE && nd.rdiff <= FTINY && nd.tdiff <= FTINY)
252     return; /* 100% pure specular */
253    
254     getacoords(r, &nd); /* set up coordinates */
255    
256     if (nd.specfl & (SP_REFL|SP_TRAN) && !(nd.specfl & (SP_PURE|SP_BADU)))
257     agaussamp(r, &nd);
258    
259     if (nd.rdiff > FTINY) { /* ambient from this side */
260     ambient(ctmp, r);
261     scalecolor(ctmp, nd.rdiff);
262     multcolor(ctmp, nd.mcolor); /* modified by material color */
263     addcolor(r->rcol, ctmp); /* add to returned color */
264     }
265     if (nd.tdiff > FTINY) { /* ambient from other side */
266     flipsurface(r);
267     ambient(ctmp, r);
268     scalecolor(ctmp, nd.tdiff);
269     multcolor(ctmp, nd.mcolor); /* modified by color */
270     addcolor(r->rcol, ctmp);
271     flipsurface(r);
272     }
273     /* add direct component */
274     direct(r, diraniso, &nd);
275     /* check distance */
276     if (transtest > bright(r->rcol))
277     r->rt = transdist;
278     }
279    
280    
281     static
282     getacoords(r, np) /* set up coordinate system */
283     RAY *r;
284     register ANISODAT *np;
285     {
286     register MFUNC *mf;
287     register int i;
288    
289     mf = getfunc(np->mp, 3, 0x7, 1);
290     setfunc(np->mp, r);
291     errno = 0;
292     for (i = 0; i < 3; i++)
293     np->u[i] = evalue(mf->ep[i]);
294     if (errno) {
295     objerror(np->mp, WARNING, "compute error");
296     np->specfl |= SP_BADU;
297     return;
298     }
299     multv3(np->u, np->u, mf->f->xfm);
300     fcross(np->v, np->pnorm, np->u);
301     if (normalize(np->v) == 0.0) {
302     objerror(np->mp, WARNING, "illegal orientation vector");
303     np->specfl |= SP_BADU;
304     return;
305     }
306     fcross(np->u, np->v, np->pnorm);
307     }
308    
309    
310     static
311     agaussamp(r, np) /* sample anisotropic gaussian specular */
312     RAY *r;
313     register ANISODAT *np;
314     {
315     RAY sr;
316     FVECT h;
317     double rv[2];
318     double d, sinp, cosp;
319     int confuse;
320     register int i;
321     /* compute reflection */
322     if (np->specfl & SP_REFL &&
323     rayorigin(&sr, r, SPECULAR, np->rspec) == 0) {
324     confuse = 0;
325     dimlist[ndims++] = (int)np->mp;
326     refagain:
327     dimlist[ndims] = confuse += 3601;
328     d = urand(ilhash(dimlist,ndims+1)+samplendx);
329     multisamp(rv, 2, d);
330     d = 2.0*PI * rv[0];
331     cosp = np->u_alpha * cos(d);
332     sinp = np->v_alpha * sin(d);
333     d = sqrt(cosp*cosp + sinp*sinp);
334     cosp /= d;
335     sinp /= d;
336     if (rv[1] <= FTINY)
337     d = 1.0;
338     else
339     d = sqrt( -log(rv[1]) /
340     (cosp*cosp/(np->u_alpha*np->u_alpha) +
341     sinp*sinp/(np->v_alpha*np->v_alpha)) );
342     for (i = 0; i < 3; i++)
343     h[i] = np->pnorm[i] +
344     d*(cosp*np->u[i] + sinp*np->v[i]);
345     d = -2.0 * DOT(h, r->rdir) / (1.0 + d*d);
346     for (i = 0; i < 3; i++)
347     sr.rdir[i] = r->rdir[i] + d*h[i];
348     if (DOT(sr.rdir, r->ron) <= FTINY) /* oops! */
349     goto refagain;
350     rayvalue(&sr);
351     multcolor(sr.rcol, np->scolor);
352     addcolor(r->rcol, sr.rcol);
353     ndims--;
354     }
355     /* compute transmission */
356     }