ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/m_brdf.c
Revision: 1.5
Committed: Tue May 7 17:19:52 1991 UTC (32 years, 11 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.4: +212 -54 lines
Log Message:
added MAT_TFUNC, MAT_TDATA and MAT_BRTDF types

File Contents

# Content
1 /* Copyright (c) 1990 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 COLOR scolor; /* color of specular reflection */
70 double rspec; /* specular reflection */
71 double rdiff; /* diffuse reflection */
72 double trans; /* transmissivity */
73 double tspec; /* specular transmission */
74 double tdiff; /* diffuse transmission */
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 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 if (ldot < 0.0 ? np->trans <= FTINY : np->trans >= 1.0-FTINY)
101 return; /* wrong side */
102
103 if (ldot > 0.0 && np->rdiff > FTINY) {
104 /*
105 * Compute and add diffuse reflected component to returned
106 * color. The diffuse reflected component will always be
107 * modified by the color of the material.
108 */
109 copycolor(ctmp, np->mcolor);
110 dtmp = ldot * omega * np->rdiff / PI;
111 scalecolor(ctmp, dtmp);
112 addcolor(cval, ctmp);
113 }
114 if (ldot < 0.0 && np->tdiff > FTINY) {
115 /*
116 * Diffuse transmitted component.
117 */
118 copycolor(ctmp, np->mcolor);
119 dtmp = -ldot * omega * np->tdiff / 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 setfunc(np->mp, np->pr);
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 ldx[i] /= funcxf.sca;
133 /* compute BRTDF */
134 if (np->mp->otype == MAT_BRTDF) {
135 colval(ctmp,RED) = funvalue(sa[6], 3, ldx);
136 if (sa[7] == sa[6])
137 colval(ctmp,GRN) = colval(ctmp,RED);
138 else
139 colval(ctmp,GRN) = funvalue(sa[7], 3, ldx);
140 if (sa[8] == sa[6])
141 colval(ctmp,BLU) = colval(ctmp,RED);
142 else if (sa[8] == sa[7])
143 colval(ctmp,BLU) = colval(ctmp,GRN);
144 else
145 colval(ctmp,BLU) = funvalue(sa[8], 3, ldx);
146 dtmp = bright(ctmp);
147 } else if (np->dp == NULL) {
148 dtmp = funvalue(sa[0], 3, ldx);
149 setcolor(ctmp, dtmp, dtmp, dtmp);
150 } else {
151 for (i = 0; i < np->dp->nd; i++)
152 pt[i] = funvalue(sa[3+i], 3, ldx);
153 dtmp = datavalue(np->dp, pt);
154 dtmp = funvalue(sa[0], 1, &dtmp);
155 setcolor(ctmp, dtmp, dtmp, dtmp);
156 }
157 if (errno)
158 goto computerr;
159 if (dtmp <= FTINY)
160 return;
161 if (ldot > 0.0) {
162 /*
163 * Compute reflected non-diffuse component.
164 */
165 multcolor(ctmp, np->scolor);
166 dtmp = ldot * omega;
167 scalecolor(ctmp, dtmp);
168 addcolor(cval, ctmp);
169 } else {
170 /*
171 * Compute transmitted non-diffuse component.
172 */
173 dtmp = -ldot * omega * np->tspec;
174 scalecolor(ctmp, dtmp);
175 addcolor(cval, ctmp);
176 }
177 return;
178 computerr:
179 objerror(np->mp, WARNING, "compute error");
180 return;
181 }
182
183
184 m_brdf(m, r) /* color a ray which hit a BRDF material */
185 register OBJREC *m;
186 register RAY *r;
187 {
188 int minsa, minfa;
189 BRDFDAT nd;
190 COLOR ctmp;
191 double dtmp;
192 FVECT vec;
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 r->rt = r->rot; /* default ray length */
238 /* load auxiliary files */
239 if (m->otype == MAT_PDATA || m->otype == MAT_MDATA
240 || m->otype == MAT_TDATA) {
241 nd.dp = getdata(m->oargs.sarg[1]);
242 for (i = 3; i < m->oargs.nsargs; i++)
243 if (m->oargs.sarg[i][0] == '-')
244 break;
245 if (i-3 != nd.dp->nd)
246 objerror(m, USER, "dimension error");
247 if (!fundefined(m->oargs.sarg[3]))
248 loadfunc(m->oargs.sarg[2]);
249 } else if (m->otype == MAT_BRTDF) {
250 nd.dp = NULL;
251 if (!fundefined(m->oargs.sarg[7]))
252 loadfunc(m->oargs.sarg[9]);
253 } else {
254 nd.dp = NULL;
255 if (!fundefined(m->oargs.sarg[0]))
256 loadfunc(m->oargs.sarg[1]);
257 }
258 /* set special variables */
259 setfunc(m, r);
260 multv3(vec, nd.pnorm, funcxf.xfm);
261 varset("NxP", '=', vec[0]/funcxf.sca);
262 varset("NyP", '=', vec[1]/funcxf.sca);
263 varset("NzP", '=', vec[2]/funcxf.sca);
264 varset("RdotP", '=', nd.pdot);
265 varset("CrP", '=', colval(nd.mcolor,RED));
266 varset("CgP", '=', colval(nd.mcolor,GRN));
267 varset("CbP", '=', colval(nd.mcolor,BLU));
268 /* compute transmitted ray */
269 if (m->otype == MAT_BRTDF && nd.tspec > FTINY) {
270 RAY sr;
271 errno = 0;
272 setcolor(ctmp, varvalue(m->oargs.sarg[0]),
273 varvalue(m->oargs.sarg[1]),
274 varvalue(m->oargs.sarg[2]));
275 scalecolor(ctmp, nd.tspec);
276 if (errno)
277 objerror(m, WARNING, "compute error");
278 else if ((dtmp = bright(ctmp)) > FTINY &&
279 rayorigin(&sr, r, TRANS, dtmp) == 0) {
280 VCOPY(sr.rdir, r->rdir);
281 rayvalue(&sr);
282 multcolor(sr.rcol, ctmp);
283 addcolor(r->rcol, sr.rcol);
284 if (dtmp > .5)
285 r->rt = r->rot + sr.rt;
286 }
287 }
288 if (r->crtype & SHADOW) /* the rest is shadow */
289 return;
290 if (nd.rspec > FTINY) { /* has specular component */
291 /* compute specular color */
292 if (m->otype == MAT_MFUNC || m->otype == MAT_MDATA)
293 copycolor(nd.scolor, nd.mcolor);
294 else
295 setcolor(nd.scolor, 1.0, 1.0, 1.0);
296 scalecolor(nd.scolor, nd.rspec);
297 /* compute reflected ray */
298 if (m->otype == MAT_BRTDF) {
299 RAY sr;
300 errno = 0;
301 setcolor(ctmp, varvalue(m->oargs.sarg[3]),
302 varvalue(m->oargs.sarg[4]),
303 varvalue(m->oargs.sarg[5]));
304 scalecolor(ctmp, nd.rspec);
305 if (errno)
306 objerror(m, WARNING, "compute error");
307 else if ((dtmp = bright(ctmp)) > FTINY &&
308 rayorigin(&sr, r, REFLECTED, dtmp) == 0) {
309 for (i = 0; i < 3; i++)
310 sr.rdir[i] = r->rdir[i] +
311 2.0*nd.pdot*nd.pnorm[i];
312 rayvalue(&sr);
313 multcolor(sr.rcol, ctmp);
314 addcolor(r->rcol, sr.rcol);
315 }
316 }
317 }
318 /* compute ambient */
319 if (nd.rdiff > FTINY) {
320 ambient(ctmp, r);
321 if (m->otype == MAT_BRTDF)
322 scalecolor(ctmp, nd.rdiff);
323 else
324 scalecolor(ctmp, 1.0-nd.trans);
325 multcolor(ctmp, nd.mcolor); /* modified by material color */
326 addcolor(r->rcol, ctmp); /* add to returned color */
327 }
328 if (nd.tdiff > FTINY) { /* from other side */
329 flipsurface(r);
330 ambient(ctmp, r);
331 if (m->otype == MAT_BRTDF)
332 scalecolor(ctmp, nd.tdiff);
333 else
334 scalecolor(ctmp, nd.trans);
335 multcolor(ctmp, nd.mcolor);
336 addcolor(r->rcol, ctmp);
337 flipsurface(r);
338 }
339 /* add direct component */
340 direct(r, dirbrdf, &nd);
341 }