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

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id$";
3 #endif
4 /*
5 * Shading for materials with arbitrary BRDF's
6 */
7
8 /* ====================================================================
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 #include "ray.h"
66
67 #include "data.h"
68
69 #include "otypes.h"
70
71 #include "func.h"
72
73 /*
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 * of the direction to the light source. (Data modification functions
79 * are passed the source direction as args 2-4.)
80 * 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 * 2+ func funcfile transform
85 * 0
86 * 4+ red grn blu specularity A5 ..
87 *
88 * Arguments for MAT_PDATA and MAT_MDATA are:
89 * 4+ func datafile funcfile v0 .. transform
90 * 0
91 * 4+ red grn blu specularity A5 ..
92 *
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 * 9+ rdf gdf bdf
110 * rdb gdb bdb
111 * rdt gdt bdt A10 ..
112 *
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 * CrP, CgP, CbP - perturbed material color (or pattern)
118 */
119
120 typedef struct {
121 OBJREC *mp; /* material pointer */
122 RAY *pr; /* intersected ray */
123 DATARRAY *dp; /* data array for PDATA, MDATA or TDATA */
124 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 FVECT pnorm; /* perturbed surface normal */
131 double pdot; /* perturbed dot product */
132 } BRDFDAT; /* BRDF material data */
133
134
135 static void
136 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 FVECT ldx;
146 static double vldx[5], pt[MAXDIM];
147 register char **sa;
148 register int i;
149 #define lddx (vldx+1)
150
151 setcolor(cval, 0.0, 0.0, 0.0);
152
153 ldot = DOT(np->pnorm, ldir);
154
155 if (ldot <= FTINY && ldot >= -FTINY)
156 return; /* too close to grazing */
157
158 if (ldot < 0.0 ? np->trans <= FTINY : np->trans >= 1.0-FTINY)
159 return; /* wrong side */
160
161 if (ldot > 0.0) {
162 /*
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 copycolor(ctmp, np->rdiff);
168 dtmp = ldot * omega / PI;
169 scalecolor(ctmp, dtmp);
170 addcolor(cval, ctmp);
171 } else {
172 /*
173 * Diffuse transmitted component.
174 */
175 copycolor(ctmp, np->tdiff);
176 dtmp = -ldot * omega / PI;
177 scalecolor(ctmp, dtmp);
178 addcolor(cval, ctmp);
179 }
180 if (ldot > 0.0 ? np->rspec <= FTINY : np->tspec <= FTINY)
181 return; /* no specular component */
182 /* set up function */
183 setbrdfunc(np);
184 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 lddx[i] = ldx[i]/funcxf.sca;
190 lddx[3] = omega;
191 /* compute BRTDF */
192 if (np->mp->otype == MAT_BRTDF) {
193 if (sa[6][0] == '0') /* special case */
194 colval(ctmp,RED) = 0.0;
195 else
196 colval(ctmp,RED) = funvalue(sa[6], 4, lddx);
197 if (!strcmp(sa[7],sa[6]))
198 colval(ctmp,GRN) = colval(ctmp,RED);
199 else
200 colval(ctmp,GRN) = funvalue(sa[7], 4, lddx);
201 if (!strcmp(sa[8],sa[6]))
202 colval(ctmp,BLU) = colval(ctmp,RED);
203 else if (!strcmp(sa[8],sa[7]))
204 colval(ctmp,BLU) = colval(ctmp,GRN);
205 else
206 colval(ctmp,BLU) = funvalue(sa[8], 4, lddx);
207 dtmp = bright(ctmp);
208 } else if (np->dp == NULL) {
209 dtmp = funvalue(sa[0], 4, lddx);
210 setcolor(ctmp, dtmp, dtmp, dtmp);
211 } else {
212 for (i = 0; i < np->dp->nd; i++)
213 pt[i] = funvalue(sa[3+i], 4, lddx);
214 vldx[0] = datavalue(np->dp, pt);
215 dtmp = funvalue(sa[0], 5, vldx);
216 setcolor(ctmp, dtmp, dtmp, dtmp);
217 }
218 if (errno) {
219 objerror(np->mp, WARNING, "compute error");
220 return;
221 }
222 if (dtmp <= FTINY)
223 return;
224 if (ldot > 0.0) {
225 /*
226 * Compute reflected non-diffuse component.
227 */
228 if (np->mp->otype == MAT_MFUNC | np->mp->otype == MAT_MDATA)
229 multcolor(ctmp, np->mcolor);
230 dtmp = ldot * omega * np->rspec;
231 scalecolor(ctmp, dtmp);
232 addcolor(cval, ctmp);
233 } else {
234 /*
235 * Compute transmitted non-diffuse component.
236 */
237 if (np->mp->otype == MAT_TFUNC | np->mp->otype == MAT_TDATA)
238 multcolor(ctmp, np->mcolor);
239 dtmp = -ldot * omega * np->tspec;
240 scalecolor(ctmp, dtmp);
241 addcolor(cval, ctmp);
242 }
243 #undef lddx
244 }
245
246
247 int
248 m_brdf(m, r) /* color a ray that hit a BRDTfunc material */
249 register OBJREC *m;
250 register RAY *r;
251 {
252 int hitfront = 1;
253 BRDFDAT nd;
254 RAY sr;
255 double transtest, transdist;
256 int hasrefl, hastrans;
257 COLOR ctmp;
258 FVECT vtmp;
259 register MFUNC *mf;
260 register int i;
261 /* check arguments */
262 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 hitfront = 0;
292 }
293 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 transdist = r->rot;
305 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 return(1);
332 /* 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 if (!hitfront)
350 flipsurface(r);
351 ambient(ctmp, r, nd.pnorm);
352 multcolor(ctmp, nd.rdiff);
353 addcolor(r->rcol, ctmp); /* add to returned color */
354 if (!hitfront)
355 flipsurface(r);
356 }
357 if (hastrans) { /* from other side */
358 if (hitfront)
359 flipsurface(r);
360 vtmp[0] = -nd.pnorm[0];
361 vtmp[1] = -nd.pnorm[1];
362 vtmp[2] = -nd.pnorm[2];
363 ambient(ctmp, r, vtmp);
364 multcolor(ctmp, nd.tdiff);
365 addcolor(r->rcol, ctmp);
366 if (hitfront)
367 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
375 return(1);
376 }
377
378
379
380 int
381 m_brdf2(m, r) /* color a ray that hit a BRDF material */
382 register OBJREC *m;
383 register RAY *r;
384 {
385 BRDFDAT nd;
386 COLOR ctmp;
387 FVECT vtmp;
388 double dtmp;
389 /* always a shadow */
390 if (r->crtype & SHADOW)
391 return(1);
392 /* 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 objerror(m, USER, "bad # arguments");
396 nd.mp = m;
397 nd.pr = r;
398 /* get material color */
399 setcolor(nd.mcolor, m->oargs.farg[0],
400 m->oargs.farg[1],
401 m->oargs.farg[2]);
402 /* get specular component */
403 nd.rspec = m->oargs.farg[3];
404 /* compute transmittance */
405 if (m->otype == MAT_TFUNC | m->otype == MAT_TDATA) {
406 nd.trans = m->oargs.farg[4]*(1.0 - nd.rspec);
407 nd.tspec = nd.trans * m->oargs.farg[5];
408 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 /* 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 /* 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 multcolor(nd.rdiff, nd.mcolor);
431 multcolor(nd.tdiff, nd.mcolor);
432 /* load auxiliary files */
433 if (hasdata(m->otype)) {
434 nd.dp = getdata(m->oargs.sarg[1]);
435 getfunc(m, 2, 0, 0);
436 } else {
437 nd.dp = NULL;
438 getfunc(m, 1, 0, 0);
439 }
440 /* compute ambient */
441 if (nd.trans < 1.0-FTINY) {
442 ambient(ctmp, r, nd.pnorm);
443 scalecolor(ctmp, 1.0-nd.trans);
444 multcolor(ctmp, nd.mcolor); /* modified by material color */
445 addcolor(r->rcol, ctmp); /* add to returned color */
446 }
447 if (nd.trans > FTINY) { /* from other side */
448 flipsurface(r);
449 vtmp[0] = -nd.pnorm[0];
450 vtmp[1] = -nd.pnorm[1];
451 vtmp[2] = -nd.pnorm[2];
452 ambient(ctmp, r, vtmp);
453 scalecolor(ctmp, nd.trans);
454 multcolor(ctmp, nd.mcolor);
455 addcolor(r->rcol, ctmp);
456 flipsurface(r);
457 }
458 /* add direct component */
459 direct(r, dirbrdf, &nd);
460
461 return(1);
462 }
463
464
465 int
466 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 varset("RdotP", '=', np->pdot <= -1.0 ? -1.0 :
479 np->pdot >= 1.0 ? 1.0 : np->pdot);
480 varset("CrP", '=', colval(np->mcolor,RED));
481 varset("CgP", '=', colval(np->mcolor,GRN));
482 varset("CbP", '=', colval(np->mcolor,BLU));
483 return(1);
484 }