ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/m_brdf.c
Revision: 1.10
Committed: Mon Jun 17 08:53:58 1991 UTC (32 years, 10 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.9: +22 -11 lines
Log Message:
fixed potential bug in setting of variables

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