ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/m_brdf.c
Revision: 2.15
Committed: Sat Feb 22 02:07:28 2003 UTC (21 years, 2 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.14: +74 -23 lines
Log Message:
Changes and check-in for 3.5 release
Includes new source files and modifications not recorded for many years
See ray/doc/notes/ReleaseNotes for notes between 3.1 and 3.5 release

File Contents

# User Rev Content
1 greg 1.1 #ifndef lint
2 greg 2.15 static const char RCSid[] = "$Id$";
3 greg 1.1 #endif
4     /*
5     * Shading for materials with arbitrary BRDF's
6     */
7    
8 greg 2.15 /* ====================================================================
9     * The Radiance Software License, Version 1.0
10     *
11     * Copyright (c) 1990 - 2002 The Regents of the University of California,
12     * through Lawrence Berkeley National Laboratory. All rights reserved.
13     *
14     * Redistribution and use in source and binary forms, with or without
15     * modification, are permitted provided that the following conditions
16     * are met:
17     *
18     * 1. Redistributions of source code must retain the above copyright
19     * notice, this list of conditions and the following disclaimer.
20     *
21     * 2. Redistributions in binary form must reproduce the above copyright
22     * notice, this list of conditions and the following disclaimer in
23     * the documentation and/or other materials provided with the
24     * distribution.
25     *
26     * 3. The end-user documentation included with the redistribution,
27     * if any, must include the following acknowledgment:
28     * "This product includes Radiance software
29     * (http://radsite.lbl.gov/)
30     * developed by the Lawrence Berkeley National Laboratory
31     * (http://www.lbl.gov/)."
32     * Alternately, this acknowledgment may appear in the software itself,
33     * if and wherever such third-party acknowledgments normally appear.
34     *
35     * 4. The names "Radiance," "Lawrence Berkeley National Laboratory"
36     * and "The Regents of the University of California" must
37     * not be used to endorse or promote products derived from this
38     * software without prior written permission. For written
39     * permission, please contact [email protected].
40     *
41     * 5. Products derived from this software may not be called "Radiance",
42     * nor may "Radiance" appear in their name, without prior written
43     * permission of Lawrence Berkeley National Laboratory.
44     *
45     * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
46     * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
47     * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
48     * DISCLAIMED. IN NO EVENT SHALL Lawrence Berkeley National Laboratory OR
49     * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
50     * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
51     * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
52     * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
53     * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
54     * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
55     * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56     * SUCH DAMAGE.
57     * ====================================================================
58     *
59     * This software consists of voluntary contributions made by many
60     * individuals on behalf of Lawrence Berkeley National Laboratory. For more
61     * information on Lawrence Berkeley National Laboratory, please see
62     * <http://www.lbl.gov/>.
63     */
64    
65 greg 1.1 #include "ray.h"
66    
67     #include "data.h"
68    
69     #include "otypes.h"
70    
71 greg 2.2 #include "func.h"
72    
73 greg 1.1 /*
74     * Arguments to this material include the color and specularity.
75     * String arguments include the reflection function and files.
76     * The BRDF is currently used just for the specular component to light
77     * sources. Reflectance values or data coordinates are functions
78 greg 2.7 * of the direction to the light source. (Data modification functions
79     * are passed the source direction as args 2-4.)
80 greg 1.1 * We orient the surface towards the incoming ray, so a single
81     * surface can be used to represent an infinitely thin object.
82     *
83     * Arguments for MAT_PFUNC and MAT_MFUNC are:
84 greg 1.4 * 2+ func funcfile transform
85 greg 1.1 * 0
86 greg 1.4 * 4+ red grn blu specularity A5 ..
87 greg 1.1 *
88     * Arguments for MAT_PDATA and MAT_MDATA are:
89 greg 1.4 * 4+ func datafile funcfile v0 .. transform
90 greg 1.1 * 0
91 greg 1.4 * 4+ red grn blu specularity A5 ..
92 greg 1.5 *
93     * Arguments for MAT_TFUNC are:
94     * 2+ func funcfile transform
95     * 0
96     * 4+ red grn blu rspec trans tspec A7 ..
97     *
98     * Arguments for MAT_TDATA are:
99     * 4+ func datafile funcfile v0 .. transform
100     * 0
101     * 4+ red grn blu rspec trans tspec A7 ..
102     *
103     * Arguments for the more general MAT_BRTDF are:
104     * 10+ rrefl grefl brefl
105     * rtrns gtrns btrns
106     * rbrtd gbrtd bbrtd
107     * funcfile transform
108     * 0
109 greg 2.6 * 9+ rdf gdf bdf
110     * rdb gdb bdb
111     * rdt gdt bdt A10 ..
112 greg 1.5 *
113     * In addition to the normal variables available to functions,
114     * we define the following:
115     * NxP, NyP, NzP - perturbed surface normal
116     * RdotP - perturbed ray dot product
117 greg 2.6 * CrP, CgP, CbP - perturbed material color (or pattern)
118 greg 1.1 */
119    
120     typedef struct {
121     OBJREC *mp; /* material pointer */
122     RAY *pr; /* intersected ray */
123 greg 1.5 DATARRAY *dp; /* data array for PDATA, MDATA or TDATA */
124 greg 2.6 COLOR mcolor; /* material (or pattern) color */
125     COLOR rdiff; /* diffuse reflection */
126     COLOR tdiff; /* diffuse transmission */
127     double rspec; /* specular reflectance (1 for BRDTF) */
128     double trans; /* transmissivity (.5 for BRDTF) */
129     double tspec; /* specular transmittance (1 for BRDTF) */
130 greg 1.1 FVECT pnorm; /* perturbed surface normal */
131     double pdot; /* perturbed dot product */
132     } BRDFDAT; /* BRDF material data */
133    
134    
135 greg 2.15 static void
136 greg 1.1 dirbrdf(cval, np, ldir, omega) /* compute source contribution */
137     COLOR cval; /* returned coefficient */
138     register BRDFDAT *np; /* material data */
139     FVECT ldir; /* light source direction */
140     double omega; /* light source size */
141     {
142     double ldot;
143     double dtmp;
144     COLOR ctmp;
145 greg 1.4 FVECT ldx;
146 greg 2.12 static double vldx[5], pt[MAXDIM];
147 greg 1.5 register char **sa;
148 greg 1.1 register int i;
149 greg 2.12 #define lddx (vldx+1)
150 greg 1.1
151     setcolor(cval, 0.0, 0.0, 0.0);
152    
153     ldot = DOT(np->pnorm, ldir);
154    
155 greg 1.5 if (ldot <= FTINY && ldot >= -FTINY)
156     return; /* too close to grazing */
157 greg 2.6
158 greg 1.5 if (ldot < 0.0 ? np->trans <= FTINY : np->trans >= 1.0-FTINY)
159 greg 1.1 return; /* wrong side */
160    
161 greg 2.6 if (ldot > 0.0) {
162 greg 1.1 /*
163     * Compute and add diffuse reflected component to returned
164     * color. The diffuse reflected component will always be
165     * modified by the color of the material.
166     */
167 greg 2.6 copycolor(ctmp, np->rdiff);
168     dtmp = ldot * omega / PI;
169 greg 1.1 scalecolor(ctmp, dtmp);
170     addcolor(cval, ctmp);
171 greg 2.6 } else {
172 greg 1.1 /*
173 greg 1.5 * Diffuse transmitted component.
174 greg 1.1 */
175 greg 2.6 copycolor(ctmp, np->tdiff);
176     dtmp = -ldot * omega / PI;
177 greg 1.5 scalecolor(ctmp, dtmp);
178     addcolor(cval, ctmp);
179 greg 1.1 }
180 greg 1.5 if (ldot > 0.0 ? np->rspec <= FTINY : np->tspec <= FTINY)
181     return; /* no specular component */
182     /* set up function */
183 greg 1.10 setbrdfunc(np);
184 greg 1.5 sa = np->mp->oargs.sarg;
185     errno = 0;
186     /* transform light vector */
187     multv3(ldx, ldir, funcxf.xfm);
188     for (i = 0; i < 3; i++)
189 greg 2.3 lddx[i] = ldx[i]/funcxf.sca;
190 greg 2.12 lddx[3] = omega;
191 greg 1.5 /* compute BRTDF */
192     if (np->mp->otype == MAT_BRTDF) {
193 greg 2.6 if (sa[6][0] == '0') /* special case */
194     colval(ctmp,RED) = 0.0;
195     else
196 greg 2.12 colval(ctmp,RED) = funvalue(sa[6], 4, lddx);
197 greg 1.7 if (!strcmp(sa[7],sa[6]))
198 greg 1.5 colval(ctmp,GRN) = colval(ctmp,RED);
199     else
200 greg 2.12 colval(ctmp,GRN) = funvalue(sa[7], 4, lddx);
201 greg 1.7 if (!strcmp(sa[8],sa[6]))
202 greg 1.5 colval(ctmp,BLU) = colval(ctmp,RED);
203 greg 1.7 else if (!strcmp(sa[8],sa[7]))
204 greg 1.5 colval(ctmp,BLU) = colval(ctmp,GRN);
205     else
206 greg 2.12 colval(ctmp,BLU) = funvalue(sa[8], 4, lddx);
207 greg 1.5 dtmp = bright(ctmp);
208     } else if (np->dp == NULL) {
209 greg 2.12 dtmp = funvalue(sa[0], 4, lddx);
210 greg 1.5 setcolor(ctmp, dtmp, dtmp, dtmp);
211     } else {
212     for (i = 0; i < np->dp->nd; i++)
213 greg 2.12 pt[i] = funvalue(sa[3+i], 4, lddx);
214 greg 2.7 vldx[0] = datavalue(np->dp, pt);
215 greg 2.12 dtmp = funvalue(sa[0], 5, vldx);
216 greg 1.5 setcolor(ctmp, dtmp, dtmp, dtmp);
217     }
218 greg 2.2 if (errno) {
219     objerror(np->mp, WARNING, "compute error");
220     return;
221     }
222 greg 1.5 if (dtmp <= FTINY)
223     return;
224     if (ldot > 0.0) {
225     /*
226     * Compute reflected non-diffuse component.
227     */
228 greg 2.6 if (np->mp->otype == MAT_MFUNC | np->mp->otype == MAT_MDATA)
229 greg 1.6 multcolor(ctmp, np->mcolor);
230     dtmp = ldot * omega * np->rspec;
231 greg 1.5 scalecolor(ctmp, dtmp);
232     addcolor(cval, ctmp);
233     } else {
234     /*
235     * Compute transmitted non-diffuse component.
236     */
237 greg 2.6 if (np->mp->otype == MAT_TFUNC | np->mp->otype == MAT_TDATA)
238 greg 1.6 multcolor(ctmp, np->mcolor);
239 greg 1.5 dtmp = -ldot * omega * np->tspec;
240     scalecolor(ctmp, dtmp);
241     addcolor(cval, ctmp);
242     }
243 greg 2.12 #undef lddx
244 greg 1.1 }
245    
246    
247 greg 2.15 int
248     m_brdf(m, r) /* color a ray that hit a BRDTfunc material */
249 greg 1.1 register OBJREC *m;
250     register RAY *r;
251     {
252 greg 2.15 int hitfront = 1;
253 greg 1.1 BRDFDAT nd;
254 greg 2.6 RAY sr;
255 greg 1.7 double transtest, transdist;
256 greg 2.6 int hasrefl, hastrans;
257 greg 1.1 COLOR ctmp;
258 greg 2.14 FVECT vtmp;
259 greg 2.6 register MFUNC *mf;
260 greg 1.1 register int i;
261 greg 1.5 /* check arguments */
262 greg 2.6 if (m->oargs.nsargs < 10 | m->oargs.nfargs < 9)
263     objerror(m, USER, "bad # arguments");
264     nd.mp = m;
265     nd.pr = r;
266     /* dummy values */
267     nd.rspec = nd.tspec = 1.0;
268     nd.trans = 0.5;
269     /* diffuse reflectance */
270     if (r->rod > 0.0)
271     setcolor(nd.rdiff, m->oargs.farg[0],
272     m->oargs.farg[1],
273     m->oargs.farg[2]);
274     else
275     setcolor(nd.rdiff, m->oargs.farg[3],
276     m->oargs.farg[4],
277     m->oargs.farg[5]);
278     /* diffuse transmittance */
279     setcolor(nd.tdiff, m->oargs.farg[6],
280     m->oargs.farg[7],
281     m->oargs.farg[8]);
282     /* get modifiers */
283     raytexture(r, m->omod);
284     nd.pdot = raynormal(nd.pnorm, r); /* perturb normal */
285     if (r->rod < 0.0) { /* orient perturbed values */
286     nd.pdot = -nd.pdot;
287     for (i = 0; i < 3; i++) {
288     nd.pnorm[i] = -nd.pnorm[i];
289     r->pert[i] = -r->pert[i];
290     }
291 greg 2.15 hitfront = 0;
292 greg 1.5 }
293 greg 2.6 copycolor(nd.mcolor, r->pcol); /* get pattern color */
294     multcolor(nd.rdiff, nd.mcolor); /* modify diffuse values */
295     multcolor(nd.tdiff, nd.mcolor);
296     hasrefl = bright(nd.rdiff) > FTINY;
297     hastrans = bright(nd.tdiff) > FTINY;
298     /* load cal file */
299     nd.dp = NULL;
300     mf = getfunc(m, 9, 0x3f, 0);
301     /* compute transmitted ray */
302     setbrdfunc(&nd);
303     transtest = 0;
304 greg 2.8 transdist = r->rot;
305 greg 2.6 errno = 0;
306     setcolor(ctmp, evalue(mf->ep[3]),
307     evalue(mf->ep[4]),
308     evalue(mf->ep[5]));
309     if (errno)
310     objerror(m, WARNING, "compute error");
311     else if (rayorigin(&sr, r, TRANS, bright(ctmp)) == 0) {
312     if (!(r->crtype & SHADOW) &&
313     DOT(r->pert,r->pert) > FTINY*FTINY) {
314     for (i = 0; i < 3; i++) /* perturb direction */
315     sr.rdir[i] = r->rdir[i] - .75*r->pert[i];
316     if (normalize(sr.rdir) == 0.0) {
317     objerror(m, WARNING, "illegal perturbation");
318     VCOPY(sr.rdir, r->rdir);
319     }
320     } else {
321     VCOPY(sr.rdir, r->rdir);
322     transtest = 2;
323     }
324     rayvalue(&sr);
325     multcolor(sr.rcol, ctmp);
326     addcolor(r->rcol, sr.rcol);
327     transtest *= bright(sr.rcol);
328     transdist = r->rot + sr.rt;
329     }
330     if (r->crtype & SHADOW) /* the rest is shadow */
331 greg 2.10 return(1);
332 greg 2.6 /* compute reflected ray */
333     setbrdfunc(&nd);
334     errno = 0;
335     setcolor(ctmp, evalue(mf->ep[0]),
336     evalue(mf->ep[1]),
337     evalue(mf->ep[2]));
338     if (errno)
339     objerror(m, WARNING, "compute error");
340     else if (rayorigin(&sr, r, REFLECTED, bright(ctmp)) == 0) {
341     for (i = 0; i < 3; i++)
342     sr.rdir[i] = r->rdir[i] + 2.0*nd.pdot*nd.pnorm[i];
343     rayvalue(&sr);
344     multcolor(sr.rcol, ctmp);
345     addcolor(r->rcol, sr.rcol);
346     }
347     /* compute ambient */
348     if (hasrefl) {
349 greg 2.15 if (!hitfront)
350 greg 2.6 flipsurface(r);
351 greg 2.15 ambient(ctmp, r, nd.pnorm);
352 greg 2.6 multcolor(ctmp, nd.rdiff);
353     addcolor(r->rcol, ctmp); /* add to returned color */
354 greg 2.15 if (!hitfront)
355 greg 2.6 flipsurface(r);
356     }
357     if (hastrans) { /* from other side */
358 greg 2.15 if (hitfront)
359 greg 2.6 flipsurface(r);
360 greg 2.15 vtmp[0] = -nd.pnorm[0];
361     vtmp[1] = -nd.pnorm[1];
362     vtmp[2] = -nd.pnorm[2];
363 greg 2.14 ambient(ctmp, r, vtmp);
364 greg 2.6 multcolor(ctmp, nd.tdiff);
365     addcolor(r->rcol, ctmp);
366 greg 2.15 if (hitfront)
367 greg 2.6 flipsurface(r);
368     }
369     if (hasrefl | hastrans || m->oargs.sarg[6][0] != '0')
370     direct(r, dirbrdf, &nd); /* add direct component */
371     /* check distance */
372     if (transtest > bright(r->rcol))
373     r->rt = transdist;
374 greg 2.10
375     return(1);
376 greg 2.6 }
377    
378    
379    
380 greg 2.15 int
381     m_brdf2(m, r) /* color a ray that hit a BRDF material */
382 greg 2.6 register OBJREC *m;
383     register RAY *r;
384     {
385     BRDFDAT nd;
386     COLOR ctmp;
387 greg 2.14 FVECT vtmp;
388 greg 2.6 double dtmp;
389     /* always a shadow */
390     if (r->crtype & SHADOW)
391 greg 2.10 return(1);
392 greg 2.6 /* check arguments */
393     if (m->oargs.nsargs < (hasdata(m->otype)?4:2) | m->oargs.nfargs <
394     (m->otype==MAT_TFUNC|m->otype==MAT_TDATA?6:4))
395 greg 1.1 objerror(m, USER, "bad # arguments");
396     nd.mp = m;
397     nd.pr = r;
398 greg 2.6 /* get material color */
399     setcolor(nd.mcolor, m->oargs.farg[0],
400     m->oargs.farg[1],
401     m->oargs.farg[2]);
402 greg 1.5 /* get specular component */
403     nd.rspec = m->oargs.farg[3];
404 greg 2.6 /* compute transmittance */
405     if (m->otype == MAT_TFUNC | m->otype == MAT_TDATA) {
406 greg 1.5 nd.trans = m->oargs.farg[4]*(1.0 - nd.rspec);
407     nd.tspec = nd.trans * m->oargs.farg[5];
408 greg 2.6 dtmp = nd.trans - nd.tspec;
409     setcolor(nd.tdiff, dtmp, dtmp, dtmp);
410     } else {
411     nd.tspec = nd.trans = 0.0;
412     setcolor(nd.tdiff, 0.0, 0.0, 0.0);
413     }
414     /* compute reflectance */
415     dtmp = 1.0 - nd.trans - nd.rspec;
416     setcolor(nd.rdiff, dtmp, dtmp, dtmp);
417 greg 2.11 /* check for back side */
418     if (r->rod < 0.0) {
419     if (!backvis && m->otype != MAT_TFUNC
420     && m->otype != MAT_TDATA) {
421     raytrans(r);
422     return(1);
423     }
424     flipsurface(r); /* reorient if backvis */
425     }
426 greg 1.5 /* get modifiers */
427     raytexture(r, m->omod);
428     nd.pdot = raynormal(nd.pnorm, r); /* perturb normal */
429     multcolor(nd.mcolor, r->pcol); /* modify material color */
430 greg 2.6 multcolor(nd.rdiff, nd.mcolor);
431     multcolor(nd.tdiff, nd.mcolor);
432 greg 1.1 /* load auxiliary files */
433 greg 2.2 if (hasdata(m->otype)) {
434 greg 1.1 nd.dp = getdata(m->oargs.sarg[1]);
435 greg 2.6 getfunc(m, 2, 0, 0);
436 greg 1.1 } else {
437     nd.dp = NULL;
438 greg 2.6 getfunc(m, 1, 0, 0);
439 greg 1.1 }
440     /* compute ambient */
441 greg 2.6 if (nd.trans < 1.0-FTINY) {
442 greg 2.13 ambient(ctmp, r, nd.pnorm);
443 greg 2.6 scalecolor(ctmp, 1.0-nd.trans);
444 greg 1.1 multcolor(ctmp, nd.mcolor); /* modified by material color */
445     addcolor(r->rcol, ctmp); /* add to returned color */
446 greg 1.5 }
447 greg 2.6 if (nd.trans > FTINY) { /* from other side */
448 greg 1.5 flipsurface(r);
449 greg 2.14 vtmp[0] = -nd.pnorm[0];
450     vtmp[1] = -nd.pnorm[1];
451     vtmp[2] = -nd.pnorm[2];
452     ambient(ctmp, r, vtmp);
453 greg 2.6 scalecolor(ctmp, nd.trans);
454 greg 1.5 multcolor(ctmp, nd.mcolor);
455     addcolor(r->rcol, ctmp);
456     flipsurface(r);
457 greg 1.1 }
458     /* add direct component */
459     direct(r, dirbrdf, &nd);
460 greg 2.10
461     return(1);
462 greg 1.10 }
463    
464    
465 greg 2.15 int
466 greg 1.10 setbrdfunc(np) /* set up brdf function and variables */
467     register BRDFDAT *np;
468     {
469     FVECT vec;
470    
471     if (setfunc(np->mp, np->pr) == 0)
472     return(0); /* it's OK, setfunc says we're done */
473     /* else (re)assign special variables */
474     multv3(vec, np->pnorm, funcxf.xfm);
475     varset("NxP", '=', vec[0]/funcxf.sca);
476     varset("NyP", '=', vec[1]/funcxf.sca);
477     varset("NzP", '=', vec[2]/funcxf.sca);
478 greg 1.11 varset("RdotP", '=', np->pdot <= -1.0 ? -1.0 :
479     np->pdot >= 1.0 ? 1.0 : np->pdot);
480 greg 1.10 varset("CrP", '=', colval(np->mcolor,RED));
481     varset("CgP", '=', colval(np->mcolor,GRN));
482     varset("CbP", '=', colval(np->mcolor,BLU));
483     return(1);
484 greg 1.1 }