ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/ashikhmin.c
Revision: 2.8
Committed: Fri Apr 5 01:10:26 2024 UTC (6 weeks ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 2.7: +2 -2 lines
Log Message:
fix: Improved tracking of reflected vs. transmitted rays for antimatter

File Contents

# User Rev Content
1 greg 2.1 #ifndef lint
2 greg 2.8 static const char RCSid[] = "$Id: ashikhmin.c,v 2.7 2023/11/15 18:02:52 greg Exp $";
3 greg 2.1 #endif
4     /*
5     * Shading functions for Ashikhmin-Shirley anisotropic materials.
6     */
7    
8     #include "copyright.h"
9    
10     #include "ray.h"
11     #include "ambient.h"
12     #include "otypes.h"
13     #include "rtotypes.h"
14     #include "source.h"
15     #include "func.h"
16     #include "random.h"
17 greg 2.6 #include "pmapmat.h"
18 greg 2.1
19     #ifndef MAXITER
20     #define MAXITER 10 /* maximum # specular ray attempts */
21     #endif
22    
23     /*
24     * Ashikhmin-Shirley model
25     *
26     * Arguments for MAT_ASHIKHMIN are:
27     * 4+ ux uy uz funcfile [transform...]
28     * 0
29     * 8 dred dgrn dblu sred sgrn sblu u-power v-power
30     */
31    
32     /* specularity flags */
33     #define SPA_REFL 01 /* has reflected specular component */
34     #define SPA_FLAT 02 /* reflecting surface is flat */
35     #define SPA_RBLT 010 /* reflection below sample threshold */
36    
37     typedef struct {
38     OBJREC *mp; /* material pointer */
39     RAY *rp; /* ray pointer */
40     short specfl; /* specularity flags, defined above */
41 greg 2.7 SCOLOR mcolor; /* color of this material */
42     SCOLOR scolor; /* color of specular component */
43 greg 2.1 FVECT u, v; /* u and v vectors orienting anisotropy */
44     double u_power; /* u power */
45     double v_power; /* v power */
46     FVECT pnorm; /* perturbed surface normal */
47     double pdot; /* perturbed dot product */
48     } ASHIKDAT; /* anisotropic material data */
49    
50 greg 2.2 static void getacoords_as(ASHIKDAT *np);
51     static void ashiksamp(ASHIKDAT *np);
52 greg 2.1
53 greg 2.2 #undef MAX
54     #define MAX(a,b) ((a)>(b) ? (a) : (b))
55 greg 2.1
56    
57     static double
58     schlick_fres(double dprod)
59     {
60     double pf = 1. - dprod;
61    
62     return(pf*pf*pf*pf*pf);
63     }
64    
65    
66     static void
67     dirashik( /* compute source contribution */
68 greg 2.7 SCOLOR scval, /* returned coefficient */
69 greg 2.1 void *nnp, /* material data */
70     FVECT ldir, /* light source direction */
71     double omega /* light source size */
72     )
73     {
74     ASHIKDAT *np = nnp;
75     double ldot;
76     double dtmp, dtmp1, dtmp2;
77     FVECT h;
78 greg 2.7 SCOLOR sctmp;
79 greg 2.1
80 greg 2.7 scolorblack(scval);
81 greg 2.1
82     ldot = DOT(np->pnorm, ldir);
83    
84 greg 2.7 if (ldot <= FTINY)
85 greg 2.1 return; /* wrong side */
86    
87     /*
88     * Compute and add diffuse reflected component to returned
89     * color.
90     */
91 greg 2.7 copyscolor(sctmp, np->mcolor);
92 greg 2.1 dtmp = ldot * omega * (1.0/PI) * (1. - schlick_fres(ldot));
93 greg 2.7 scalescolor(sctmp, dtmp);
94     saddscolor(scval, sctmp);
95 greg 2.1
96 greg 2.6 if (!(np->specfl & SPA_REFL) || ambRayInPmap(np->rp))
97 greg 2.1 return;
98     /*
99     * Compute specular reflection coefficient
100     */
101     /* half vector */
102     VSUB(h, ldir, np->rp->rdir);
103     normalize(h);
104     /* ellipse */
105     dtmp1 = DOT(np->u, h);
106     dtmp1 *= dtmp1 * np->u_power;
107     dtmp2 = DOT(np->v, h);
108     dtmp2 *= dtmp2 * np->v_power;
109     /* Ashikhmin-Shirley model*/
110     dtmp = DOT(np->pnorm, h);
111     dtmp = pow(dtmp, (dtmp1+dtmp2)/(1.-dtmp*dtmp));
112     dtmp *= sqrt((np->u_power+1.)*(np->v_power+1.));
113 greg 2.2 dtmp /= 8.*PI * DOT(ldir,h) * MAX(ldot,np->pdot);
114 greg 2.1 /* worth using? */
115     if (dtmp > FTINY) {
116 greg 2.7 copyscolor(sctmp, np->scolor);
117 greg 2.1 dtmp *= ldot * omega;
118 greg 2.7 scalescolor(sctmp, dtmp);
119     saddscolor(scval, sctmp);
120 greg 2.1 }
121     }
122    
123    
124     int
125     m_ashikhmin( /* shade ray that hit something anisotropic */
126     OBJREC *m,
127     RAY *r
128     )
129     {
130     ASHIKDAT nd;
131 greg 2.7 SCOLOR sctmp;
132 greg 2.1 double fres;
133     int i;
134     /* easy shadow test */
135     if (r->crtype & SHADOW)
136     return(1);
137    
138     if (m->oargs.nfargs != 8)
139     objerror(m, USER, "bad number of real arguments");
140     /* check for back side */
141     if (r->rod < 0.0) {
142     if (!backvis) {
143     raytrans(r);
144     return(1);
145     }
146     raytexture(r, m->omod);
147     flipsurface(r); /* reorient if backvis */
148     } else
149     raytexture(r, m->omod);
150     /* get material color */
151     nd.mp = m;
152     nd.rp = r;
153 greg 2.7 setscolor(nd.mcolor, m->oargs.farg[0],
154 greg 2.1 m->oargs.farg[1],
155     m->oargs.farg[2]);
156 greg 2.7 setscolor(nd.scolor, m->oargs.farg[3],
157 greg 2.1 m->oargs.farg[4],
158     m->oargs.farg[5]);
159     /* get specular power */
160     nd.specfl = 0;
161     nd.u_power = m->oargs.farg[6];
162     nd.v_power = m->oargs.farg[7];
163    
164     nd.pdot = raynormal(nd.pnorm, r); /* perturb normal */
165     if (nd.pdot < .001)
166     nd.pdot = .001; /* non-zero for dirashik() */
167 greg 2.7 smultscolor(nd.mcolor, r->pcol); /* modify diffuse color */
168 greg 2.1
169 greg 2.7 if (sintens(nd.scolor) > FTINY) { /* adjust specular color */
170 greg 2.1 nd.specfl |= SPA_REFL;
171     /* check threshold */
172 greg 2.7 if (specthresh >= pbright(nd.scolor)-FTINY)
173 greg 2.1 nd.specfl |= SPA_RBLT;
174     fres = schlick_fres(nd.pdot); /* Schick's Fresnel approx */
175 greg 2.7 for (i = NCSAMP; i--; )
176     nd.scolor[i] += (1.-nd.scolor[i])*fres;
177 greg 2.1 }
178     if (r->ro != NULL && isflat(r->ro->otype))
179     nd.specfl |= SPA_FLAT;
180     /* set up coordinates */
181 greg 2.2 getacoords_as(&nd);
182 greg 2.1 /* specular sampling? */
183     if ((nd.specfl & (SPA_REFL|SPA_RBLT)) == SPA_REFL)
184 greg 2.2 ashiksamp(&nd);
185 greg 2.1 /* diffuse interreflection */
186 greg 2.7 if (sintens(nd.mcolor) > FTINY) {
187     copyscolor(sctmp, nd.mcolor); /* modified by material color */
188 greg 2.1 if (nd.specfl & SPA_RBLT) /* add in specular as well? */
189 greg 2.7 saddscolor(sctmp, nd.scolor);
190     multambient(sctmp, r, nd.pnorm);
191     saddscolor(r->rcol, sctmp); /* add to returned color */
192 greg 2.1 }
193     direct(r, dirashik, &nd); /* add direct component */
194    
195     return(1);
196     }
197    
198    
199     static void
200     getacoords_as( /* set up coordinate system */
201     ASHIKDAT *np
202     )
203     {
204     MFUNC *mf;
205     int i;
206    
207     mf = getfunc(np->mp, 3, 0x7, 1);
208 greg 2.2 setfunc(np->mp, np->rp);
209 greg 2.1 errno = 0;
210     for (i = 0; i < 3; i++)
211     np->u[i] = evalue(mf->ep[i]);
212 greg 2.4 if ((errno == EDOM) | (errno == ERANGE))
213     np->u[0] = np->u[1] = np->u[2] = 0.0;
214 greg 2.1 if (mf->fxp != &unitxf)
215     multv3(np->u, np->u, mf->fxp->xfm);
216     fcross(np->v, np->pnorm, np->u);
217     if (normalize(np->v) == 0.0) {
218 greg 2.4 if (fabs(np->u_power - np->v_power) > 0.1)
219     objerror(np->mp, WARNING, "bad orientation vector");
220 greg 2.5 getperpendicular(np->u, np->pnorm, 1); /* punting */
221 greg 2.4 fcross(np->v, np->pnorm, np->u);
222     np->u_power = np->v_power =
223     2./(1./(np->u_power+1e-5) + 1./(np->v_power+1e-5));
224     } else
225     fcross(np->u, np->v, np->pnorm);
226 greg 2.1 }
227    
228    
229     static void
230     ashiksamp( /* sample anisotropic Ashikhmin-Shirley specular */
231     ASHIKDAT *np
232     )
233     {
234     RAY sr;
235     FVECT h;
236     double rv[2], dtmp;
237     double cosph, sinph, costh, sinth;
238     int maxiter, ntrials, nstarget, nstaken;
239     int i;
240    
241 greg 2.8 if (rayorigin(&sr, RSPECULAR, np->rp, np->scolor) < 0)
242 greg 2.1 return;
243    
244     nstarget = 1;
245     if (specjitter > 1.5) { /* multiple samples? */
246 greg 2.2 nstarget = specjitter*np->rp->rweight + .5;
247 greg 2.1 if (sr.rweight <= minweight*nstarget)
248     nstarget = sr.rweight/minweight;
249     if (nstarget > 1) {
250     dtmp = 1./nstarget;
251 greg 2.7 scalescolor(sr.rcoef, dtmp);
252 greg 2.1 sr.rweight *= dtmp;
253     } else
254     nstarget = 1;
255     }
256     dimlist[ndims++] = (int)(size_t)np->mp;
257     maxiter = MAXITER*nstarget;
258     for (nstaken = ntrials = 0; nstaken < nstarget &&
259     ntrials < maxiter; ntrials++) {
260     if (ntrials)
261     dtmp = frandom();
262     else
263 greg 2.2 dtmp = urand(ilhash(dimlist,ndims)+647+samplendx);
264 greg 2.1 multisamp(rv, 2, dtmp);
265     dtmp = 2.*PI * rv[0];
266 greg 2.2 cosph = sqrt(np->v_power + 1.) * tcos(dtmp);
267     sinph = sqrt(np->u_power + 1.) * tsin(dtmp);
268     dtmp = 1./sqrt(cosph*cosph + sinph*sinph);
269 greg 2.1 cosph *= dtmp;
270     sinph *= dtmp;
271     costh = pow(rv[1], 1./(np->u_power*cosph*cosph+np->v_power*sinph*sinph+1.));
272     if (costh <= FTINY)
273     continue;
274     sinth = sqrt(1. - costh*costh);
275     for (i = 0; i < 3; i++)
276     h[i] = cosph*sinth*np->u[i] + sinph*sinth*np->v[i] + costh*np->pnorm[i];
277    
278     if (nstaken)
279     rayclear(&sr);
280 greg 2.2 dtmp = -2.*DOT(h, np->rp->rdir);
281     VSUM(sr.rdir, np->rp->rdir, h, dtmp);
282 greg 2.1 /* sample rejection test */
283 greg 2.2 if (DOT(sr.rdir, np->rp->ron) <= FTINY)
284 greg 2.1 continue;
285 greg 2.2 checknorm(sr.rdir);
286 greg 2.1 rayvalue(&sr);
287 greg 2.7 smultscolor(sr.rcol, sr.rcoef);
288     saddscolor(np->rp->rcol, sr.rcol);
289 greg 2.1 ++nstaken;
290     }
291     ndims--;
292     }