ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/normal.c
Revision: 1.1
Committed: Thu Feb 2 10:41:30 1989 UTC (35 years, 3 months ago) by greg
Content type: text/plain
Branch: MAIN
Log Message:
Initial revision

File Contents

# User Rev Content
1 greg 1.1 /* Copyright (c) 1986 Regents of the University of California */
2    
3     #ifndef lint
4     static char SCCSid[] = "$SunId$ LBL";
5     #endif
6    
7     /*
8     * normal.c - shading function for normal materials.
9     *
10     * 8/19/85
11     * 12/19/85 - added stuff for metals.
12     * 6/26/87 - improved specular model.
13     * 9/28/87 - added model for translucent materials.
14     */
15    
16     #include "ray.h"
17    
18     #include "source.h"
19    
20     #include "otypes.h"
21    
22     /*
23     * This routine uses portions of the reflection
24     * model described by Cook and Torrance.
25     * The computation of specular components has been simplified by
26     * numerous approximations and ommisions to improve speed.
27     * We orient the surface towards the incoming ray, so a single
28     * surface can be used to represent an infinitely thin object.
29     *
30     * Arguments for MAT_PLASTIC and MAT_METAL are:
31     * red grn blu specular-frac. facet-slope
32     *
33     * Arguments for MAT_TRANS are:
34     * red grn blu rspec rough trans tspec
35     */
36    
37     #define BSPEC(m) (6.0) /* specularity parameter b */
38    
39    
40     m_normal(m, r) /* color a ray which hit something normal */
41     register OBJREC *m;
42     register RAY *r;
43     {
44     double exp();
45     COLOR mcolor; /* color of this material */
46     COLOR scolor; /* color of specular component */
47     FVECT vrefl; /* vector in direction of reflected ray */
48     double alpha2; /* roughness squared times 2 */
49     RAY lr; /* ray to illumination source */
50     double rdiff, rspec; /* reflected specular, diffuse */
51     double trans; /* transmissivity */
52     double tdiff, tspec; /* transmitted specular, diffuse */
53     FVECT pnorm; /* perturbed surface normal */
54     double pdot; /* perturbed dot product */
55     double ldot;
56     double omega;
57     double dtmp;
58     COLOR ctmp;
59     register int i;
60    
61     if (m->oargs.nfargs != (m->otype == MAT_TRANS ? 7 : 5))
62     objerror(m, USER, "bad # arguments");
63     /* easy shadow test */
64     if (r->crtype & SHADOW && m->otype != MAT_TRANS)
65     return;
66     /* get material color */
67     setcolor(mcolor, m->oargs.farg[0],
68     m->oargs.farg[1],
69     m->oargs.farg[2]);
70     /* get roughness */
71     alpha2 = m->oargs.farg[4];
72     alpha2 *= 2.0 * alpha2;
73     /* reorient if necessary */
74     if (r->rod < 0.0)
75     flipsurface(r);
76     /* get modifiers */
77     raytexture(r, m->omod);
78     pdot = raynormal(pnorm, r); /* perturb normal */
79     multcolor(mcolor, r->pcol); /* modify material color */
80     /* get specular component */
81     rspec = m->oargs.farg[3];
82    
83     if (rspec > FTINY) { /* has specular component */
84     /* compute specular color */
85     if (m->otype == MAT_METAL)
86     copycolor(scolor, mcolor);
87     else
88     setcolor(scolor, 1.0, 1.0, 1.0);
89     scalecolor(scolor, rspec);
90     /* improved model */
91     dtmp = exp(-BSPEC(m)*pdot);
92     for (i = 0; i < 3; i++)
93     colval(scolor,i) += (1.0-colval(scolor,i))*dtmp;
94     rspec += (1.0-rspec)*dtmp;
95     /* compute reflected ray */
96     for (i = 0; i < 3; i++)
97     vrefl[i] = r->rdir[i] + 2.0*pdot*pnorm[i];
98    
99     if (alpha2 <= FTINY && !(r->crtype & SHADOW))
100     if (rayorigin(&lr, r, REFLECTED, rspec) == 0) {
101     VCOPY(lr.rdir, vrefl);
102     rayvalue(&lr);
103     multcolor(lr.rcol, scolor);
104     addcolor(r->rcol, lr.rcol);
105     }
106     }
107    
108     if (m->otype == MAT_TRANS) {
109     trans = m->oargs.farg[5]*(1.0 - rspec);
110     tspec = trans * m->oargs.farg[6];
111     tdiff = trans - tspec;
112     } else
113     tdiff = tspec = trans = 0.0;
114     /* transmitted ray */
115     if (tspec > FTINY && alpha2 <= FTINY)
116     if (rayorigin(&lr, r, TRANS, tspec) == 0) {
117     VCOPY(lr.rdir, r->rdir);
118     rayvalue(&lr);
119     scalecolor(lr.rcol, tspec);
120     addcolor(r->rcol, lr.rcol);
121     }
122     if (r->crtype & SHADOW) /* the rest is shadow */
123     return;
124     /* diffuse reflection */
125     rdiff = 1.0 - trans - rspec;
126    
127     if (rdiff <= FTINY && tdiff <= FTINY && alpha2 <= FTINY)
128     return; /* purely specular */
129    
130     ambient(ctmp, r); /* compute ambient component */
131     scalecolor(ctmp, 1.0-trans); /* from this side */
132     multcolor(ctmp, mcolor); /* modified by material color */
133     addcolor(r->rcol, ctmp); /* add to returned color */
134    
135     if (trans > FTINY) { /* ambient from other side */
136     flipsurface(r);
137     scalecolor(ctmp, trans);
138     multcolor(ctmp, mcolor);
139     addcolor(r->rcol, ctmp);
140     flipsurface(r);
141     }
142    
143     for (i = 0; i < nsources; i++) { /* add specular and diffuse */
144    
145     if ((omega = srcray(&lr, r, i)) == 0.0)
146     continue; /* bad source */
147    
148     ldot = DOT(pnorm, lr.rdir);
149    
150     if (ldot < 0.0 ? trans <= FTINY : trans >= 1.0-FTINY)
151     continue; /* wrong side */
152    
153     rayvalue(&lr); /* compute light ray value */
154    
155     if (intens(lr.rcol) <= FTINY)
156     continue; /* didn't hit light source */
157    
158     if (ldot > FTINY && rdiff > FTINY) {
159     /*
160     * Compute and add diffuse component to returned color.
161     * The diffuse component will always be modified by the
162     * color of the material.
163     */
164     copycolor(ctmp, lr.rcol);
165     dtmp = ldot * omega * rdiff / PI;
166     scalecolor(ctmp, dtmp);
167     multcolor(ctmp, mcolor);
168     addcolor(r->rcol, ctmp);
169     }
170     if (ldot > FTINY && rspec > FTINY && alpha2 > FTINY) {
171     /*
172     * Compute specular reflection coefficient using
173     * gaussian distribution model.
174     */
175     /* roughness + source */
176     dtmp = alpha2 + omega/(2.0*PI);
177     /* gaussian */
178     dtmp = exp((DOT(vrefl,lr.rdir)-1.)/dtmp)/(2.*PI)/dtmp;
179     /* worth using? */
180     if (dtmp > FTINY) {
181     copycolor(ctmp, lr.rcol);
182     dtmp *= omega;
183     scalecolor(ctmp, dtmp);
184     multcolor(ctmp, scolor);
185     addcolor(r->rcol, ctmp);
186     }
187     }
188     if (ldot < -FTINY && tdiff > FTINY) {
189     /*
190     * Compute diffuse transmission.
191     */
192     copycolor(ctmp, lr.rcol);
193     dtmp = -ldot * omega * tdiff / PI;
194     scalecolor(ctmp, dtmp);
195     multcolor(ctmp, mcolor);
196     addcolor(r->rcol, ctmp);
197     }
198     if (ldot < -FTINY && tspec > FTINY && alpha2 > FTINY) {
199     /*
200     * Compute specular transmission.
201     */
202     /* roughness + source */
203     dtmp = alpha2 + omega/(2.0*PI);
204     /* gaussian */
205     dtmp = exp((DOT(r->rdir,lr.rdir)-1.)/dtmp)/(2.*PI)/dtmp;
206     /* worth using? */
207     if (dtmp > FTINY) {
208     copycolor(ctmp, lr.rcol);
209     dtmp *= tspec * omega;
210     scalecolor(ctmp, dtmp);
211     addcolor(r->rcol, ctmp);
212     }
213     }
214     }
215     }