ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/m_brdf.c
Revision: 2.6
Committed: Thu May 27 15:28:01 1993 UTC (30 years, 11 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.5: +175 -121 lines
Log Message:
removed approximation to Fresnel reflection, since the direct
component was not being calculated accordingly (BRDF not bidirectional)
changed BRDTfunc arguments and operation, fixed one or two bugs there also

File Contents

# User Rev Content
1 greg 1.7 /* Copyright (c) 1991 Regents of the University of California */
2 greg 1.1
3     #ifndef lint
4     static char SCCSid[] = "$SunId$ LBL";
5     #endif
6    
7     /*
8     * Shading for materials with arbitrary BRDF's
9     */
10    
11     #include "ray.h"
12    
13     #include "data.h"
14    
15     #include "otypes.h"
16    
17 greg 2.2 #include "func.h"
18    
19 greg 1.1 /*
20     * Arguments to this material include the color and specularity.
21     * String arguments include the reflection function and files.
22     * The BRDF is currently used just for the specular component to light
23     * sources. Reflectance values or data coordinates are functions
24     * of the direction to the light source.
25     * We orient the surface towards the incoming ray, so a single
26     * surface can be used to represent an infinitely thin object.
27     *
28     * Arguments for MAT_PFUNC and MAT_MFUNC are:
29 greg 1.4 * 2+ func funcfile transform
30 greg 1.1 * 0
31 greg 1.4 * 4+ red grn blu specularity A5 ..
32 greg 1.1 *
33     * Arguments for MAT_PDATA and MAT_MDATA are:
34 greg 1.4 * 4+ func datafile funcfile v0 .. transform
35 greg 1.1 * 0
36 greg 1.4 * 4+ red grn blu specularity A5 ..
37 greg 1.5 *
38     * Arguments for MAT_TFUNC are:
39     * 2+ func funcfile transform
40     * 0
41     * 4+ red grn blu rspec trans tspec A7 ..
42     *
43     * Arguments for MAT_TDATA are:
44     * 4+ func datafile funcfile v0 .. transform
45     * 0
46     * 4+ red grn blu rspec trans tspec A7 ..
47     *
48     * Arguments for the more general MAT_BRTDF are:
49     * 10+ rrefl grefl brefl
50     * rtrns gtrns btrns
51     * rbrtd gbrtd bbrtd
52     * funcfile transform
53     * 0
54 greg 2.6 * 9+ rdf gdf bdf
55     * rdb gdb bdb
56     * rdt gdt bdt A10 ..
57 greg 1.5 *
58     * In addition to the normal variables available to functions,
59     * we define the following:
60     * NxP, NyP, NzP - perturbed surface normal
61     * RdotP - perturbed ray dot product
62 greg 2.6 * CrP, CgP, CbP - perturbed material color (or pattern)
63 greg 1.1 */
64    
65     typedef struct {
66     OBJREC *mp; /* material pointer */
67     RAY *pr; /* intersected ray */
68 greg 1.5 DATARRAY *dp; /* data array for PDATA, MDATA or TDATA */
69 greg 2.6 COLOR mcolor; /* material (or pattern) color */
70     COLOR rdiff; /* diffuse reflection */
71     COLOR tdiff; /* diffuse transmission */
72     double rspec; /* specular reflectance (1 for BRDTF) */
73     double trans; /* transmissivity (.5 for BRDTF) */
74     double tspec; /* specular transmittance (1 for BRDTF) */
75 greg 1.1 FVECT pnorm; /* perturbed surface normal */
76     double pdot; /* perturbed dot product */
77     } BRDFDAT; /* BRDF material data */
78    
79    
80     dirbrdf(cval, np, ldir, omega) /* compute source contribution */
81     COLOR cval; /* returned coefficient */
82     register BRDFDAT *np; /* material data */
83     FVECT ldir; /* light source direction */
84     double omega; /* light source size */
85     {
86     double ldot;
87     double dtmp;
88     COLOR ctmp;
89 greg 1.4 FVECT ldx;
90 greg 2.3 double lddx[3], pt[MAXDIM];
91 greg 1.5 register char **sa;
92 greg 1.1 register int i;
93    
94     setcolor(cval, 0.0, 0.0, 0.0);
95    
96     ldot = DOT(np->pnorm, ldir);
97    
98 greg 1.5 if (ldot <= FTINY && ldot >= -FTINY)
99     return; /* too close to grazing */
100 greg 2.6
101 greg 1.5 if (ldot < 0.0 ? np->trans <= FTINY : np->trans >= 1.0-FTINY)
102 greg 1.1 return; /* wrong side */
103    
104 greg 2.6 if (ldot > 0.0) {
105 greg 1.1 /*
106     * Compute and add diffuse reflected component to returned
107     * color. The diffuse reflected component will always be
108     * modified by the color of the material.
109     */
110 greg 2.6 copycolor(ctmp, np->rdiff);
111     dtmp = ldot * omega / PI;
112 greg 1.1 scalecolor(ctmp, dtmp);
113     addcolor(cval, ctmp);
114 greg 2.6 } else {
115 greg 1.1 /*
116 greg 1.5 * Diffuse transmitted component.
117 greg 1.1 */
118 greg 2.6 copycolor(ctmp, np->tdiff);
119     dtmp = -ldot * omega / PI;
120 greg 1.5 scalecolor(ctmp, dtmp);
121     addcolor(cval, ctmp);
122 greg 1.1 }
123 greg 1.5 if (ldot > 0.0 ? np->rspec <= FTINY : np->tspec <= FTINY)
124     return; /* no specular component */
125     /* set up function */
126 greg 1.10 setbrdfunc(np);
127 greg 1.5 sa = np->mp->oargs.sarg;
128     errno = 0;
129     /* transform light vector */
130     multv3(ldx, ldir, funcxf.xfm);
131     for (i = 0; i < 3; i++)
132 greg 2.3 lddx[i] = ldx[i]/funcxf.sca;
133 greg 1.5 /* compute BRTDF */
134     if (np->mp->otype == MAT_BRTDF) {
135 greg 2.6 if (sa[6][0] == '0') /* special case */
136     colval(ctmp,RED) = 0.0;
137     else
138     colval(ctmp,RED) = funvalue(sa[6], 3, lddx);
139 greg 1.7 if (!strcmp(sa[7],sa[6]))
140 greg 1.5 colval(ctmp,GRN) = colval(ctmp,RED);
141     else
142 greg 2.3 colval(ctmp,GRN) = funvalue(sa[7], 3, lddx);
143 greg 1.7 if (!strcmp(sa[8],sa[6]))
144 greg 1.5 colval(ctmp,BLU) = colval(ctmp,RED);
145 greg 1.7 else if (!strcmp(sa[8],sa[7]))
146 greg 1.5 colval(ctmp,BLU) = colval(ctmp,GRN);
147     else
148 greg 2.3 colval(ctmp,BLU) = funvalue(sa[8], 3, lddx);
149 greg 1.5 dtmp = bright(ctmp);
150     } else if (np->dp == NULL) {
151 greg 2.3 dtmp = funvalue(sa[0], 3, lddx);
152 greg 1.5 setcolor(ctmp, dtmp, dtmp, dtmp);
153     } else {
154     for (i = 0; i < np->dp->nd; i++)
155 greg 2.3 pt[i] = funvalue(sa[3+i], 3, lddx);
156 greg 1.5 dtmp = datavalue(np->dp, pt);
157     dtmp = funvalue(sa[0], 1, &dtmp);
158     setcolor(ctmp, dtmp, dtmp, dtmp);
159     }
160 greg 2.2 if (errno) {
161     objerror(np->mp, WARNING, "compute error");
162     return;
163     }
164 greg 1.5 if (dtmp <= FTINY)
165     return;
166     if (ldot > 0.0) {
167     /*
168     * Compute reflected non-diffuse component.
169     */
170 greg 2.6 if (np->mp->otype == MAT_MFUNC | np->mp->otype == MAT_MDATA)
171 greg 1.6 multcolor(ctmp, np->mcolor);
172     dtmp = ldot * omega * np->rspec;
173 greg 1.5 scalecolor(ctmp, dtmp);
174     addcolor(cval, ctmp);
175     } else {
176     /*
177     * Compute transmitted non-diffuse component.
178     */
179 greg 2.6 if (np->mp->otype == MAT_TFUNC | np->mp->otype == MAT_TDATA)
180 greg 1.6 multcolor(ctmp, np->mcolor);
181 greg 1.5 dtmp = -ldot * omega * np->tspec;
182     scalecolor(ctmp, dtmp);
183     addcolor(cval, ctmp);
184     }
185 greg 1.1 }
186    
187    
188 greg 2.6 m_brdf(m, r) /* color a ray which hit a BRDTF material */
189 greg 1.1 register OBJREC *m;
190     register RAY *r;
191     {
192     BRDFDAT nd;
193 greg 2.6 RAY sr;
194 greg 1.7 double transtest, transdist;
195 greg 2.6 int hasrefl, hastrans;
196 greg 1.1 COLOR ctmp;
197 greg 2.6 double dtmp;
198     register MFUNC *mf;
199 greg 1.1 register int i;
200 greg 1.5 /* check arguments */
201 greg 2.6 if (m->oargs.nsargs < 10 | m->oargs.nfargs < 9)
202     objerror(m, USER, "bad # arguments");
203     nd.mp = m;
204     nd.pr = r;
205     /* dummy values */
206     nd.rspec = nd.tspec = 1.0;
207     nd.trans = 0.5;
208     /* diffuse reflectance */
209     if (r->rod > 0.0)
210     setcolor(nd.rdiff, m->oargs.farg[0],
211     m->oargs.farg[1],
212     m->oargs.farg[2]);
213     else
214     setcolor(nd.rdiff, m->oargs.farg[3],
215     m->oargs.farg[4],
216     m->oargs.farg[5]);
217     /* diffuse transmittance */
218     setcolor(nd.tdiff, m->oargs.farg[6],
219     m->oargs.farg[7],
220     m->oargs.farg[8]);
221     /* get modifiers */
222     raytexture(r, m->omod);
223     nd.pdot = raynormal(nd.pnorm, r); /* perturb normal */
224     if (r->rod < 0.0) { /* orient perturbed values */
225     nd.pdot = -nd.pdot;
226     for (i = 0; i < 3; i++) {
227     nd.pnorm[i] = -nd.pnorm[i];
228     r->pert[i] = -r->pert[i];
229     }
230 greg 1.5 }
231 greg 2.6 copycolor(nd.mcolor, r->pcol); /* get pattern color */
232     multcolor(nd.rdiff, nd.mcolor); /* modify diffuse values */
233     multcolor(nd.tdiff, nd.mcolor);
234     hasrefl = bright(nd.rdiff) > FTINY;
235     hastrans = bright(nd.tdiff) > FTINY;
236     /* load cal file */
237     nd.dp = NULL;
238     mf = getfunc(m, 9, 0x3f, 0);
239     /* compute transmitted ray */
240     setbrdfunc(&nd);
241     transtest = 0;
242     errno = 0;
243     setcolor(ctmp, evalue(mf->ep[3]),
244     evalue(mf->ep[4]),
245     evalue(mf->ep[5]));
246     if (errno)
247     objerror(m, WARNING, "compute error");
248     else if (rayorigin(&sr, r, TRANS, bright(ctmp)) == 0) {
249     if (!(r->crtype & SHADOW) &&
250     DOT(r->pert,r->pert) > FTINY*FTINY) {
251     for (i = 0; i < 3; i++) /* perturb direction */
252     sr.rdir[i] = r->rdir[i] - .75*r->pert[i];
253     if (normalize(sr.rdir) == 0.0) {
254     objerror(m, WARNING, "illegal perturbation");
255     VCOPY(sr.rdir, r->rdir);
256     }
257     } else {
258     VCOPY(sr.rdir, r->rdir);
259     transtest = 2;
260     }
261     rayvalue(&sr);
262     multcolor(sr.rcol, ctmp);
263     addcolor(r->rcol, sr.rcol);
264     transtest *= bright(sr.rcol);
265     transdist = r->rot + sr.rt;
266     }
267     if (r->crtype & SHADOW) /* the rest is shadow */
268     return;
269     /* compute reflected ray */
270     setbrdfunc(&nd);
271     errno = 0;
272     setcolor(ctmp, evalue(mf->ep[0]),
273     evalue(mf->ep[1]),
274     evalue(mf->ep[2]));
275     if (errno)
276     objerror(m, WARNING, "compute error");
277     else if (rayorigin(&sr, r, REFLECTED, bright(ctmp)) == 0) {
278     for (i = 0; i < 3; i++)
279     sr.rdir[i] = r->rdir[i] + 2.0*nd.pdot*nd.pnorm[i];
280     rayvalue(&sr);
281     multcolor(sr.rcol, ctmp);
282     addcolor(r->rcol, sr.rcol);
283     }
284     /* compute ambient */
285     if (hasrefl) {
286     if (nd.pdot < 0.0)
287     flipsurface(r);
288     ambient(ctmp, r);
289     multcolor(ctmp, nd.rdiff);
290     addcolor(r->rcol, ctmp); /* add to returned color */
291     if (nd.pdot < 0.0)
292     flipsurface(r);
293     }
294     if (hastrans) { /* from other side */
295     if (nd.pdot > 0.0)
296     flipsurface(r);
297     ambient(ctmp, r);
298     multcolor(ctmp, nd.tdiff);
299     addcolor(r->rcol, ctmp);
300     if (nd.pdot > 0.0)
301     flipsurface(r);
302     }
303     if (hasrefl | hastrans || m->oargs.sarg[6][0] != '0')
304     direct(r, dirbrdf, &nd); /* add direct component */
305     /* check distance */
306     if (transtest > bright(r->rcol))
307     r->rt = transdist;
308     }
309    
310    
311    
312     m_brdf2(m, r) /* color a ray which hit a BRDF material */
313     register OBJREC *m;
314     register RAY *r;
315     {
316     BRDFDAT nd;
317     COLOR ctmp;
318     double dtmp;
319     /* always a shadow */
320     if (r->crtype & SHADOW)
321     return;
322     /* check arguments */
323     if (m->oargs.nsargs < (hasdata(m->otype)?4:2) | m->oargs.nfargs <
324     (m->otype==MAT_TFUNC|m->otype==MAT_TDATA?6:4))
325 greg 1.1 objerror(m, USER, "bad # arguments");
326     nd.mp = m;
327     nd.pr = r;
328 greg 2.6 /* get material color */
329     setcolor(nd.mcolor, m->oargs.farg[0],
330     m->oargs.farg[1],
331     m->oargs.farg[2]);
332 greg 1.5 /* get specular component */
333     nd.rspec = m->oargs.farg[3];
334 greg 2.6 /* compute transmittance */
335     if (m->otype == MAT_TFUNC | m->otype == MAT_TDATA) {
336 greg 1.5 nd.trans = m->oargs.farg[4]*(1.0 - nd.rspec);
337     nd.tspec = nd.trans * m->oargs.farg[5];
338 greg 2.6 dtmp = nd.trans - nd.tspec;
339     setcolor(nd.tdiff, dtmp, dtmp, dtmp);
340     } else {
341     nd.tspec = nd.trans = 0.0;
342     setcolor(nd.tdiff, 0.0, 0.0, 0.0);
343     }
344     /* compute reflectance */
345     dtmp = 1.0 - nd.trans - nd.rspec;
346     setcolor(nd.rdiff, dtmp, dtmp, dtmp);
347 greg 1.5 /* fix orientation */
348 greg 2.6 if (r->rod < 0.0)
349 greg 1.5 flipsurface(r);
350     /* get modifiers */
351     raytexture(r, m->omod);
352     nd.pdot = raynormal(nd.pnorm, r); /* perturb normal */
353     multcolor(nd.mcolor, r->pcol); /* modify material color */
354 greg 2.6 multcolor(nd.rdiff, nd.mcolor);
355     multcolor(nd.tdiff, nd.mcolor);
356 greg 1.1 /* load auxiliary files */
357 greg 2.2 if (hasdata(m->otype)) {
358 greg 1.1 nd.dp = getdata(m->oargs.sarg[1]);
359 greg 2.6 getfunc(m, 2, 0, 0);
360 greg 1.1 } else {
361     nd.dp = NULL;
362 greg 2.6 getfunc(m, 1, 0, 0);
363 greg 1.1 }
364     /* compute ambient */
365 greg 2.6 if (nd.trans < 1.0-FTINY) {
366 greg 1.1 ambient(ctmp, r);
367 greg 2.6 scalecolor(ctmp, 1.0-nd.trans);
368 greg 1.1 multcolor(ctmp, nd.mcolor); /* modified by material color */
369     addcolor(r->rcol, ctmp); /* add to returned color */
370 greg 1.5 }
371 greg 2.6 if (nd.trans > FTINY) { /* from other side */
372 greg 1.5 flipsurface(r);
373     ambient(ctmp, r);
374 greg 2.6 scalecolor(ctmp, nd.trans);
375 greg 1.5 multcolor(ctmp, nd.mcolor);
376     addcolor(r->rcol, ctmp);
377     flipsurface(r);
378 greg 1.1 }
379     /* add direct component */
380     direct(r, dirbrdf, &nd);
381 greg 1.10 }
382    
383    
384     setbrdfunc(np) /* set up brdf function and variables */
385     register BRDFDAT *np;
386     {
387     FVECT vec;
388    
389     if (setfunc(np->mp, np->pr) == 0)
390     return(0); /* it's OK, setfunc says we're done */
391     /* else (re)assign special variables */
392     multv3(vec, np->pnorm, funcxf.xfm);
393     varset("NxP", '=', vec[0]/funcxf.sca);
394     varset("NyP", '=', vec[1]/funcxf.sca);
395     varset("NzP", '=', vec[2]/funcxf.sca);
396 greg 1.11 varset("RdotP", '=', np->pdot <= -1.0 ? -1.0 :
397     np->pdot >= 1.0 ? 1.0 : np->pdot);
398 greg 1.10 varset("CrP", '=', colval(np->mcolor,RED));
399     varset("CgP", '=', colval(np->mcolor,GRN));
400     varset("CbP", '=', colval(np->mcolor,BLU));
401     return(1);
402 greg 1.1 }