ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/m_brdf.c
Revision: 2.2
Committed: Mon Nov 25 09:51:03 1991 UTC (32 years, 5 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.1: +18 -25 lines
Log Message:
changed function file calls to allow expressions instead of just vars

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