converted more mixed tab/space indentations to tabs. only whitespace changes.
[blender.git] / source / blender / render / intern / source / pixelshading.c
index 4e58978..2d42938 100644 (file)
@@ -1,4 +1,4 @@
-/**
+/*
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -14,7 +14,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  *
  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
  * All rights reserved.
  * ***** END GPL LICENSE BLOCK *****
  */
 
+/** \file blender/render/intern/source/pixelshading.c
+ *  \ingroup render
+ */
+
+
+#include <float.h>
 #include <math.h>
 #include <string.h>
-#include "BLI_arithb.h"
+
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
 
 /* External modules: */
 #include "IMB_imbuf_types.h"
 #include "IMB_imbuf.h"
-#include "MTC_matrixops.h"
-#include "MTC_vectorops.h"
 
 #include "DNA_camera_types.h"
 #include "DNA_group_types.h"
 #include "DNA_texture_types.h"
 #include "DNA_lamp_types.h"
 
+#include "BKE_colortools.h"
 #include "BKE_image.h"
 #include "BKE_global.h"
+#include "BKE_material.h"
 #include "BKE_texture.h"
-#include "BKE_utildefines.h"
+
 
 /* own module */
 #include "render_types.h"
@@ -56,6 +64,8 @@
 #include "rendercore.h"
 #include "shadbuf.h"
 #include "pixelshading.h"
+#include "shading.h"
+#include "sunsky.h"
 
 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
 /* defined in pipeline.c, is hardcopy of active dynamic allocated Render */
@@ -139,7 +149,7 @@ static void render_lighting_halo(HaloRen *har, float *colf)
                        
                        VECCOPY(shi.co, rco);
                        shi.osatex= 0;
-                       do_lamp_tex(lar, lv, &shi, lacol);
+                       do_lamp_tex(lar, lv, &shi, lacol, LA_TEXTURE);
                }
                
                if(lar->type==LA_SPOT) {
@@ -150,7 +160,7 @@ static void render_lighting_halo(HaloRen *har, float *colf)
                                        
                                        /* rotate view to lampspace */
                                        VECCOPY(lvrot, lv);
-                                       MTC_Mat3MulVecfl(lar->imat, lvrot);
+                                       mul_m3_v3(lar->imat, lvrot);
                                        
                                        x= MAX2(fabs(lvrot[0]/lvrot[2]) , fabs(lvrot[1]/lvrot[2]));
                                        /* 1.0/(sqrt(1+x*x)) is equivalent to cos(atan(x)) */
@@ -182,7 +192,7 @@ static void render_lighting_halo(HaloRen *har, float *colf)
                                        inp= vn[0]*lv[0] + vn[1]*lv[1] + vn[2]*lv[2];
                                        if(inp>0.0) {
                                                /* testshadowbuf==0.0 : 100% shadow */
-                                               shadfac = testshadowbuf(lar->shb, rco, dco, dco, inp, 0.0f);
+                                               shadfac = testshadowbuf(&R, lar->shb, rco, dco, dco, inp, 0.0f);
                                                if( shadfac>0.0 ) {
                                                        shadfac*= inp*soft*lar->energy;
                                                        ir -= shadfac;
@@ -219,7 +229,7 @@ static void render_lighting_halo(HaloRen *har, float *colf)
                if(i> -0.41) {                  /* heuristic valua! */
                        shadfac= 1.0;
                        if(lar->shb) {
-                               shadfac = testshadowbuf(lar->shb, rco, dco, dco, inp, 0.0f);
+                               shadfac = testshadowbuf(&R, lar->shb, rco, dco, dco, inp, 0.0f);
                                if(shadfac==0.0) continue;
                                i*= shadfac;
                        }
@@ -243,8 +253,36 @@ static void render_lighting_halo(HaloRen *har, float *colf)
 }
 
 
+/**
+ * Converts a halo z-buffer value to distance from the camera's near plane
+ * @param z The z-buffer value to convert
+ * @return a distance from the camera's near plane in blender units
+ */
+static float haloZtoDist(int z)
+{
+       float zco = 0;
+
+       if(z >= 0x7FFFFF)
+               return 10e10;
+       else {
+               zco = (float)z/(float)0x7FFFFF;
+               if(R.r.mode & R_ORTHO)
+                       return (R.winmat[3][2] - zco*R.winmat[3][3])/(R.winmat[2][2]);
+               else
+                       return (R.winmat[3][2])/(R.winmat[2][2] - R.winmat[2][3]*zco);
+       }
+}
 
-void shadeHaloFloat(HaloRen *har,  float *col, int zz, 
+/**
+ * @param col (float[4]) Store the rgb color here (with alpha)
+ * The alpha is used to blend the color to the background 
+ * color_new = (1-alpha)*color_background + color
+ * @param zz The current zbuffer value at the place of this pixel
+ * @param dist Distance of the pixel from the center of the halo squared. Given in pixels
+ * @param xn The x coordinate of the pixel relaticve to the center of the halo. given in pixels
+ * @param yn The y coordinate of the pixel relaticve to the center of the halo. given in pixels
+ */
+int shadeHaloFloat(HaloRen *har,  float *col, int zz, 
                                        float dist, float xn,  float yn, short flarec)
 {
        /* fill in col */
@@ -252,23 +290,51 @@ void shadeHaloFloat(HaloRen *har,  float *col, int zz,
        int a;
    
        if(R.wrld.mode & WO_MIST) {
-       if(har->type & HA_ONLYSKY) {
-           /* stars but no mist */
-           alpha= har->alfa;
-       }
-       else {
-           /* a bit patchy... */
-           alpha= mistfactor(-har->co[2], har->co)*har->alfa;
-       }
+               if(har->type & HA_ONLYSKY) {
+                       /* stars but no mist */
+                       alpha= har->alfa;
+               }
+               else {
+                       /* a bit patchy... */
+                       alpha= mistfactor(-har->co[2], har->co)*har->alfa;
+               }
        }
        else alpha= har->alfa;
        
-       if(alpha==0.0) {
-               col[0] = 0.0;
-               col[1] = 0.0;
-               col[2] = 0.0;
-               col[3] = 0.0;
-               return;
+       if(alpha==0.0)
+               return 0;
+
+       /* soften the halo if it intersects geometry */
+       if(har->mat && har->mat->mode & MA_HALO_SOFT) {
+               float segment_length, halo_depth, distance_from_z, visible_depth, soften;
+               
+               /* calculate halo depth */
+               segment_length= har->hasize*sasqrt(1.0f - dist/(har->rad*har->rad));
+               halo_depth= 2.0f*segment_length;
+
+               if(halo_depth < FLT_EPSILON)
+                       return 0;
+
+               /* calculate how much of this depth is visible */
+               distance_from_z = haloZtoDist(zz) - haloZtoDist(har->zs);
+               visible_depth = halo_depth;
+               if(distance_from_z < segment_length) {
+                       soften= (segment_length + distance_from_z)/halo_depth;
+
+                       /* apply softening to alpha */
+                       if(soften < 1.0f)
+                               alpha *= soften;
+                       if(alpha <= 0.0f)
+                               return 0;
+               }
+       }
+       else {
+               /* not a soft halo. use the old softening code */
+               /* halo being intersected? */
+               if(har->zs> zz-har->zd) {
+                       t= ((float)(zz-har->zs))/(float)har->zd;
+                       alpha*= sqrt(sqrt(t));
+               }
        }
 
        radist= sqrt(dist);
@@ -366,21 +432,10 @@ void shadeHaloFloat(HaloRen *har,  float *col, int zz,
                        if(ster<1.0) dist*= sqrt(ster);
                }
        }
-       
-       /* halo being intersected? */
-       if(har->zs> zz-har->zd) {
-               t= ((float)(zz-har->zs))/(float)har->zd;
-               alpha*= sqrt(sqrt(t));
-       }
 
        /* disputable optimize... (ton) */
-       if(dist<=0.00001) {
-               col[0] = 0.0;
-               col[1] = 0.0;
-               col[2] = 0.0;
-               col[3] = 0.0;
-               return;
-       }
+       if(dist<=0.00001)
+               return 0;
        
        dist*= alpha;
        ringf*= dist;
@@ -441,6 +496,8 @@ void shadeHaloFloat(HaloRen *har,  float *col, int zz,
        /* alpha requires clip, gives black dots */
        if(col[3] > 1.0f)
                col[3]= 1.0f;
+
+       return 1;
 }
 
 /* ------------------------------------------------------------------------- */
@@ -461,7 +518,7 @@ static void fillBackgroundImage(float *collector, float fx, float fy)
 }
 
 /* Only view vector is important here. Result goes to colf[3] */
-void shadeSkyView(float *colf, float *rco, float *view, float *dxyview)
+void shadeSkyView(float *colf, float *rco, float *view, float *dxyview, short thread)
 {
        float lo[3], zen[3], hor[3], blend, blendm;
        int skyflag;
@@ -485,22 +542,22 @@ void shadeSkyView(float *colf, float *rco, float *view, float *dxyview)
                /* the fraction of how far we are above the bottom of the screen */
                blend= fabs(0.5+ view[1]);
        }
-       
-       hor[0]= R.wrld.horr; hor[1]= R.wrld.horg; hor[2]= R.wrld.horb;
-       zen[0]= R.wrld.zenr; zen[1]= R.wrld.zeng; zen[2]= R.wrld.zenb;
-       
+
+       VECCOPY(hor, &R.wrld.horr);
+       VECCOPY(zen, &R.wrld.zenr);
+
        /* Careful: SKYTEX and SKYBLEND are NOT mutually exclusive! If           */
        /* SKYBLEND is active, the texture and color blend are added.           */
        if(R.wrld.skytype & WO_SKYTEX) {
                VECCOPY(lo, view);
                if(R.wrld.skytype & WO_SKYREAL) {
                        
-                       MTC_Mat3MulVecfl(R.imat, lo);
+                       mul_m3_v3(R.imat, lo);
                        
                        SWAP(float, lo[1],  lo[2]);
                        
                }
-               do_sky_tex(rco, lo, dxyview, hor, zen, &blend, skyflag);
+               do_sky_tex(rco, lo, dxyview, hor, zen, &blend, skyflag, thread);
        }
        
        if(blend>1.0) blend= 1.0;
@@ -519,13 +576,48 @@ void shadeSkyView(float *colf, float *rco, float *view, float *dxyview)
        }
 }
 
+/* shade sky according to sun lamps, all parameters are like shadeSkyView except sunsky*/
+void shadeSunView(float *colf, float *view)
+{
+       GroupObject *go;
+       LampRen *lar;
+       float sview[3];
+       int do_init= 1;
+       
+       for(go=R.lights.first; go; go= go->next) {
+               lar= go->lampren;
+               if(lar->type==LA_SUN && lar->sunsky && (lar->sunsky->effect_type & LA_SUN_EFFECT_SKY)){
+                       float sun_collector[3];
+                       float colorxyz[3];
+                       
+                       if(do_init) {
+                               
+                               VECCOPY(sview, view);
+                               normalize_v3(sview);
+                               mul_m3_v3(R.imat, sview);
+                               if (sview[2] < 0.0)
+                                       sview[2] = 0.0;
+                               normalize_v3(sview);
+                               do_init= 0;
+                       }
+                       
+                       GetSkyXYZRadiancef(lar->sunsky, sview, colorxyz);
+                       xyz_to_rgb(colorxyz[0], colorxyz[1], colorxyz[2], &sun_collector[0], &sun_collector[1], &sun_collector[2], 
+                                          lar->sunsky->sky_colorspace);
+                       
+                       ramp_blend(lar->sunsky->skyblendtype, colf, colf+1, colf+2, lar->sunsky->skyblendfac, sun_collector);
+               }
+       }
+}
+
+
 /*
   Stuff the sky color into the collector.
  */
-void shadeSkyPixel(float *collector, float fx, float fy) 
+void shadeSkyPixel(float *collector, float fx, float fy, short thread
 {
        float view[3], dxyview[2];
-       
+
        /*
          The rules for sky:
          1. Draw an image, if a background image was provided. Stop
@@ -537,13 +629,11 @@ void shadeSkyPixel(float *collector, float fx, float fy)
        /* 1. Do a backbuffer image: */ 
        if(R.r.bufflag & 1) {
                fillBackgroundImage(collector, fx, fy);
-               return;
        } 
        else if((R.wrld.skytype & (WO_SKYBLEND+WO_SKYTEX))==0) {
                /* 2. solid color */
-               collector[0] = R.wrld.horr;
-               collector[1] = R.wrld.horg;
-               collector[2] = R.wrld.horb;
+               VECCOPY(collector, &R.wrld.horr);
+
                collector[3] = 0.0f;
        } 
        else {
@@ -560,7 +650,7 @@ void shadeSkyPixel(float *collector, float fx, float fy)
                }
                else {
                        calc_view_vector(view, fx, fy);
-                       fac= Normalize(view);
+                       fac= normalize_v3(view);
                        
                        if(R.wrld.skytype & WO_SKYTEX) {
                                dxyview[0]= -R.viewdx/fac;
@@ -569,10 +659,23 @@ void shadeSkyPixel(float *collector, float fx, float fy)
                }
                
                /* get sky color in the collector */
-               shadeSkyView(collector, NULL, view, dxyview);
+               shadeSkyView(collector, NULL, view, dxyview, thread);
                collector[3] = 0.0f;
        }
+       
+       calc_view_vector(view, fx, fy);
+       shadeSunView(collector, view);
 }
 
+/* aerial perspective */
+void shadeAtmPixel(struct SunSky *sunsky, float *collector, float fx, float fy, float distance)
+{
+       float view[3];
+               
+       calc_view_vector(view, fx, fy);
+       normalize_v3(view);
+       /*mul_m3_v3(R.imat, view);*/
+       AtmospherePixleShader(sunsky, view, distance, collector);
+}
 
 /* eof */