Blender V2.61 - r43446

pixelshading.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version. 
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00019  * All rights reserved.
00020  *
00021  * Contributor(s): 2004-2006, Blender Foundation, full recode
00022  *
00023  * ***** END GPL LICENSE BLOCK *****
00024  */
00025 
00031 #include <float.h>
00032 #include <math.h>
00033 #include <string.h>
00034 
00035 #include "BLI_math.h"
00036 #include "BLI_utildefines.h"
00037 
00038 /* External modules: */
00039 #include "IMB_imbuf_types.h"
00040 #include "IMB_imbuf.h"
00041 
00042 #include "DNA_camera_types.h"
00043 #include "DNA_group_types.h"
00044 #include "DNA_material_types.h"
00045 #include "DNA_object_types.h"
00046 #include "DNA_image_types.h"
00047 #include "DNA_texture_types.h"
00048 #include "DNA_lamp_types.h"
00049 
00050 #include "BKE_colortools.h"
00051 #include "BKE_image.h"
00052 #include "BKE_global.h"
00053 #include "BKE_material.h"
00054 #include "BKE_texture.h"
00055 
00056 
00057 /* own module */
00058 #include "render_types.h"
00059 #include "renderpipeline.h"
00060 #include "renderdatabase.h"
00061 #include "texture.h"
00062 #include "pixelblending.h"
00063 #include "rendercore.h"
00064 #include "shadbuf.h"
00065 #include "pixelshading.h"
00066 #include "shading.h"
00067 #include "sunsky.h"
00068 
00069 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
00070 /* defined in pipeline.c, is hardcopy of active dynamic allocated Render */
00071 /* only to be used here in this file, it's for speed */
00072 extern struct Render R;
00073 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
00074 
00075 
00076 extern float hashvectf[];
00077 
00078 static void render_lighting_halo(HaloRen *har, float col_r[3])
00079 {
00080     GroupObject *go;
00081     LampRen *lar;
00082     float i, inp, inpr, rco[3], dco[3], lv[3], lampdist, ld, t, *vn;
00083     float ir, ig, ib, shadfac, soft, lacol[3];
00084     
00085     ir= ig= ib= 0.0;
00086     
00087     copy_v3_v3(rco, har->co);
00088     dco[0]=dco[1]=dco[2]= 1.0f/har->rad;
00089     
00090     vn= har->no;
00091     
00092     for(go=R.lights.first; go; go= go->next) {
00093         lar= go->lampren;
00094         
00095         /* test for lamplayer */
00096         if(lar->mode & LA_LAYER) if((lar->lay & har->lay)==0) continue;
00097         
00098         /* lampdist cacluation */
00099         if(lar->type==LA_SUN || lar->type==LA_HEMI) {
00100             copy_v3_v3(lv, lar->vec);
00101             lampdist= 1.0;
00102         }
00103         else {
00104             lv[0]= rco[0]-lar->co[0];
00105             lv[1]= rco[1]-lar->co[1];
00106             lv[2]= rco[2]-lar->co[2];
00107             ld= sqrt(lv[0]*lv[0]+lv[1]*lv[1]+lv[2]*lv[2]);
00108             lv[0]/= ld;
00109             lv[1]/= ld;
00110             lv[2]/= ld;
00111             
00112             /* ld is re-used further on (texco's) */
00113             
00114             if(lar->mode & LA_QUAD) {
00115                 t= 1.0;
00116                 if(lar->ld1>0.0f)
00117                     t= lar->dist/(lar->dist+lar->ld1*ld);
00118                 if(lar->ld2>0.0f)
00119                     t*= lar->distkw/(lar->distkw+lar->ld2*ld*ld);
00120                 
00121                 lampdist= t;
00122             }
00123             else {
00124                 lampdist= (lar->dist/(lar->dist+ld));
00125             }
00126             
00127             if(lar->mode & LA_SPHERE) {
00128                 t= lar->dist - ld;
00129                 if(t<0.0f) continue;
00130                 
00131                 t/= lar->dist;
00132                 lampdist*= (t);
00133             }
00134             
00135         }
00136         
00137         lacol[0]= lar->r;
00138         lacol[1]= lar->g;
00139         lacol[2]= lar->b;
00140         
00141         if(lar->mode & LA_TEXTURE) {
00142             ShadeInput shi;
00143             
00144             /* Warning, This is not that nice, and possibly a bit slow,
00145             however some variables were not initialized properly in, unless using shade_input_initialize(...), we need to do a memset */
00146             memset(&shi, 0, sizeof(ShadeInput)); 
00147             /* end warning! - Campbell */
00148             
00149             copy_v3_v3(shi.co, rco);
00150             shi.osatex= 0;
00151             do_lamp_tex(lar, lv, &shi, lacol, LA_TEXTURE);
00152         }
00153         
00154         if(lar->type==LA_SPOT) {
00155             
00156             if(lar->mode & LA_SQUARE) {
00157                 if(lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2]>0.0f) {
00158                     float x, lvrot[3];
00159                     
00160                     /* rotate view to lampspace */
00161                     copy_v3_v3(lvrot, lv);
00162                     mul_m3_v3(lar->imat, lvrot);
00163                     
00164                     x= MAX2(fabs(lvrot[0]/lvrot[2]) , fabs(lvrot[1]/lvrot[2]));
00165                     /* 1.0/(sqrt(1+x*x)) is equivalent to cos(atan(x)) */
00166                     
00167                     inpr= 1.0/(sqrt(1.0f+x*x));
00168                 }
00169                 else inpr= 0.0;
00170             }
00171             else {
00172                 inpr= lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2];
00173             }
00174             
00175             t= lar->spotsi;
00176             if(inpr<t) continue;
00177             else {
00178                 t= inpr-t;
00179                 soft= 1.0;
00180                 if(t<lar->spotbl && lar->spotbl!=0.0f) {
00181                     /* soft area */
00182                     i= t/lar->spotbl;
00183                     t= i*i;
00184                     soft= (3.0f*t-2.0f*t*i);
00185                     inpr*= soft;
00186                 }
00187                 if(lar->mode & LA_ONLYSHADOW) {
00188                     /* if(ma->mode & MA_SHADOW) { */
00189                     /* dot product positive: front side face! */
00190                     inp= vn[0]*lv[0] + vn[1]*lv[1] + vn[2]*lv[2];
00191                     if(inp>0.0f) {
00192                         /* testshadowbuf==0.0 : 100% shadow */
00193                         shadfac = testshadowbuf(&R, lar->shb, rco, dco, dco, inp, 0.0f);
00194                         if( shadfac>0.0f ) {
00195                             shadfac*= inp*soft*lar->energy;
00196                             ir -= shadfac;
00197                             ig -= shadfac;
00198                             ib -= shadfac;
00199                             
00200                             continue;
00201                         }
00202                     }
00203                     /* } */
00204                 }
00205                 lampdist*=inpr;
00206             }
00207             if(lar->mode & LA_ONLYSHADOW) continue;
00208             
00209         }
00210         
00211         /* dot product and  reflectivity*/
00212         
00213         inp= 1.0-fabs(vn[0]*lv[0] + vn[1]*lv[1] + vn[2]*lv[2]);
00214         
00215         /* inp= cos(0.5*M_PI-acos(inp)); */
00216         
00217         i= inp;
00218         
00219         if(lar->type==LA_HEMI) {
00220             i= 0.5f*i+0.5f;
00221         }
00222         if(i>0.0f) {
00223             i*= lampdist;
00224         }
00225         
00226         /* shadow  */
00227         if(i> -0.41f) { /* heuristic valua! */
00228             if(lar->shb) {
00229                 shadfac = testshadowbuf(&R, lar->shb, rco, dco, dco, inp, 0.0f);
00230                 if(shadfac==0.0f) continue;
00231                 i*= shadfac;
00232             }
00233         }
00234         
00235         if(i>0.0f) {
00236             ir+= i*lacol[0];
00237             ig+= i*lacol[1];
00238             ib+= i*lacol[2];
00239         }
00240     }
00241     
00242     if(ir<0.0f) ir= 0.0f;
00243     if(ig<0.0f) ig= 0.0f;
00244     if(ib<0.0f) ib= 0.0f;
00245 
00246     col_r[0]*= ir;
00247     col_r[1]*= ig;
00248     col_r[2]*= ib;
00249     
00250 }
00251 
00252 
00258 static float haloZtoDist(int z)
00259 {
00260     float zco = 0;
00261 
00262     if(z >= 0x7FFFFF)
00263         return 10e10;
00264     else {
00265         zco = (float)z/(float)0x7FFFFF;
00266         if(R.r.mode & R_ORTHO)
00267             return (R.winmat[3][2] - zco*R.winmat[3][3])/(R.winmat[2][2]);
00268         else
00269             return (R.winmat[3][2])/(R.winmat[2][2] - R.winmat[2][3]*zco);
00270     }
00271 }
00272 
00282 int shadeHaloFloat(HaloRen *har,  float *col, int zz, 
00283                     float dist, float xn,  float yn, short flarec)
00284 {
00285     /* fill in col */
00286     float t, zn, radist, ringf=0.0f, linef=0.0f, alpha, si, co;
00287     int a;
00288    
00289     if(R.wrld.mode & WO_MIST) {
00290         if(har->type & HA_ONLYSKY) {
00291             /* stars but no mist */
00292             alpha= har->alfa;
00293         }
00294         else {
00295             /* a bit patchy... */
00296             alpha= mistfactor(-har->co[2], har->co)*har->alfa;
00297         }
00298     }
00299     else alpha= har->alfa;
00300     
00301     if(alpha==0.0f)
00302         return 0;
00303 
00304     /* soften the halo if it intersects geometry */
00305     if(har->mat && har->mat->mode & MA_HALO_SOFT) {
00306         float segment_length, halo_depth, distance_from_z /* , visible_depth */ /* UNUSED */, soften;
00307         
00308         /* calculate halo depth */
00309         segment_length= har->hasize*sasqrt(1.0f - dist/(har->rad*har->rad));
00310         halo_depth= 2.0f*segment_length;
00311 
00312         if(halo_depth < FLT_EPSILON)
00313             return 0;
00314 
00315         /* calculate how much of this depth is visible */
00316         distance_from_z = haloZtoDist(zz) - haloZtoDist(har->zs);
00317         /* visible_depth = halo_depth; */ /* UNUSED */
00318         if(distance_from_z < segment_length) {
00319             soften= (segment_length + distance_from_z)/halo_depth;
00320 
00321             /* apply softening to alpha */
00322             if(soften < 1.0f)
00323                 alpha *= soften;
00324             if(alpha <= 0.0f)
00325                 return 0;
00326         }
00327     }
00328     else {
00329         /* not a soft halo. use the old softening code */
00330         /* halo being intersected? */
00331         if(har->zs> zz-har->zd) {
00332             t= ((float)(zz-har->zs))/(float)har->zd;
00333             alpha*= sqrtf(sqrtf(t));
00334         }
00335     }
00336 
00337     radist= sqrt(dist);
00338 
00339     /* watch it: not used nicely: flarec is set at zero in pixstruct */
00340     if(flarec) har->pixels+= (int)(har->rad-radist);
00341 
00342     if(har->ringc) {
00343         float *rc, fac;
00344         int ofs;
00345         
00346         /* per ring an antialised circle */
00347         ofs= har->seed;
00348         
00349         for(a= har->ringc; a>0; a--, ofs+=2) {
00350             
00351             rc= hashvectf + (ofs % 768);
00352             
00353             fac= fabsf( rc[1]*(har->rad*fabsf(rc[0]) - radist) );
00354             
00355             if(fac< 1.0f) {
00356                 ringf+= (1.0f-fac);
00357             }
00358         }
00359     }
00360 
00361     if(har->type & HA_VECT) {
00362         dist= fabsf( har->cos*(yn) - har->sin*(xn) )/har->rad;
00363         if(dist>1.0f) dist= 1.0f;
00364         if(har->tex) {
00365             zn= har->sin*xn - har->cos*yn;
00366             yn= har->cos*xn + har->sin*yn;
00367             xn= zn;
00368         }
00369     }
00370     else dist= dist/har->radsq;
00371 
00372     if(har->type & HA_FLARECIRC) {
00373         
00374         dist= 0.5+fabs(dist-0.5f);
00375         
00376     }
00377 
00378     if(har->hard>=30) {
00379         dist= sqrt(dist);
00380         if(har->hard>=40) {
00381             dist= sinf(dist*(float)M_PI_2);
00382             if(har->hard>=50) {
00383                 dist= sqrt(dist);
00384             }
00385         }
00386     }
00387     else if(har->hard<20) dist*=dist;
00388 
00389     if(dist < 1.0f)
00390         dist= (1.0f-dist);
00391     else
00392         dist= 0.0f;
00393     
00394     if(har->linec) {
00395         float *rc, fac;
00396         int ofs;
00397         
00398         /* per starpoint an antialiased line */
00399         ofs= har->seed;
00400         
00401         for(a= har->linec; a>0; a--, ofs+=3) {
00402             
00403             rc= hashvectf + (ofs % 768);
00404             
00405             fac= fabs( (xn)*rc[0]+(yn)*rc[1]);
00406             
00407             if(fac< 1.0f )
00408                 linef+= (1.0f-fac);
00409         }
00410         
00411         linef*= dist;
00412     }
00413 
00414     if(har->starpoints) {
00415         float ster, angle;
00416         /* rotation */
00417         angle= atan2(yn, xn);
00418         angle*= (1.0f+0.25f*har->starpoints);
00419         
00420         co= cosf(angle);
00421         si= sinf(angle);
00422         
00423         angle= (co*xn+si*yn)*(co*yn-si*xn);
00424         
00425         ster= fabs(angle);
00426         if(ster>1.0f) {
00427             ster= (har->rad)/(ster);
00428             
00429             if(ster<1.0f) dist*= sqrtf(ster);
00430         }
00431     }
00432 
00433     /* disputable optimize... (ton) */
00434     if(dist<=0.00001f)
00435         return 0;
00436     
00437     dist*= alpha;
00438     ringf*= dist;
00439     linef*= alpha;
00440     
00441     /* The color is either the rgb spec-ed by the user, or extracted from   */
00442     /* the texture                                                           */
00443     if(har->tex) {
00444         col[0]= har->r; 
00445         col[1]= har->g; 
00446         col[2]= har->b;
00447         col[3]= dist;
00448         
00449         do_halo_tex(har, xn, yn, col);
00450         
00451         col[0]*= col[3];
00452         col[1]*= col[3];
00453         col[2]*= col[3];
00454         
00455     }
00456     else {
00457         col[0]= dist*har->r;
00458         col[1]= dist*har->g;
00459         col[2]= dist*har->b;
00460         if(har->type & HA_XALPHA) col[3]= dist*dist;
00461         else col[3]= dist;
00462     }
00463 
00464     if(har->mat) {
00465         if(har->mat->mode & MA_HALO_SHADE) {
00466             /* we test for lights because of preview... */
00467             if(R.lights.first) render_lighting_halo(har, col);
00468         }
00469 
00470         /* Next, we do the line and ring factor modifications. */
00471         if(linef!=0.0f) {
00472             Material *ma= har->mat;
00473             
00474             col[0]+= linef * ma->specr;
00475             col[1]+= linef * ma->specg;
00476             col[2]+= linef * ma->specb;
00477             
00478             if(har->type & HA_XALPHA) col[3]+= linef*linef;
00479             else col[3]+= linef;
00480         }
00481         if(ringf!=0.0f) {
00482             Material *ma= har->mat;
00483 
00484             col[0]+= ringf * ma->mirr;
00485             col[1]+= ringf * ma->mirg;
00486             col[2]+= ringf * ma->mirb;
00487             
00488             if(har->type & HA_XALPHA) col[3]+= ringf*ringf;
00489             else col[3]+= ringf;
00490         }
00491     }
00492     
00493     /* alpha requires clip, gives black dots */
00494     if(col[3] > 1.0f)
00495         col[3]= 1.0f;
00496 
00497     return 1;
00498 }
00499 
00500 /* ------------------------------------------------------------------------- */
00501 
00502 /* Only view vector is important here. Result goes to col_r[3] */
00503 void shadeSkyView(float col_r[3], const float rco[3], const float view[3], const float dxyview[2], short thread)
00504 {
00505     float lo[3], zen[3], hor[3], blend, blendm;
00506     int skyflag;
00507     
00508     /* flag indicating if we render the top hemisphere */
00509     skyflag = WO_ZENUP;
00510     
00511     /* Some view vector stuff. */
00512     if(R.wrld.skytype & WO_SKYREAL) {
00513         
00514         blend= view[0]*R.grvec[0]+ view[1]*R.grvec[1]+ view[2]*R.grvec[2];
00515         
00516         if(blend<0.0f) skyflag= 0;
00517         
00518         blend= fabs(blend);
00519     }
00520     else if(R.wrld.skytype & WO_SKYPAPER) {
00521         blend= 0.5f + 0.5f * view[1];
00522     }
00523     else {
00524         /* the fraction of how far we are above the bottom of the screen */
00525         blend= fabs(0.5f + view[1]);
00526     }
00527 
00528     copy_v3_v3(hor, &R.wrld.horr);
00529     copy_v3_v3(zen, &R.wrld.zenr);
00530 
00531     /* Careful: SKYTEX and SKYBLEND are NOT mutually exclusive! If           */
00532     /* SKYBLEND is active, the texture and color blend are added.           */
00533     if(R.wrld.skytype & WO_SKYTEX) {
00534         copy_v3_v3(lo, view);
00535         if(R.wrld.skytype & WO_SKYREAL) {
00536             
00537             mul_m3_v3(R.imat, lo);
00538             
00539             SWAP(float, lo[1],  lo[2]);
00540             
00541         }
00542         do_sky_tex(rco, lo, dxyview, hor, zen, &blend, skyflag, thread);
00543     }
00544     
00545     if(blend>1.0f) blend= 1.0f;
00546     blendm= 1.0f-blend;
00547     
00548     /* No clipping, no conversion! */
00549     if(R.wrld.skytype & WO_SKYBLEND) {
00550         col_r[0] = (blendm*hor[0] + blend*zen[0]);
00551         col_r[1] = (blendm*hor[1] + blend*zen[1]);
00552         col_r[2] = (blendm*hor[2] + blend*zen[2]);
00553     } else {
00554         /* Done when a texture was grabbed. */
00555         col_r[0]= hor[0];
00556         col_r[1]= hor[1];
00557         col_r[2]= hor[2];
00558     }
00559 }
00560 
00561 /* shade sky according to sun lamps, all parameters are like shadeSkyView except sunsky*/
00562 void shadeSunView(float col_r[3], const float view[3])
00563 {
00564     GroupObject *go;
00565     LampRen *lar;
00566     float sview[3];
00567     int do_init= 1;
00568     
00569     for(go=R.lights.first; go; go= go->next) {
00570         lar= go->lampren;
00571         if(lar->type==LA_SUN && lar->sunsky && (lar->sunsky->effect_type & LA_SUN_EFFECT_SKY)){
00572             float sun_collector[3];
00573             float colorxyz[3];
00574             
00575             if(do_init) {
00576 
00577                 normalize_v3_v3(sview, view);
00578                 mul_m3_v3(R.imat, sview);
00579                 if (sview[2] < 0.0f)
00580                     sview[2] = 0.0f;
00581                 normalize_v3(sview);
00582                 do_init= 0;
00583             }
00584             
00585             GetSkyXYZRadiancef(lar->sunsky, sview, colorxyz);
00586             xyz_to_rgb(colorxyz[0], colorxyz[1], colorxyz[2], &sun_collector[0], &sun_collector[1], &sun_collector[2], 
00587                        lar->sunsky->sky_colorspace);
00588             
00589             ramp_blend(lar->sunsky->skyblendtype, col_r, lar->sunsky->skyblendfac, sun_collector);
00590         }
00591     }
00592 }
00593 
00594 
00595 /*
00596   Stuff the sky color into the collector.
00597  */
00598 void shadeSkyPixel(float collector[4], float fx, float fy, short thread)
00599 {
00600     float view[3], dxyview[2];
00601 
00602     /*
00603       The rules for sky:
00604       1. Draw an image, if a background image was provided. Stop
00605       2. get texture and color blend, and combine these.
00606     */
00607 
00608     float fac;
00609 
00610     if((R.wrld.skytype & (WO_SKYBLEND+WO_SKYTEX))==0) {
00611         /* 1. solid color */
00612         copy_v3_v3(collector, &R.wrld.horr);
00613 
00614         collector[3] = 0.0f;
00615     } 
00616     else {
00617         /* 2. */
00618 
00619         /* This one true because of the context of this routine  */
00620         if(R.wrld.skytype & WO_SKYPAPER) {
00621             view[0]= -1.0f + 2.0f*(fx/(float)R.winx);
00622             view[1]= -1.0f + 2.0f*(fy/(float)R.winy);
00623             view[2]= 0.0;
00624             
00625             dxyview[0]= 1.0f/(float)R.winx;
00626             dxyview[1]= 1.0f/(float)R.winy;
00627         }
00628         else {
00629             calc_view_vector(view, fx, fy);
00630             fac= normalize_v3(view);
00631             
00632             if(R.wrld.skytype & WO_SKYTEX) {
00633                 dxyview[0]= -R.viewdx/fac;
00634                 dxyview[1]= -R.viewdy/fac;
00635             }
00636         }
00637         
00638         /* get sky color in the collector */
00639         shadeSkyView(collector, NULL, view, dxyview, thread);
00640         collector[3] = 0.0f;
00641     }
00642     
00643     calc_view_vector(view, fx, fy);
00644     shadeSunView(collector, view);
00645 }
00646 
00647 /* aerial perspective */
00648 void shadeAtmPixel(struct SunSky *sunsky, float collector[3], float fx, float fy, float distance)
00649 {
00650     float view[3];
00651 
00652     calc_view_vector(view, fx, fy);
00653     normalize_v3(view);
00654     /*mul_m3_v3(R.imat, view);*/
00655     AtmospherePixleShader(sunsky, view, distance, collector);
00656 }
00657 
00658 /* eof */