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

# Content
1 /* Copyright (c) 1991 Regents of the University of California */
2
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 #include "func.h"
18
19 /*
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 * 2+ func funcfile transform
30 * 0
31 * 4+ red grn blu specularity A5 ..
32 *
33 * Arguments for MAT_PDATA and MAT_MDATA are:
34 * 4+ func datafile funcfile v0 .. transform
35 * 0
36 * 4+ red grn blu specularity A5 ..
37 *
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 * 9+ rdf gdf bdf
55 * rdb gdb bdb
56 * rdt gdt bdt A10 ..
57 *
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 * CrP, CgP, CbP - perturbed material color (or pattern)
63 */
64
65 typedef struct {
66 OBJREC *mp; /* material pointer */
67 RAY *pr; /* intersected ray */
68 DATARRAY *dp; /* data array for PDATA, MDATA or TDATA */
69 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 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 FVECT ldx;
90 double lddx[3], pt[MAXDIM];
91 register char **sa;
92 register int i;
93
94 setcolor(cval, 0.0, 0.0, 0.0);
95
96 ldot = DOT(np->pnorm, ldir);
97
98 if (ldot <= FTINY && ldot >= -FTINY)
99 return; /* too close to grazing */
100
101 if (ldot < 0.0 ? np->trans <= FTINY : np->trans >= 1.0-FTINY)
102 return; /* wrong side */
103
104 if (ldot > 0.0) {
105 /*
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 copycolor(ctmp, np->rdiff);
111 dtmp = ldot * omega / PI;
112 scalecolor(ctmp, dtmp);
113 addcolor(cval, ctmp);
114 } else {
115 /*
116 * Diffuse transmitted component.
117 */
118 copycolor(ctmp, np->tdiff);
119 dtmp = -ldot * omega / PI;
120 scalecolor(ctmp, dtmp);
121 addcolor(cval, ctmp);
122 }
123 if (ldot > 0.0 ? np->rspec <= FTINY : np->tspec <= FTINY)
124 return; /* no specular component */
125 /* set up function */
126 setbrdfunc(np);
127 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 lddx[i] = ldx[i]/funcxf.sca;
133 /* compute BRTDF */
134 if (np->mp->otype == MAT_BRTDF) {
135 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 if (!strcmp(sa[7],sa[6]))
140 colval(ctmp,GRN) = colval(ctmp,RED);
141 else
142 colval(ctmp,GRN) = funvalue(sa[7], 3, lddx);
143 if (!strcmp(sa[8],sa[6]))
144 colval(ctmp,BLU) = colval(ctmp,RED);
145 else if (!strcmp(sa[8],sa[7]))
146 colval(ctmp,BLU) = colval(ctmp,GRN);
147 else
148 colval(ctmp,BLU) = funvalue(sa[8], 3, lddx);
149 dtmp = bright(ctmp);
150 } else if (np->dp == NULL) {
151 dtmp = funvalue(sa[0], 3, lddx);
152 setcolor(ctmp, dtmp, dtmp, dtmp);
153 } else {
154 for (i = 0; i < np->dp->nd; i++)
155 pt[i] = funvalue(sa[3+i], 3, lddx);
156 dtmp = datavalue(np->dp, pt);
157 dtmp = funvalue(sa[0], 1, &dtmp);
158 setcolor(ctmp, dtmp, dtmp, dtmp);
159 }
160 if (errno) {
161 objerror(np->mp, WARNING, "compute error");
162 return;
163 }
164 if (dtmp <= FTINY)
165 return;
166 if (ldot > 0.0) {
167 /*
168 * Compute reflected non-diffuse component.
169 */
170 if (np->mp->otype == MAT_MFUNC | np->mp->otype == MAT_MDATA)
171 multcolor(ctmp, np->mcolor);
172 dtmp = ldot * omega * np->rspec;
173 scalecolor(ctmp, dtmp);
174 addcolor(cval, ctmp);
175 } else {
176 /*
177 * Compute transmitted non-diffuse component.
178 */
179 if (np->mp->otype == MAT_TFUNC | np->mp->otype == MAT_TDATA)
180 multcolor(ctmp, np->mcolor);
181 dtmp = -ldot * omega * np->tspec;
182 scalecolor(ctmp, dtmp);
183 addcolor(cval, ctmp);
184 }
185 }
186
187
188 m_brdf(m, r) /* color a ray which hit a BRDTF material */
189 register OBJREC *m;
190 register RAY *r;
191 {
192 BRDFDAT nd;
193 RAY sr;
194 double transtest, transdist;
195 int hasrefl, hastrans;
196 COLOR ctmp;
197 double dtmp;
198 register MFUNC *mf;
199 register int i;
200 /* check arguments */
201 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 }
231 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 objerror(m, USER, "bad # arguments");
326 nd.mp = m;
327 nd.pr = r;
328 /* get material color */
329 setcolor(nd.mcolor, m->oargs.farg[0],
330 m->oargs.farg[1],
331 m->oargs.farg[2]);
332 /* get specular component */
333 nd.rspec = m->oargs.farg[3];
334 /* compute transmittance */
335 if (m->otype == MAT_TFUNC | m->otype == MAT_TDATA) {
336 nd.trans = m->oargs.farg[4]*(1.0 - nd.rspec);
337 nd.tspec = nd.trans * m->oargs.farg[5];
338 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 /* fix orientation */
348 if (r->rod < 0.0)
349 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 multcolor(nd.rdiff, nd.mcolor);
355 multcolor(nd.tdiff, nd.mcolor);
356 /* load auxiliary files */
357 if (hasdata(m->otype)) {
358 nd.dp = getdata(m->oargs.sarg[1]);
359 getfunc(m, 2, 0, 0);
360 } else {
361 nd.dp = NULL;
362 getfunc(m, 1, 0, 0);
363 }
364 /* compute ambient */
365 if (nd.trans < 1.0-FTINY) {
366 ambient(ctmp, r);
367 scalecolor(ctmp, 1.0-nd.trans);
368 multcolor(ctmp, nd.mcolor); /* modified by material color */
369 addcolor(r->rcol, ctmp); /* add to returned color */
370 }
371 if (nd.trans > FTINY) { /* from other side */
372 flipsurface(r);
373 ambient(ctmp, r);
374 scalecolor(ctmp, nd.trans);
375 multcolor(ctmp, nd.mcolor);
376 addcolor(r->rcol, ctmp);
377 flipsurface(r);
378 }
379 /* add direct component */
380 direct(r, dirbrdf, &nd);
381 }
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 varset("RdotP", '=', np->pdot <= -1.0 ? -1.0 :
397 np->pdot >= 1.0 ? 1.0 : np->pdot);
398 varset("CrP", '=', colval(np->mcolor,RED));
399 varset("CgP", '=', colval(np->mcolor,GRN));
400 varset("CbP", '=', colval(np->mcolor,BLU));
401 return(1);
402 }