Revision: 15761
          
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=15761
Author:   unclezeiv
Date:     2008-07-25 18:09:35 +0200 (Fri, 25 Jul 2008)

Log Message:
-----------
Added support for all diffuse shaders. This required to bound the maximum value 
of the shader over a cluster of lights.

Also:
- removed unused values from the OrenNayar shader
- some macros were passed a function call as a parameter, thus issuing it more 
than once: fixed.

Limitations:
- the Oren Nayar shader was pretty complex to bound and the resulting code 
looks a bit slow; there's room for optimizations though
- more testing required

Modified Paths:
--------------
    branches/soc-2008-unclezeiv/source/blender/render/intern/source/lightcuts.c
    
branches/soc-2008-unclezeiv/source/blender/render/intern/source/shadeoutput.c

Modified: 
branches/soc-2008-unclezeiv/source/blender/render/intern/source/lightcuts.c
===================================================================
--- branches/soc-2008-unclezeiv/source/blender/render/intern/source/lightcuts.c 
2008-07-25 13:45:57 UTC (rev 15760)
+++ branches/soc-2008-unclezeiv/source/blender/render/intern/source/lightcuts.c 
2008-07-25 16:09:35 UTC (rev 15761)
@@ -154,10 +154,6 @@
 
        CutNode *cut_nodes;
        int cut_nodes_size;
-#ifdef LIGHTCUTS_DEBUG
-       short dbg_first_pixel;
-       short dbg_jolly;
-#endif
        int stat_samples;
        int stat_cut_size;
        int stat_rays_shot;
@@ -165,6 +161,9 @@
        
        double start_time;
        double tree_creation_time;
+#ifdef LIGHTCUTS_DEBUG
+       int dbg_first_pixel;
+#endif
 } LightcutsData;
 
 #define VEC_LEN_SQ(v) (v[0]*v[0] + v[1]*v[1] + v[2]*v[2])
@@ -395,8 +394,10 @@
                                 * both by a linear falloff with distance = 
d/ld1 and by a
                                 * quadratic falloff with distance = d^2/ld2 
                                 */
+                               float d1= 1.0f / lar->ld1;
+                               float d2= lar->dist / lar->ld2;
                                clus->falloff_type= FALLOFF_MIX;
-                               clus->falloff_dist= lar->dist * MAX2(1.0f / 
lar->ld1, lar->dist / lar->ld2);
+                               clus->falloff_dist= lar->dist * MAX2(d1, d2);
                        }
                        break;
                }
@@ -1089,18 +1090,145 @@
 
 float spec(float inp, int hard);
 
+float bound_OrenNayar_Diff(float max_dot, float min_dot, float *n, float *v, 
float *tmin, float *tmax, float rough_sq)
+{
+       float nv, t, A, B;
+       float View_B[3], lmin[3], lmax[3], mat[3][3];
+       float bound_sin_tan, x;
+       
+       if(max_dot <= 0.0f)
+               return 0.0f;
+       
+       /* Dot product between surface normal and view vector */
+       nv= INPR(n, v);
+       nv= MAX2(nv, 0.0f);
+       
+       /*
+        * original forumla is:
+        *     t = dot(Lit_B, View_B)
+        * where _B vectors are normalized vectors perpendicular to the normal,
+        * pointing towards the light and the camera respectively.
+        *   To bound this we exploit the usual cosine bounding mechanism in
+        * View_B's direction.  
+        */
+       
+       /* TODO: optim: View_B and mat could be precomputed per sample */
+       VECADDFAC(View_B, v, n, -nv);
+       Normalize(View_B);
+       
+       get_axis_matrix(mat, View_B);
+       transform_aabb(mat, tmin, tmax, lmin, lmax);
+       t = compute_cosine_bound(lmin, lmax);
+       
+       /*
+        * real formula is
+        *     a = MAX(acos(realnl), acos(nv)), b = MIN(*)
+        *     sin(a) * tan(b)
+        * this is equivalent to:
+        *     a = MAX(realnl, nv), b = MIN(*)
+        *     sqrt(1 - a * a) * sqrt(1 - b * b) / b
+        * which in turn is bound by:
+        *     sqrt(1 - b * b) * sqrt(1 - b * b) / b = (1 - b * b) / b
+        * Tighter bounds could possibly be found.
+        */
+       x = MIN3(nv, min_dot, 0.95);
+       bound_sin_tan= 1 / x - x;
+       
+       /* TODO: optim: these values can be precomputed (also in shadeoutput.c) 
*/
+       A = 1.0f - 0.5f * rough_sq / (rough_sq + 0.33f);
+       B = 0.45f * rough_sq / (rough_sq + 0.09f);
+       
+       return max_dot * (A + B * t * bound_sin_tan);
+}
+
+float bound_Toon_Diff(float min_ang, float size, float smooth)
+{
+       float ang = saacos( (double)(min_ang) );
+
+       if( ang < size ) return 1.0f;
+       if( ang >= (size + smooth) || smooth == 0.0f ) return 0.0f;
+       return 1.0f - ((ang - size) / smooth);
+}
+
+float bound_Minnaert_Diff(float max_dot, float *n, float *v, float darkness)
+{
+       float nv;
+       
+       if (max_dot <= 0.0f)
+               return 0.0f;
+
+       /* nv = dot product between surface normal and view vector */
+       /* TODO: optim: nv could be precomputed per sample */
+       nv = INPR(n, v);
+       nv = MAX2(nv, 0.0f);
+
+       /* The Real model */
+       if (darkness <= 1.0f)
+               return max_dot * pow(MAX2(nv * max_dot, 0.1f), darkness - 1.0f);
+       
+       /* Nvidia model */
+       return max_dot * pow(1.001f - nv, darkness - 1.0f);
+}
+
+float bound_Fresnel_Diff(float max_dot, float grad, float fac)
+{
+       float t2;
+       
+       if(fac==0.0f) return 1.0f;
+       
+       /* XXX: not sure: are negative values allowed? */
+       if(max_dot>0.0f) t2= 1.0f+max_dot;
+       else t2= 1.0f-max_dot;
+       
+       t2= grad + (1.0f-grad)*pow(t2, fac);
+       
+       return CLAMPIS(t2, 0.0f, 1.0f);
+}
+
 /* error bound: material term */
-/* TODO: currently supporting only lambertian diffuse and Phong specular */
+/* TODO: currently supporting only Phong specular */
 static float calc_material_eb(LightcutsCluster *clus, ShadeInput *shi, float 
tsm[3][3], float *tspos, float msm[3][3], float *mspos)
 {
-       float tmin[3], tmax[3], eb_diff, eb_spec=0.0f;
+       float tmin[3], tmax[3], eb_diff, eb_spec=0.0f, cb;
        transform_aabb(tsm, clus->min, clus->max, tmin, tmax);
        if (clus->type != CLUSTER_SUN) {
                VECADD(tmin, tspos, tmin);
                VECADD(tmax, tspos, tmax);
        }
-       eb_diff= MAX2(compute_cosine_bound(tmin, tmax), 0.0) * shi->refl;
-       /* TODO: optimize */
+       cb= compute_cosine_bound(tmin, tmax);
+       
+       /* TODO: potentially optimizable, the shader is always the same over a 
sample */
+       switch(shi->mat->diff_shader) {
+       case MA_DIFF_TOON:
+               eb_diff= bound_Toon_Diff(MAX2(cb, 0.0), shi->mat->param[0], 
shi->mat->param[1]);
+               break;
+       case MA_DIFF_MINNAERT:
+               eb_diff= bound_Minnaert_Diff(MAX2(cb, 0.0), shi->vn, shi->view, 
shi->mat->darkness);
+               break;
+       case MA_DIFF_FRESNEL:
+               eb_diff= bound_Fresnel_Diff(MAX2(cb, 0.0), shi->mat->param[0], 
shi->mat->param[1]);
+               break;
+       case MA_DIFF_ORENNAYAR:
+               {
+                       /* TODO: optim: tsmdwn is always the same over the 
sample */
+                       float tsmdwn[3][3], tdmin[3], tdmax[3], minb;
+                       VECCOPY(tsmdwn[0], tsm[1]);
+                       VECCOPY(tsmdwn[1], tsm[0]);
+                       VECCOPY(tsmdwn[2], tsm[2]);
+                       VECNEG(tsmdwn[2]);
+                       transform_aabb(tsmdwn, clus->min, clus->max, tdmin, 
tdmax);
+                       if (clus->type != CLUSTER_SUN) {
+                               VECADD(tdmin, tspos, tdmin);
+                               VECADD(tdmax, tspos, tdmax);
+                       }
+                       minb= compute_cosine_bound(tdmin, tdmax);
+                       eb_diff= bound_OrenNayar_Diff(MAX2(cb, 0.0f), 
MAX2(minb, 0.0f), shi->vn, shi->view, clus->min, clus->max, shi->mat->roughness 
* shi->mat->roughness);
+               }
+               break;
+       default:
+               eb_diff= MAX2(cb, 0.0) * shi->refl;
+       }
+       
        if (shi->mat->spec_shader==MA_SPEC_PHONG) {
                transform_aabb(msm, clus->min, clus->max, tmin, tmax);
                if (clus->type != CLUSTER_SUN) {
@@ -1108,7 +1236,8 @@
                        VECADD(tmax, mspos, tmax);
                }
                // t= shadfac[3]*shi->spec*visifac*specfac;
-               eb_spec= spec(MAX2(compute_cosine_bound(tmin, tmax), 0.0), 
shi->har) * shi->spec;
+               cb= compute_cosine_bound(tmin, tmax);
+               eb_spec= spec(MAX2(cb, 0.0), shi->har) * shi->spec;
        }
        return eb_diff + eb_spec;
 }
@@ -1169,8 +1298,10 @@
                
                if (angle <= clus->cone_angle)
                        return 1.0;
-               return get_attenuation(clus, pos) * MAX2(0.0f, cosf(angle - 
clus->cone_angle));
                
+               cos_t= cosf(angle - clus->cone_angle);
+               return get_attenuation(clus, pos) * MAX2(0.0f, cos_t);
+               
                /*
                 * TODO: possible optimizations
                 * cos(a+b) = cos_a*cos_b - sin_a*sin_b

Modified: 
branches/soc-2008-unclezeiv/source/blender/render/intern/source/shadeoutput.c
===================================================================
--- 
branches/soc-2008-unclezeiv/source/blender/render/intern/source/shadeoutput.c   
    2008-07-25 13:45:57 UTC (rev 15760)
+++ 
branches/soc-2008-unclezeiv/source/blender/render/intern/source/shadeoutput.c   
    2008-07-25 16:09:35 UTC (rev 15761)
@@ -696,7 +696,7 @@
 }
 
 /* cartoon render diffuse */
-static float Toon_Diff( float *n, float *l, float *v, float size, float smooth 
)
+static float Toon_Diff( float *n, float *l, float size, float smooth )
 {
        float rslt, ang;
 
@@ -715,23 +715,14 @@
 
 /* 'nl' is either dot product, or return value of area light */
 /* in latter case, only last multiplication uses 'nl' */
-static float OrenNayar_Diff(float nl, float *n, float *l, float *v, float 
rough_sq )
+static float OrenNayar_Diff(float nl, float *n, float *l, float *v, float 
rough_sq)
 {
-       float i, nh, nv, vh, realnl, h[3];
+       float i, nv, realnl;
        float a, b, t, A, B;
        float Lit_A, View_A, Lit_B[3], View_B[3];
        
        if(nl<0.0f) return 0.0f; /* value from area light */
-       
-       h[0]= v[0]+l[0];
-       h[1]= v[1]+l[1];
-       h[2]= v[2]+l[2];
-       Normalize(h);
-       
-       /* Dot product between surface normal and half-way vector */
-       nh= INPR(n, h);
-       nh= MAX2(nh, 0.0f);
-       
+               
        /* Dot product between surface normal and view vector */
        nv= INPR(n, v);
        nv= MAX2(nv, 0.0f);
@@ -739,11 +730,7 @@
        /* Dot product between surface normal and light vector */
        realnl= INPR(n, l);
        if(realnl<=0.0f) return 0.0f;
-       
-       /* Dot product between view vector and halfway vector */
-       vh= INPR(v, h);
-       vh= MAX2(vh, 0.0f);
-       
+               
        Lit_A = saacos(realnl);
        View_A = saacos( nv );
        
@@ -1300,7 +1287,7 @@
                
                /* diffuse shaders (oren nayer gets inp from area light) */
                if(ma->diff_shader==MA_DIFF_ORENNAYAR) is= OrenNayar_Diff(inp, 
vn, lv, view, ma->roughness * ma->roughness);
-               else if(ma->diff_shader==MA_DIFF_TOON) is= Toon_Diff(vn, lv, 
view, ma->param[0], ma->param[1]);
+               else if(ma->diff_shader==MA_DIFF_TOON) is= Toon_Diff(vn, lv, 
ma->param[0], ma->param[1]);
                else if(ma->diff_shader==MA_DIFF_MINNAERT) is= 
Minnaert_Diff(inp, vn, view, ma->darkness);
                else if(ma->diff_shader==MA_DIFF_FRESNEL) is= Fresnel_Diff(vn, 
lv, view, ma->param[0], ma->param[1]);
                else is= inp;   // Lambert
@@ -1924,7 +1911,7 @@
 #ifdef LC_LATER /* we start by supporting only lambert */
                /* diffuse shaders (oren nayer gets inp from area light) */
                if(ma->diff_shader==MA_DIFF_ORENNAYAR) is= OrenNayar_Diff(inp, 
vn, lv, view, ma->roughness * ma->roughness);
-               else if(ma->diff_shader==MA_DIFF_TOON) is= Toon_Diff(vn, lv, 
view, ma->param[0], ma->param[1]);
+               else if(ma->diff_shader==MA_DIFF_TOON) is= Toon_Diff(vn, lv, 
ma->param[0], ma->param[1]);
                else if(ma->diff_shader==MA_DIFF_MINNAERT) is= 
Minnaert_Diff(inp, vn, view, ma->darkness);
                else if(ma->diff_shader==MA_DIFF_FRESNEL) is= Fresnel_Diff(vn, 
lv, view, ma->param[0], ma->param[1]);
                else is= inp;   // Lambert
@@ -2099,10 +2086,11 @@
 {
        Material *ma= shi->mat;
        float lv[3], lampdist, shadfac[4];
-       float i, is, i_noshad, inp, *vn;
+       float i, is, i_noshad, inp, *vn, *view, phongcorr=1.0f;
        float visifac;
        
        vn= shi->vn;
+       view= shi->view;
        
        *pi= *pi_noshad= *pt= 0.0f;
        
@@ -2116,8 +2104,33 @@
 
        /* dot product and reflectivity */
        /* inp = dotproduct, is = shader result, i = lamp energy (with shadow), 
i_noshad = i without shadow */
-       i= is= inp= vn[0]*lv[0] + vn[1]*lv[1] + vn[2]*lv[2];
+       inp= vn[0]*lv[0] + vn[1]*lv[1] + vn[2]*lv[2];
        
+       /* diffuse shaders */
+       if(lar->mode & LA_NO_DIFF) {
+               is= 0.0f;       // skip shaders
+       }
+#ifdef LC_USELESS
+       else if(lar->type==LA_HEMI) {
+               is= 0.5f*inp + 0.5f;
+       }
+#endif
+       else {
+#ifdef LC_USELESS /* we convert area lights in pointlights */
+               if(lar->type==LA_AREA)
+                       inp= area_lamp_energy_multisample(lar, shi->co, vn);
+#endif
+

@@ Diff output truncated at 10240 characters. @@

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to