=bmesh= merge from trunk at r36529
[blender.git] / source / blender / render / intern / source / shadeoutput.c
index 58284534ce900a0ee1485f4e5e1803bae7bf233e..55249847aa4b0f44800a518da3f79aea1f9f64d0 100644 (file)
@@ -384,25 +384,6 @@ void renderspothalo(ShadeInput *shi, float *col, float alpha)
 
 /* ---------------- shaders ----------------------- */
 
-static double Normalize_d(double *n)
-{
-       double d;
-       
-       d= n[0]*n[0]+n[1]*n[1]+n[2]*n[2];
-
-       if(d>0.00000000000000001) {
-               d= sqrt(d);
-
-               n[0]/=d; 
-               n[1]/=d; 
-               n[2]/=d;
-       } else {
-               n[0]=n[1]=n[2]= 0.0;
-               d= 0.0;
-       }
-       return d;
-}
-
 /* mix of 'real' fresnel and allowing control. grad defines blending gradient */
 float fresnel_fac(float *view, float *vn, float grad, float fac)
 {
@@ -441,10 +422,10 @@ static float area_lamp_energy(float (*area)[3], float *co, float *vn)
        VECSUB(vec[2], co, area[2]);
        VECSUB(vec[3], co, area[3]);
        
-       Normalize_d(vec[0]);
-       Normalize_d(vec[1]);
-       Normalize_d(vec[2]);
-       Normalize_d(vec[3]);
+       normalize_dv3(vec[0]);
+       normalize_dv3(vec[1]);
+       normalize_dv3(vec[2]);
+       normalize_dv3(vec[3]);
 
        /* cross product */
        CROSS(cross[0], vec[0], vec[1]);
@@ -452,10 +433,10 @@ static float area_lamp_energy(float (*area)[3], float *co, float *vn)
        CROSS(cross[2], vec[2], vec[3]);
        CROSS(cross[3], vec[3], vec[0]);
 
-       Normalize_d(cross[0]);
-       Normalize_d(cross[1]);
-       Normalize_d(cross[2]);
-       Normalize_d(cross[3]);
+       normalize_dv3(cross[0]);
+       normalize_dv3(cross[1]);
+       normalize_dv3(cross[2]);
+       normalize_dv3(cross[3]);
 
        /* angles */
        rad[0]= vec[0][0]*vec[1][0]+ vec[0][1]*vec[1][1]+ vec[0][2]*vec[1][2];
@@ -726,7 +707,7 @@ static float Toon_Diff( float *n, float *l, float *v, float size, float smooth )
 /* in latter case, only last multiplication uses 'nl' */
 static float OrenNayar_Diff(float nl, float *n, float *l, float *v, float rough )
 {
-       float i, nh, nv, vh, realnl, h[3];
+       float i/*, nh*/, nv, vh, realnl, h[3];
        float a, b, t, A, B;
        float Lit_A, View_A, Lit_B[3], View_B[3];
        
@@ -735,8 +716,8 @@ static float OrenNayar_Diff(float nl, float *n, float *l, float *v, float rough
        h[2]= v[2]+l[2];
        normalize_v3(h);
        
-       nh= n[0]*h[0]+n[1]*h[1]+n[2]*h[2]; /* Dot product between surface normal and half-way vector */
-       if(nh<0.0f) nh = 0.0f;
+       /* nh= n[0]*h[0]+n[1]*h[1]+n[2]*h[2]; */ /* Dot product between surface normal and half-way vector */
+       /* if(nh<0.0f) nh = 0.0f; */
        
        nv= n[0]*v[0]+n[1]*v[1]+n[2]*v[2]; /* Dot product between surface normal and view vector */
        if(nv<=0.0f) nv= 0.0f;
@@ -878,7 +859,9 @@ void shade_color(ShadeInput *shi, ShadeResult *shr)
 
        if(ma->fresnel_tra!=0.0f) 
                shi->alpha*= fresnel_fac(shi->view, shi->vn, ma->fresnel_tra_i, ma->fresnel_tra);
-
+       
+       if (!(shi->mode & MA_TRANSP)) shi->alpha= 1.0f;
+       
        shr->diff[0]= shi->r;
        shr->diff[1]= shi->g;
        shr->diff[2]= shi->b;
@@ -1502,10 +1485,10 @@ static void shade_lamp_loop_only_shadow(ShadeInput *shi, ShadeResult *shr)
                float inpr, lv[3];
                float *view, shadfac[4];
                float ir, accum, visifac, lampdist;
+               float shaded = 0.0f, lightness = 0.0f;
                
 
                view= shi->view;
-
                accum= ir= 0.0f;
                
                lights= get_lights(shi);
@@ -1521,28 +1504,66 @@ static void shade_lamp_loop_only_shadow(ShadeInput *shi, ShadeResult *shr)
                        
                        if(lar->shb || (lar->mode & LA_SHAD_RAY)) {
                                visifac= lamp_get_visibility(lar, shi->co, lv, &lampdist);
+                               ir+= 1.0f;
+
                                if(visifac <= 0.0f) {
-                                       ir+= 1.0f;
-                                       accum+= 1.0f;
+                                       if (shi->mat->shadowonly_flag == MA_SO_OLD)
+                                               accum+= 1.0f;
+
                                        continue;
                                }
                                inpr= INPR(shi->vn, lv);
                                if(inpr <= 0.0f) {
-                                       ir+= 1.0f;
-                                       accum+= 1.0f;
+                                       if (shi->mat->shadowonly_flag == MA_SO_OLD)
+                                               accum+= 1.0f;
+
                                        continue;
-                               }                               
+                               }
+
                                lamp_get_shadow(lar, shi, inpr, shadfac, shi->depth);
 
-                               ir+= 1.0f;
-                               accum+= (1.0f-visifac) + (visifac)*rgb_to_grayscale(shadfac)*shadfac[3];
+                               if (shi->mat->shadowonly_flag == MA_SO_OLD) {
+                                       /* Old "Shadows Only" */
+                                       accum+= (1.0f-visifac) + (visifac)*rgb_to_grayscale(shadfac)*shadfac[3];
+                               }
+                               else {
+                                       shaded += rgb_to_grayscale(shadfac)*shadfac[3] * visifac * lar->energy;
+
+                                       if (shi->mat->shadowonly_flag == MA_SO_SHADOW) {
+                                               lightness += visifac * lar->energy;
+                                       }
+                               }
                        }
                }
+
+               /* Apply shadows as alpha */
                if(ir>0.0f) {
-                       accum/= ir;
-                       shr->alpha= (shi->mat->alpha)*(1.0f-accum);
+                       if (shi->mat->shadowonly_flag == MA_SO_OLD) {
+                               accum = 1.0f - accum/ir;
+                       }
+                       else {
+                               if (shi->mat->shadowonly_flag == MA_SO_SHADOW) {
+                                       if (lightness > 0.0f) {
+                                               /* Get shadow value from between 0.0f and non-shadowed lightness */
+                                               accum = (lightness - shaded) / (lightness);
+                                       }
+                                       else {
+                                               accum = 0.0f;
+                                       }
+                               }
+                               else { /* shadowonly_flag == MA_SO_SHADED */
+                                       /* Use shaded value */
+                                       accum = 1.0f - shaded;
+                       }}
+
+                       shr->alpha= (shi->alpha)*(accum);
+                       if (shr->alpha<0.0f) shr->alpha=0.0f;
+               }
+               else {
+                       /* If "fully shaded", use full alpha even on areas that have no lights */
+                       if (shi->mat->shadowonly_flag == MA_SO_SHADED) shr->alpha=shi->alpha;
+                       else shr->alpha= 0.f;
                }
-               else shr->alpha= 0.f;
        }
        
        /* quite disputable this...  also note it doesn't mirror-raytrace */    
@@ -1551,18 +1572,31 @@ static void shade_lamp_loop_only_shadow(ShadeInput *shi, ShadeResult *shr)
                
                if(R.wrld.mode & WO_AMB_OCC) {
                        f= R.wrld.aoenergy*shi->amb;
-
+                       
                        if(R.wrld.aomix==WO_AOADD) {
-                               f= f*(1.0f - rgb_to_grayscale(shi->ao));
-                               shr->alpha= (shr->alpha + f)*f;
+                               if (shi->mat->shadowonly_flag == MA_SO_OLD) {
+                                       f= f*(1.0f - rgb_to_grayscale(shi->ao));
+                                       shr->alpha= (shr->alpha + f)*f;
+                               }
+                               else {
+                                       shr->alpha -= f*rgb_to_grayscale(shi->ao);
+                                       if (shr->alpha<0.0f) shr->alpha=0.0f;
+                               }
                        }
-                       else
+                       else /* AO Multiply */
                                shr->alpha= (1.0f - f)*shr->alpha + f*(1.0f - (1.0f - shr->alpha)*rgb_to_grayscale(shi->ao));
                }
 
                if(R.wrld.mode & WO_ENV_LIGHT) {
-                       f= R.wrld.ao_env_energy*shi->amb*(1.0f - rgb_to_grayscale(shi->env));
-                       shr->alpha= (shr->alpha + f)*f;
+                       if (shi->mat->shadowonly_flag == MA_SO_OLD) {
+                               f= R.wrld.ao_env_energy*shi->amb*(1.0f - rgb_to_grayscale(shi->env));
+                               shr->alpha= (shr->alpha + f)*f;
+                       }
+                       else {
+                               f= R.wrld.ao_env_energy*shi->amb;
+                               shr->alpha -= f*rgb_to_grayscale(shi->env);
+                               if (shr->alpha<0.0f) shr->alpha=0.0f;
+                       }
                }
        }
 }
@@ -1583,6 +1617,8 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr)
        
        memset(shr, 0, sizeof(ShadeResult));
        
+       if(!(shi->mode & MA_TRANSP)) shi->alpha = 1.0f;
+       
        /* separate loop */
        if(ma->mode & MA_ONLYSHADOW) {
                shade_lamp_loop_only_shadow(shi, shr);
@@ -1599,10 +1635,12 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr)
                        shi->g= shi->vcol[1];
                        shi->b= shi->vcol[2];
                        if(ma->mode & (MA_FACETEXTURE_ALPHA))
-                               shi->alpha= shi->vcol[3];
+                               shi->alpha= (shi->mode & MA_TRANSP) ? shi->vcol[3] : 1.0f;
                }
-               if(ma->texco)
+               if(ma->texco){
                        do_material_tex(shi);
+                       if (!(shi->mode & MA_TRANSP)) shi->alpha = 1.0f;
+               }
                
                shr->col[0]= shi->r*shi->alpha;
                shr->col[1]= shi->g*shi->alpha;
@@ -1757,11 +1795,11 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr)
        
        /* alpha in end, spec can influence it */
        if(passflag & (SCE_PASS_COMBINED)) {
-               if(ma->fresnel_tra!=0.0f) 
+               if((ma->fresnel_tra!=0.0f) && (shi->mode & MA_TRANSP))
                        shi->alpha*= fresnel_fac(shi->view, shi->vn, ma->fresnel_tra_i, ma->fresnel_tra);
                        
                /* note: shi->mode! */
-               if(shi->mode & MA_TRANSP) {
+               if(shi->mode & MA_TRANSP && (shi->mode & (MA_ZTRANSP|MA_RAYTRANSP))) {
                        if(shi->spectra!=0.0f) {
                                float t = MAX3(shr->spec[0], shr->spec[1], shr->spec[2]);
                                t *= shi->spectra;
@@ -1831,7 +1869,7 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr)
                        shr->combined[0] *= obcol[0];
                        shr->combined[1] *= obcol[1];
                        shr->combined[2] *= obcol[2];
-                       shr->alpha *= obcol[3];
+                       if (shi->mode & MA_TRANSP) shr->alpha *= obcol[3];
                }
        }