Revision: 15864
          
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=15864
Author:   unclezeiv
Date:     2008-07-29 13:53:43 +0200 (Tue, 29 Jul 2008)

Log Message:
-----------
Added support for "Bias" a.k.a. "Phong correction" a.k.a. terminator problem 
etc.

Also rationalized the code a bit, and optimized the Oren Nayar bounding.

Notes:
- I'm not currently bounding the bias for the specular component; I also have a 
suspect that the current code is wrong for the specular case in shade_lamp_loop 
(will look into it)
- bounding components is good as it potentially saves computations, but it can 
get expensive itself on the other hand; a thourough run-time analysis should be 
run to see if some of the bounding code is not worth calling

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-29 11:37:11 UTC (rev 15863)
+++ branches/soc-2008-unclezeiv/source/blender/render/intern/source/lightcuts.c 
2008-07-29 11:53:43 UTC (rev 15864)
@@ -167,6 +167,17 @@
 #endif
 } LightcutsData;
 
+typedef struct SampleCoordInfo {
+       float tsm[3][3];        /* tangent space matrix */
+       float tspos[3];         /* sample position in tangent space */
+       float msm[3][3];        /* mirror direction space matrix */
+       float mspos[3];         /* sample position in mirror space */
+       float dtsm[3][3];       /* tangent space matrix pointing downwards */
+       float dtspos[3];
+       float phongcorr_thresh; /* sample threshold (terminator problem) */
+       short do_phongcorr;
+} SampleCoordInfo;
+
 #define VEC_LEN_SQ(v) (v[0]*v[0] + v[1]*v[1] + v[2]*v[2])
 #define VECCOPYMUL(v1,v2,aS) {*(v1)= *(v2)*aS; *(v1+1)= *(v2+1)*aS; *(v1+2)= 
*(v2+2)*aS;}
 #define VECNEG(v) {*(v)=-*(v); *(v+1)=-*(v+1); *(v+2)=-*(v+2);}
@@ -1099,7 +1110,7 @@
 
 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)
+static 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];
@@ -1150,7 +1161,7 @@
        return max_dot * (A + B * t * bound_sin_tan);
 }
 
-float bound_Toon_Diff(float min_ang, float size, float smooth)
+static float bound_Toon_Diff(float min_ang, float size, float smooth)
 {
        float ang = saacos( (double)(min_ang) );
 
@@ -1159,7 +1170,7 @@
        return 1.0f - ((ang - size) / smooth);
 }
 
-float bound_Minnaert_Diff(float max_dot, float *n, float *v, float darkness)
+static float bound_Minnaert_Diff(float max_dot, float *n, float *v, float 
darkness)
 {
        float nv;
        
@@ -1179,7 +1190,7 @@
        return max_dot * pow(1.001f - nv, darkness - 1.0f);
 }
 
-float bound_Fresnel_Diff(float max_dot, float grad, float fac)
+static float bound_Fresnel_Diff(float max_dot, float grad, float fac)
 {
        float t2;
        
@@ -1194,60 +1205,64 @@
        return CLAMPIS(t2, 0.0f, 1.0f);
 }
 
+static float get_cosine_bound_in_given_space(float sm[3][3], float *pos, float 
*min, float *max, short trasl)
+{
+       float tmin[3], tmax[3];
+       transform_aabb(sm, min, max, tmin, tmax);
+       if (trasl) {
+               VECADD(tmin, pos, tmin);
+               VECADD(tmax, pos, tmax);
+       }
+       return compute_cosine_bound(tmin, tmax);
+}
+
 /* error bound: material term */
 /* 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)
+static float calc_material_eb(LightcutsCluster *clus, ShadeInput *shi, 
SampleCoordInfo *sci)
 {
-       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);
-       }
-       cb= compute_cosine_bound(tmin, tmax);
+       float maxb, eb_diff, eb_spec= 0.0f;
        
+       maxb= get_cosine_bound_in_given_space(sci->tsm, sci->tspos, clus->min, 
clus->max, clus->type != CLUSTER_SUN);
+       
+       /*
+        * TODO: if we add support for non shadow lamps, check should be:
+        * (sci->do_phongcorr && (lar->mode & LA_SHAD_RAY)) 
+        */
+       if (sci->do_phongcorr && maxb <= sci->phongcorr_thresh)
+               return 0.0f;
+       
        /* 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]);
+               eb_diff= bound_Toon_Diff(MAX2(maxb, 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);
+               eb_diff= bound_Minnaert_Diff(MAX2(maxb, 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]);
+               eb_diff= bound_Fresnel_Diff(MAX2(maxb, 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);
+                       float minb= -get_cosine_bound_in_given_space(sci->dtsm, 
sci->dtspos, clus->min, clus->max, clus->type != CLUSTER_SUN);
+                       eb_diff= bound_OrenNayar_Diff(MAX2(maxb, 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;
+               eb_diff= MAX2(maxb, 0.0) * shi->refl;
        }
        
+       if (sci->do_phongcorr) {
+               float phongcorr= (maxb - sci->phongcorr_thresh) / (maxb * (1.0f 
- sci->phongcorr_thresh));
+               eb_diff*= phongcorr;
+       }
+       
        if (shi->mat->spec_shader==MA_SPEC_PHONG) {
-               transform_aabb(msm, clus->min, clus->max, tmin, tmax);
-               if (clus->type != CLUSTER_SUN) {
-                       VECADD(tmin, mspos, tmin);
-                       VECADD(tmax, mspos, tmax);
-               }
                // t= shadfac[3]*shi->spec*visifac*specfac;
-               cb= compute_cosine_bound(tmin, tmax);
-               eb_spec= spec(MAX2(cb, 0.0), shi->har) * shi->spec;
+               maxb= get_cosine_bound_in_given_space(sci->msm, sci->mspos, 
clus->min, clus->max, clus->type != CLUSTER_SUN);
+               eb_spec= spec(MAX2(maxb, 0.0), shi->har) * shi->spec;
        }
+       
        return eb_diff + eb_spec;
 }
 
@@ -1341,10 +1356,7 @@
        int used= 0;
        int used_type[3]= {0, 0, 0};
        float i, i_noshad, t;
-       float tsm[3][3]; /* tangent space matrix */
-       float msm[3][3]; /* mirror direction space matrix */
-       float tspos[3];
-       float mspos[3];
+       SampleCoordInfo sci;
        float noropp[3];
        float mirdir[3];
        LightcutsCluster *array;
@@ -1370,13 +1382,22 @@
        /* XXX: shi->vn seems to point inside the mesh, investigate; works 
inverted like this */
        VECCOPY(noropp, shi->vn);
        VECNEG(noropp);
-       get_axis_matrix(tsm, noropp);
+       get_axis_matrix(sci.tsm, noropp);
        
        /* get sample coordinates in tangent space */
-       VECCOPY(tspos, shi->co);
-       Mat3MulVecfl(tsm, tspos);
-       VECNEG(tspos);
+       VECCOPY(sci.tspos, shi->co);
+       Mat3MulVecfl(sci.tsm, sci.tspos);
+       VECNEG(sci.tspos);
        
+       /* compute downwards tangent space matrix */
+       VECCOPY(sci.dtsm[0], sci.tsm[1]);
+       VECCOPY(sci.dtsm[1], sci.tsm[0]);
+       VECCOPY(sci.dtsm[2], sci.tsm[2]);
+       VECNEG(sci.dtsm[2]);
+       VECCOPY(sci.dtspos, shi->co);
+       Mat3MulVecfl(sci.dtsm, sci.dtspos);
+       VECNEG(sci.dtspos);
+       
        /* create mirror direction space */
        {
                float nor2[3];
@@ -1386,11 +1407,21 @@
                VecMulf(nor2, -2 * Inpf(mirdir, nor2));
                VecAddf(mirdir, nor2, mirdir);
                
-               get_axis_matrix(msm, mirdir);
-               VECCOPY(mspos, shi->co);
-               Mat3MulVecfl(msm, mspos);
-               VECNEG(mspos);
+               get_axis_matrix(sci.msm, mirdir);
+               VECCOPY(sci.mspos, shi->co);
+               Mat3MulVecfl(sci.msm, sci.mspos);
+               VECNEG(sci.mspos);
        }
+       
+       if(shi->mat->mode & MA_SHADOW) {
+               sci.phongcorr_thresh= 0.0f;
+               if((shi->mat->mode & MA_RAYBIAS) && (shi->vlr->flag & R_SMOOTH))
+                       sci.phongcorr_thresh= shi->obr->ob->smoothresh;
+               else if(shi->mat->sbias!=0.0f)
+                       sci.phongcorr_thresh= shi->mat->sbias;
+               if (sci.phongcorr_thresh!=0.0f)
+                       sci.do_phongcorr= 1;
+       }
 
        cut_nodes= lcd->cut_nodes + shi->thread * lcd->cut_nodes_size;
 
@@ -1407,7 +1438,7 @@
 
                                root->id= tree->root;
                                root->type= clus->type;
-                               root->error_bound= calc_geometric_eb(lcd, clus, 
shi->co) * calc_material_eb(clus, shi, tsm, tspos, msm, mspos);
+                               root->error_bound= calc_geometric_eb(lcd, clus, 
shi->co) * calc_material_eb(clus, shi, &sci);
 #ifdef LIGHTCUTS_DEBUG
                                dbg_convert[tree->root]= 0;
 #endif
@@ -1476,8 +1507,10 @@
                                        hinode->child1, hinode->child2);
                }
                if (cn_hinode->error_bound + FLT_EPSILON < 
cn_hinode->contr_factor) {
-                       printf("troublesome node! at %d, %d (it=%d) (id=%4d): 
eb %7.5f < cf %7.5f, (%10.6f * 10^6)\n",
-                                       shi->xs, shi->ys, it, cn_hinode->id, 
cn_hinode->error_bound, cn_hinode->contr_factor, 1000000.0f * 
fabs(cn_hinode->error_bound - cn_hinode->contr_factor));
+                       float error = 1000000.0f * fabs(cn_hinode->error_bound 
- cn_hinode->contr_factor);
+                       if (error > 1.0f) /* greater than 10^-6 ! */
+                               printf("troublesome node! at %d, %d (it=%d) 
(id=%4d): eb %7.5f < cf %7.5f, (%10.6f * 10^-6)\n",
+                                               shi->xs, shi->ys, it, 
cn_hinode->id, cn_hinode->error_bound, cn_hinode->contr_factor, error);
                        // break;
                }
 
@@ -1522,7 +1555,7 @@
                        /* for the represented light we can reuse most 
calculations */
                        cn_rep->id= rep->id;
                        cn_rep->type= rep->type;
-                       cn_rep->error_bound= calc_geometric_eb(lcd, rep, 
shi->co) * calc_material_eb(rep, shi, tsm, tspos, msm, mspos);
+                       cn_rep->error_bound= calc_geometric_eb(lcd, rep, 
shi->co) * calc_material_eb(rep, shi, &sci);
 
                        if (cn_rep->error_bound > FLT_EPSILON) {
                                cn_rep->contr_factor= cn_hinode->contr_factor;
@@ -1554,7 +1587,7 @@
                        /* for the "unrepresented" light we have to compute 
stuff from scratch */
                        cn_unrep->id= unrep->id;
                        cn_unrep->type= unrep->type;
-                       cn_unrep->error_bound= calc_geometric_eb(lcd, unrep, 
shi->co) * calc_material_eb(unrep, shi, tsm, tspos, msm, mspos);
+                       cn_unrep->error_bound= calc_geometric_eb(lcd, unrep, 
shi->co) * calc_material_eb(unrep, shi, &sci);
 
                        if (cn_unrep->error_bound > FLT_EPSILON) {
                                single_light_contrib(unrep->lar, shi, &i, 
&i_noshad, &t);

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-29 11:37:11 UTC (rev 15863)
+++ 
branches/soc-2008-unclezeiv/source/blender/render/intern/source/shadeoutput.c   
    2008-07-29 11:53:43 UTC (rev 15864)
@@ -2014,6 +2014,9 @@
                        }
                }
 #endif
+
+               /* specularity */
+               shadfac[3]*= phongcorr; /* note, shadfac not allowed to be 
stored nonlocal */
                

@@ 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