ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/normal.c
Revision: 1.2
Committed: Sat Apr 15 12:23:22 1989 UTC (35 years ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.1: +15 -7 lines
Log Message:
repaired and improved ambient calculation

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 greg 1.2 if (rdiff > FTINY) { /* ambient from this side */
131     ambient(ctmp, r);
132     if (alpha2 <= FTINY)
133     scalecolor(ctmp, rdiff);
134     else
135     scalecolor(ctmp, 1.0-trans);
136     multcolor(ctmp, mcolor); /* modified by material color */
137     addcolor(r->rcol, ctmp); /* add to returned color */
138     }
139     if (tdiff > FTINY) { /* ambient from other side */
140 greg 1.1 flipsurface(r);
141 greg 1.2 ambient(ctmp, r);
142     if (alpha2 <= FTINY)
143     scalecolor(ctmp, tdiff);
144     else
145     scalecolor(ctmp, trans);
146 greg 1.1 multcolor(ctmp, mcolor);
147     addcolor(r->rcol, ctmp);
148     flipsurface(r);
149     }
150    
151     for (i = 0; i < nsources; i++) { /* add specular and diffuse */
152    
153     if ((omega = srcray(&lr, r, i)) == 0.0)
154     continue; /* bad source */
155    
156     ldot = DOT(pnorm, lr.rdir);
157    
158     if (ldot < 0.0 ? trans <= FTINY : trans >= 1.0-FTINY)
159     continue; /* wrong side */
160    
161     rayvalue(&lr); /* compute light ray value */
162    
163     if (intens(lr.rcol) <= FTINY)
164     continue; /* didn't hit light source */
165    
166     if (ldot > FTINY && rdiff > FTINY) {
167     /*
168     * Compute and add diffuse component to returned color.
169     * The diffuse component will always be modified by the
170     * color of the material.
171     */
172     copycolor(ctmp, lr.rcol);
173     dtmp = ldot * omega * rdiff / PI;
174     scalecolor(ctmp, dtmp);
175     multcolor(ctmp, mcolor);
176     addcolor(r->rcol, ctmp);
177     }
178     if (ldot > FTINY && rspec > FTINY && alpha2 > FTINY) {
179     /*
180     * Compute specular reflection coefficient using
181     * gaussian distribution model.
182     */
183     /* roughness + source */
184     dtmp = alpha2 + omega/(2.0*PI);
185     /* gaussian */
186     dtmp = exp((DOT(vrefl,lr.rdir)-1.)/dtmp)/(2.*PI)/dtmp;
187     /* worth using? */
188     if (dtmp > FTINY) {
189     copycolor(ctmp, lr.rcol);
190     dtmp *= omega;
191     scalecolor(ctmp, dtmp);
192     multcolor(ctmp, scolor);
193     addcolor(r->rcol, ctmp);
194     }
195     }
196     if (ldot < -FTINY && tdiff > FTINY) {
197     /*
198     * Compute diffuse transmission.
199     */
200     copycolor(ctmp, lr.rcol);
201     dtmp = -ldot * omega * tdiff / PI;
202     scalecolor(ctmp, dtmp);
203     multcolor(ctmp, mcolor);
204     addcolor(r->rcol, ctmp);
205     }
206     if (ldot < -FTINY && tspec > FTINY && alpha2 > FTINY) {
207     /*
208     * Compute specular transmission.
209     */
210     /* roughness + source */
211     dtmp = alpha2 + omega/(2.0*PI);
212     /* gaussian */
213     dtmp = exp((DOT(r->rdir,lr.rdir)-1.)/dtmp)/(2.*PI)/dtmp;
214     /* worth using? */
215     if (dtmp > FTINY) {
216     copycolor(ctmp, lr.rcol);
217     dtmp *= tspec * omega;
218     scalecolor(ctmp, dtmp);
219     addcolor(r->rcol, ctmp);
220     }
221     }
222     }
223     }