soc-2008-mxcurioni: merged changes to revision 15441
[blender.git] / source / blender / render / intern / source / pixelshading.c
1 /**
2  *
3  * ***** BEGIN GPL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version. 
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software Foundation,
17  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18  *
19  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
20  * All rights reserved.
21  *
22  * Contributor(s): 2004-2006, Blender Foundation, full recode
23  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 #include <float.h>
28 #include <math.h>
29 #include <string.h>
30 #include "BLI_arithb.h"
31
32 /* External modules: */
33 #include "IMB_imbuf_types.h"
34 #include "IMB_imbuf.h"
35 #include "MTC_matrixops.h"
36 #include "MTC_vectorops.h"
37
38 #include "DNA_camera_types.h"
39 #include "DNA_group_types.h"
40 #include "DNA_material_types.h"
41 #include "DNA_object_types.h"
42 #include "DNA_image_types.h"
43 #include "DNA_texture_types.h"
44 #include "DNA_lamp_types.h"
45
46 #include "BKE_image.h"
47 #include "BKE_global.h"
48 #include "BKE_texture.h"
49 #include "BKE_utildefines.h"
50
51 /* own module */
52 #include "render_types.h"
53 #include "renderpipeline.h"
54 #include "renderdatabase.h"
55 #include "texture.h"
56 #include "pixelblending.h"
57 #include "rendercore.h"
58 #include "shadbuf.h"
59 #include "pixelshading.h"
60 #include "sunsky.h"
61
62 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
63 /* defined in pipeline.c, is hardcopy of active dynamic allocated Render */
64 /* only to be used here in this file, it's for speed */
65 extern struct Render R;
66 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
67
68
69 extern float hashvectf[];
70
71 static void render_lighting_halo(HaloRen *har, float *colf)
72 {
73         GroupObject *go;
74         LampRen *lar;
75         float i, inp, inpr, rco[3], dco[3], lv[3], lampdist, ld, t, *vn;
76         float ir, ig, ib, shadfac, soft, lacol[3];
77         
78         ir= ig= ib= 0.0;
79         
80         VECCOPY(rco, har->co);  
81         dco[0]=dco[1]=dco[2]= 1.0/har->rad;
82         
83         vn= har->no;
84         
85         for(go=R.lights.first; go; go= go->next) {
86                 lar= go->lampren;
87                 
88                 /* test for lamplayer */
89                 if(lar->mode & LA_LAYER) if((lar->lay & har->lay)==0) continue;
90                 
91                 /* lampdist cacluation */
92                 if(lar->type==LA_SUN || lar->type==LA_HEMI) {
93                         VECCOPY(lv, lar->vec);
94                         lampdist= 1.0;
95                 }
96                 else {
97                         lv[0]= rco[0]-lar->co[0];
98                         lv[1]= rco[1]-lar->co[1];
99                         lv[2]= rco[2]-lar->co[2];
100                         ld= sqrt(lv[0]*lv[0]+lv[1]*lv[1]+lv[2]*lv[2]);
101                         lv[0]/= ld;
102                         lv[1]/= ld;
103                         lv[2]/= ld;
104                         
105                         /* ld is re-used further on (texco's) */
106                         
107                         if(lar->mode & LA_QUAD) {
108                                 t= 1.0;
109                                 if(lar->ld1>0.0)
110                                         t= lar->dist/(lar->dist+lar->ld1*ld);
111                                 if(lar->ld2>0.0)
112                                         t*= lar->distkw/(lar->distkw+lar->ld2*ld*ld);
113                                 
114                                 lampdist= t;
115                         }
116                         else {
117                                 lampdist= (lar->dist/(lar->dist+ld));
118                         }
119                         
120                         if(lar->mode & LA_SPHERE) {
121                                 t= lar->dist - ld;
122                                 if(t<0.0) continue;
123                                 
124                                 t/= lar->dist;
125                                 lampdist*= (t);
126                         }
127                         
128                 }
129                 
130                 lacol[0]= lar->r;
131                 lacol[1]= lar->g;
132                 lacol[2]= lar->b;
133                 
134                 if(lar->mode & LA_TEXTURE) {
135                         ShadeInput shi;
136                         
137                         /* Warning, This is not that nice, and possibly a bit slow,
138                         however some variables were not initialized properly in, unless using shade_input_initialize(...), we need to do a memset */
139                         memset(&shi, 0, sizeof(ShadeInput)); 
140                         /* end warning! - Campbell */
141                         
142                         VECCOPY(shi.co, rco);
143                         shi.osatex= 0;
144                         do_lamp_tex(lar, lv, &shi, lacol);
145                 }
146                 
147                 if(lar->type==LA_SPOT) {
148                         
149                         if(lar->mode & LA_SQUARE) {
150                                 if(lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2]>0.0) {
151                                         float x, lvrot[3];
152                                         
153                                         /* rotate view to lampspace */
154                                         VECCOPY(lvrot, lv);
155                                         MTC_Mat3MulVecfl(lar->imat, lvrot);
156                                         
157                                         x= MAX2(fabs(lvrot[0]/lvrot[2]) , fabs(lvrot[1]/lvrot[2]));
158                                         /* 1.0/(sqrt(1+x*x)) is equivalent to cos(atan(x)) */
159                                         
160                                         inpr= 1.0/(sqrt(1.0+x*x));
161                                 }
162                                 else inpr= 0.0;
163                         }
164                         else {
165                                 inpr= lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2];
166                         }
167                         
168                         t= lar->spotsi;
169                         if(inpr<t) continue;
170                         else {
171                                 t= inpr-t;
172                                 i= 1.0;
173                                 soft= 1.0;
174                                 if(t<lar->spotbl && lar->spotbl!=0.0) {
175                                         /* soft area */
176                                         i= t/lar->spotbl;
177                                         t= i*i;
178                                         soft= (3.0*t-2.0*t*i);
179                                         inpr*= soft;
180                                 }
181                                 if(lar->mode & LA_ONLYSHADOW) {
182                                         /* if(ma->mode & MA_SHADOW) { */
183                                         /* dot product positive: front side face! */
184                                         inp= vn[0]*lv[0] + vn[1]*lv[1] + vn[2]*lv[2];
185                                         if(inp>0.0) {
186                                                 /* testshadowbuf==0.0 : 100% shadow */
187                                                 shadfac = testshadowbuf(&R, lar->shb, rco, dco, dco, inp, 0.0f);
188                                                 if( shadfac>0.0 ) {
189                                                         shadfac*= inp*soft*lar->energy;
190                                                         ir -= shadfac;
191                                                         ig -= shadfac;
192                                                         ib -= shadfac;
193                                                         
194                                                         continue;
195                                                 }
196                                         }
197                                         /* } */
198                                 }
199                                 lampdist*=inpr;
200                         }
201                         if(lar->mode & LA_ONLYSHADOW) continue;
202                         
203                 }
204                 
205                 /* dot product and  reflectivity*/
206                 
207                 inp= 1.0-fabs(vn[0]*lv[0] + vn[1]*lv[1] + vn[2]*lv[2]);
208                 
209                 /* inp= cos(0.5*M_PI-acos(inp)); */
210                 
211                 i= inp;
212                 
213                 if(lar->type==LA_HEMI) {
214                         i= 0.5*i+0.5;
215                 }
216                 if(i>0.0) {
217                         i*= lampdist;
218                 }
219                 
220                 /* shadow  */
221                 if(i> -0.41) {                  /* heuristic valua! */
222                         shadfac= 1.0;
223                         if(lar->shb) {
224                                 shadfac = testshadowbuf(&R, lar->shb, rco, dco, dco, inp, 0.0f);
225                                 if(shadfac==0.0) continue;
226                                 i*= shadfac;
227                         }
228                 }
229                 
230                 if(i>0.0) {
231                         ir+= i*lacol[0];
232                         ig+= i*lacol[1];
233                         ib+= i*lacol[2];
234                 }
235         }
236         
237         if(ir<0.0) ir= 0.0;
238         if(ig<0.0) ig= 0.0;
239         if(ib<0.0) ib= 0.0;
240
241         colf[0]*= ir;
242         colf[1]*= ig;
243         colf[2]*= ib;
244         
245 }
246
247
248 /**
249  * Converts a halo z-buffer value to distance from the camera's near plane
250  * @param z The z-buffer value to convert
251  * @return a distance from the camera's near plane in blender units
252  */
253 static float haloZtoDist(int z)
254 {
255         float zco = 0;
256
257         if(z >= 0x7FFFFF)
258                 return 10e10;
259         else {
260                 zco = (float)z/(float)0x7FFFFF;
261                 if(R.r.mode & R_ORTHO)
262                         return (R.winmat[3][2] - zco*R.winmat[3][3])/(R.winmat[2][2]);
263                 else
264                         return (R.winmat[3][2])/(R.winmat[2][2] - R.winmat[2][3]*zco);
265         }
266 }
267
268 /**
269  * @param col (float[4]) Store the rgb color here (with alpha)
270  * The alpha is used to blend the color to the background 
271  * color_new = (1-alpha)*color_background + color
272  * @param zz The current zbuffer value at the place of this pixel
273  * @param dist Distance of the pixel from the center of the halo squared. Given in pixels
274  * @param xn The x coordinate of the pixel relaticve to the center of the halo. given in pixels
275  * @param yn The y coordinate of the pixel relaticve to the center of the halo. given in pixels
276  */
277 int shadeHaloFloat(HaloRen *har,  float *col, int zz, 
278                                         float dist, float xn,  float yn, short flarec)
279 {
280         /* fill in col */
281         float t, zn, radist, ringf=0.0f, linef=0.0f, alpha, si, co;
282         int a;
283    
284         if(R.wrld.mode & WO_MIST) {
285        if(har->type & HA_ONLYSKY) {
286            /* stars but no mist */
287            alpha= har->alfa;
288        }
289        else {
290            /* a bit patchy... */
291            alpha= mistfactor(-har->co[2], har->co)*har->alfa;
292        }
293         }
294         else alpha= har->alfa;
295         
296         if(alpha==0.0)
297                 return 0;
298
299         /* soften the halo if it intersects geometry */
300         if(har->mat && har->mat->mode & MA_HALO_SOFT) {
301                 float segment_length, halo_depth, distance_from_z, visible_depth, soften;
302                 
303                 /* calculate halo depth */
304                 segment_length= har->hasize*sasqrt(1.0f - dist/(har->rad*har->rad));
305                 halo_depth= 2.0f*segment_length;
306
307                 if(halo_depth < FLT_EPSILON)
308                         return 0;
309
310                 /* calculate how much of this depth is visible */
311                 distance_from_z = haloZtoDist(zz) - haloZtoDist(har->zs);
312                 visible_depth = halo_depth;
313                 if(distance_from_z < segment_length) {
314                         soften= (segment_length + distance_from_z)/halo_depth;
315
316                         /* apply softening to alpha */
317                         if(soften < 1.0f)
318                                 alpha *= soften;
319                         if(alpha <= 0.0f)
320                                 return 0;
321                 }
322         }
323         else {
324                 /* not a soft halo. use the old softening code */
325                 /* halo being intersected? */
326                 if(har->zs> zz-har->zd) {
327                         t= ((float)(zz-har->zs))/(float)har->zd;
328                         alpha*= sqrt(sqrt(t));
329                 }
330         }
331
332         radist= sqrt(dist);
333
334         /* watch it: not used nicely: flarec is set at zero in pixstruct */
335         if(flarec) har->pixels+= (int)(har->rad-radist);
336
337         if(har->ringc) {
338                 float *rc, fac;
339                 int ofs;
340                 
341                 /* per ring an antialised circle */
342                 ofs= har->seed;
343                 
344                 for(a= har->ringc; a>0; a--, ofs+=2) {
345                         
346                         rc= hashvectf + (ofs % 768);
347                         
348                         fac= fabs( rc[1]*(har->rad*fabs(rc[0]) - radist) );
349                         
350                         if(fac< 1.0) {
351                                 ringf+= (1.0-fac);
352                         }
353                 }
354         }
355
356         if(har->type & HA_VECT) {
357                 dist= fabs( har->cos*(yn) - har->sin*(xn) )/har->rad;
358                 if(dist>1.0) dist= 1.0;
359                 if(har->tex) {
360                         zn= har->sin*xn - har->cos*yn;
361                         yn= har->cos*xn + har->sin*yn;
362                         xn= zn;
363                 }
364         }
365         else dist= dist/har->radsq;
366
367         if(har->type & HA_FLARECIRC) {
368                 
369                 dist= 0.5+fabs(dist-0.5);
370                 
371         }
372
373         if(har->hard>=30) {
374                 dist= sqrt(dist);
375                 if(har->hard>=40) {
376                         dist= sin(dist*M_PI_2);
377                         if(har->hard>=50) {
378                                 dist= sqrt(dist);
379                         }
380                 }
381         }
382         else if(har->hard<20) dist*=dist;
383
384         if(dist < 1.0f)
385                 dist= (1.0f-dist);
386         else
387                 dist= 0.0f;
388         
389         if(har->linec) {
390                 float *rc, fac;
391                 int ofs;
392                 
393                 /* per starpoint an antialiased line */
394                 ofs= har->seed;
395                 
396                 for(a= har->linec; a>0; a--, ofs+=3) {
397                         
398                         rc= hashvectf + (ofs % 768);
399                         
400                         fac= fabs( (xn)*rc[0]+(yn)*rc[1]);
401                         
402                         if(fac< 1.0f )
403                                 linef+= (1.0f-fac);
404                 }
405                 
406                 linef*= dist;
407         }
408
409         if(har->starpoints) {
410                 float ster, angle;
411                 /* rotation */
412                 angle= atan2(yn, xn);
413                 angle*= (1.0+0.25*har->starpoints);
414                 
415                 co= cos(angle);
416                 si= sin(angle);
417                 
418                 angle= (co*xn+si*yn)*(co*yn-si*xn);
419                 
420                 ster= fabs(angle);
421                 if(ster>1.0) {
422                         ster= (har->rad)/(ster);
423                         
424                         if(ster<1.0) dist*= sqrt(ster);
425                 }
426         }
427
428         /* disputable optimize... (ton) */
429         if(dist<=0.00001)
430                 return 0;
431         
432         dist*= alpha;
433         ringf*= dist;
434         linef*= alpha;
435         
436         /* The color is either the rgb spec-ed by the user, or extracted from   */
437         /* the texture                                                           */
438         if(har->tex) {
439                 col[0]= har->r; 
440                 col[1]= har->g; 
441                 col[2]= har->b;
442                 col[3]= dist;
443                 
444                 do_halo_tex(har, xn, yn, col);
445                 
446                 col[0]*= col[3];
447                 col[1]*= col[3];
448                 col[2]*= col[3];
449                 
450         }
451         else {
452                 col[0]= dist*har->r;
453                 col[1]= dist*har->g;
454                 col[2]= dist*har->b;
455                 if(har->type & HA_XALPHA) col[3]= dist*dist;
456                 else col[3]= dist;
457         }
458
459         if(har->mat) {
460                 if(har->mat->mode & MA_HALO_SHADE) {
461                         /* we test for lights because of preview... */
462                         if(R.lights.first) render_lighting_halo(har, col);
463                 }
464
465                 /* Next, we do the line and ring factor modifications. */
466                 if(linef!=0.0) {
467                         Material *ma= har->mat;
468                         
469                         col[0]+= linef * ma->specr;
470                         col[1]+= linef * ma->specg;
471                         col[2]+= linef * ma->specb;
472                         
473                         if(har->type & HA_XALPHA) col[3]+= linef*linef;
474                         else col[3]+= linef;
475                 }
476                 if(ringf!=0.0) {
477                         Material *ma= har->mat;
478
479                         col[0]+= ringf * ma->mirr;
480                         col[1]+= ringf * ma->mirg;
481                         col[2]+= ringf * ma->mirb;
482                         
483                         if(har->type & HA_XALPHA) col[3]+= ringf*ringf;
484                         else col[3]+= ringf;
485                 }
486         }
487         
488         /* alpha requires clip, gives black dots */
489         if(col[3] > 1.0f)
490                 col[3]= 1.0f;
491
492         return 1;
493 }
494
495 /* ------------------------------------------------------------------------- */
496
497 static void fillBackgroundImage(float *collector, float fx, float fy)
498 {
499         collector[0] = 0.0; 
500         collector[1] = 0.0; 
501         collector[2] = 0.0; 
502         collector[3] = 0.0; 
503         
504         if(R.backbuf) {
505                 float dx= 1.0f/(float)R.winx;
506                 float dy= 1.0f/(float)R.winy;
507                 
508                 image_sample(R.backbuf, fx*dx, fy*dy, dx, dy, collector);
509         }
510 }
511
512 /* Only view vector is important here. Result goes to colf[3] */
513 void shadeSkyView(float *colf, float *rco, float *view, float *dxyview)
514 {
515         float lo[3], zen[3], hor[3], blend, blendm;
516         int skyflag;
517         
518         /* flag indicating if we render the top hemisphere */
519         skyflag = WO_ZENUP;
520         
521         /* Some view vector stuff. */
522         if(R.wrld.skytype & WO_SKYREAL) {
523                 
524                 blend= view[0]*R.grvec[0]+ view[1]*R.grvec[1]+ view[2]*R.grvec[2];
525                 
526                 if(blend<0.0) skyflag= 0;
527                 
528                 blend= fabs(blend);
529         }
530         else if(R.wrld.skytype & WO_SKYPAPER) {
531                 blend= 0.5+ 0.5*view[1];
532         }
533         else {
534                 /* the fraction of how far we are above the bottom of the screen */
535                 blend= fabs(0.5+ view[1]);
536         }
537         
538         hor[0]= R.wrld.horr; hor[1]= R.wrld.horg; hor[2]= R.wrld.horb;
539         zen[0]= R.wrld.zenr; zen[1]= R.wrld.zeng; zen[2]= R.wrld.zenb;
540         
541         /* Careful: SKYTEX and SKYBLEND are NOT mutually exclusive! If           */
542         /* SKYBLEND is active, the texture and color blend are added.           */
543         if(R.wrld.skytype & WO_SKYTEX) {
544                 VECCOPY(lo, view);
545                 if(R.wrld.skytype & WO_SKYREAL) {
546                         
547                         MTC_Mat3MulVecfl(R.imat, lo);
548                         
549                         SWAP(float, lo[1],  lo[2]);
550                         
551                 }
552                 do_sky_tex(rco, lo, dxyview, hor, zen, &blend, skyflag);
553         }
554         
555         if(blend>1.0) blend= 1.0;
556         blendm= 1.0-blend;
557         
558         /* No clipping, no conversion! */
559         if(R.wrld.skytype & WO_SKYBLEND) {
560                 colf[0] = (blendm*hor[0] + blend*zen[0]);
561                 colf[1] = (blendm*hor[1] + blend*zen[1]);
562                 colf[2] = (blendm*hor[2] + blend*zen[2]);
563         } else {
564                 /* Done when a texture was grabbed. */
565                 colf[0]= hor[0];
566                 colf[1]= hor[1];
567                 colf[2]= hor[2];
568         }
569 }
570
571 /* shade sky according to sun lamps, all parameters are like shadeSkyView except sunsky*/
572 void shadeSunView(struct SunSky *sunsky, float *colf, float *rco, float *view, float *dxyview)
573 {
574         float colorxyz[3];
575         float scale;
576                         
577         /**
578         sunAngle = sqrt(sunsky->sunSolidAngle / M_PI);
579
580         sunDir[0] = sunsky->toSun[0];
581         sunDir[1] = sunsky->toSun[1];
582         sunDir[2] = sunsky->toSun[2];
583         */
584                         
585         Normalize(view);
586         MTC_Mat3MulVecfl(R.imat, view);
587         if (view[2] < 0.0)
588                 view[2] = 0.0;
589         Normalize(view);
590         GetSkyXYZRadiancef(sunsky, view, colorxyz);
591         scale = MAX3(colorxyz[0], colorxyz[1], colorxyz[2]);
592         colorxyz[0] /= scale;
593         colorxyz[1] /= scale;
594         colorxyz[2] /= scale;
595         
596         xyz_to_rgb(colorxyz[0], colorxyz[1], colorxyz[2], &colf[0], &colf[1], &colf[2]);
597
598         ClipColor(colf);
599 }
600
601
602 /*
603   Stuff the sky color into the collector.
604  */
605 void shadeSkyPixel(float *collector, float fx, float fy) 
606 {
607         float view[3], dxyview[2];
608         float sun_collector[3];
609         float suns_color[3];
610         short num_sun_lamp;
611         GroupObject *go;
612         LampRen *lar;
613
614         /*
615           The rules for sky:
616           1. Draw an image, if a background image was provided. Stop
617           2. get texture and color blend, and combine these.
618         */
619
620         float fac;
621
622         /* 1. Do a backbuffer image: */ 
623         if(R.r.bufflag & 1) {
624                 fillBackgroundImage(collector, fx, fy);
625         } 
626         else if((R.wrld.skytype & (WO_SKYBLEND+WO_SKYTEX))==0) {
627                 /* 2. solid color */
628                 collector[0] = R.wrld.horr;
629                 collector[1] = R.wrld.horg;
630                 collector[2] = R.wrld.horb;
631                 collector[3] = 0.0f;
632         } 
633         else {
634                 /* 3. */
635
636                 /* This one true because of the context of this routine  */
637                 if(R.wrld.skytype & WO_SKYPAPER) {
638                         view[0]= -1.0f + 2.0f*(fx/(float)R.winx);
639                         view[1]= -1.0f + 2.0f*(fy/(float)R.winy);
640                         view[2]= 0.0;
641                         
642                         dxyview[0]= 1.0f/(float)R.winx;
643                         dxyview[1]= 1.0f/(float)R.winy;
644                 }
645                 else {
646                         calc_view_vector(view, fx, fy);
647                         fac= Normalize(view);
648                         
649                         if(R.wrld.skytype & WO_SKYTEX) {
650                                 dxyview[0]= -R.viewdx/fac;
651                                 dxyview[1]= -R.viewdy/fac;
652                         }
653                 }
654                 
655                 /* get sky color in the collector */
656                 shadeSkyView(collector, NULL, view, dxyview);
657                 collector[3] = 0.0f;
658         }
659                 
660         suns_color[0] = suns_color[1] = suns_color[2] = 0;
661         num_sun_lamp = 0;
662         for(go=R.lights.first; go; go= go->next) {
663                 lar= go->lampren;
664                 if(lar->type==LA_SUN && lar->sunsky && (lar->sunsky->effect_type & LA_SUN_EFFECT_SKY)){
665
666                         num_sun_lamp ++;
667                         calc_view_vector(view, fx, fy);
668                         Normalize(view);
669
670                         shadeSunView(lar->sunsky, sun_collector, NULL, view, NULL);
671                         suns_color[0] += sun_collector[0];
672                         suns_color[1] += sun_collector[1];
673                         suns_color[2] += sun_collector[2];
674
675                 }
676         }
677         if( num_sun_lamp > 0 ){
678                 suns_color[0] /= num_sun_lamp;
679                 suns_color[1] /= num_sun_lamp;
680                 suns_color[2] /= num_sun_lamp;
681
682                 collector[0] += suns_color[0];
683                 collector[1] += suns_color[1];
684                 collector[2] += suns_color[2];
685                 ClipColor(collector);
686         }
687 }
688
689 /* aerial perspective */
690 void shadeAtmPixel(struct SunSky *sunsky, float *collector, float fx, float fy, float distance)
691 {
692         float view[3];
693                 
694         calc_view_vector(view, fx, fy);
695         Normalize(view);
696         /*MTC_Mat3MulVecfl(R.imat, view);*/
697         AtmospherePixleShader(sunsky, view, distance, collector);
698 }
699
700 /* eof */