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

Log Message:
-----------
Phong specularity is now supported, but more extensive testing is required.
Also: light contribution function is now called directly, the callback 
mechanism was not actually needed.

Modified Paths:
--------------
    branches/soc-2008-unclezeiv/source/blender/render/intern/include/lightcuts.h
    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/include/lightcuts.h
===================================================================
--- 
branches/soc-2008-unclezeiv/source/blender/render/intern/include/lightcuts.h    
    2008-07-04 01:03:50 UTC (rev 15422)
+++ 
branches/soc-2008-unclezeiv/source/blender/render/intern/include/lightcuts.h    
    2008-07-04 02:03:03 UTC (rev 15423)
@@ -37,8 +37,6 @@
 
 void lightcuts_free(struct LightcutsData **p);
 
-typedef void (*LightContribFunc)(LampRen *lar, ShadeInput *shi, float *i, 
float *i_noshad);
+void lightcuts_do_lights(struct LightcutsData *lcd, ShadeInput *shi, 
ShadeResult *shr);
 
-void lightcuts_do_lights(struct LightcutsData *lcd, LightContribFunc 
get_contrib, ShadeInput *shi, ShadeResult *shr);
-
 #endif /*LIGHTCUTS_H_*/

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-04 01:03:50 UTC (rev 15422)
+++ branches/soc-2008-unclezeiv/source/blender/render/intern/source/lightcuts.c 
2008-07-04 02:03:03 UTC (rev 15423)
@@ -36,6 +36,7 @@
 #include "BLI_rand.h"
 #include "DNA_group_types.h"
 #include "DNA_lamp_types.h"
+#include "DNA_material_types.h"
 #include "DNA_listBase.h"
 #include "MEM_guardedalloc.h"
 #include "PIL_time.h"
@@ -104,8 +105,10 @@
        float error_bound;
        float contr_factor;
        float contr_factor_noshad;
+       float contr_factor_spec;
        float f_clus;
        float f_clus_noshad;
+       float f_clus_spec;
 } CutNode;
 
 typedef struct LightcutsTree {
@@ -150,6 +153,7 @@
 #define VECNEG(v) {*(v)=-*(v); *(v+1)=-*(v+1); *(v+2)=-*(v+2);}
 /* TODO: tentative calculation, will look better into it */
 #define LC_LUMINOSITY(c) (0.299*(c)[0] + 0.587*(c)[1] + 0.114*(c)[2])
+#define LC_LUMINOSITY2(c1,c2) (LC_LUMINOSITY(c1)+LC_LUMINOSITY(c2))
 /* #define LC_LUMINOSITY(c) (0.316*c[0] + 0.460*c[1] + 0.224*c[2]) */
 #define IS_LEAF(node) (!(node)->child1 && !(node)->child2)
 
@@ -895,29 +899,42 @@
        return max[2] / sqrt(xsq + ysq + max[2]*max[2]);
 }
 
-/* fill in tangent space matrix tsm given normal */
-static void get_tangent_space_matrix(float tsm[3][3], float *nor)
+/* fill in a new matrix describing a space where axis is z+ */
+static void get_axis_matrix(float amat[3][3], float *axis)
 {
-       float normat[3][3];
+       float mat[3][3];
        
-       VECCOPY(normat[2], nor);
-       VecOrthoBasisf(normat[2], normat[0], normat[1]);
+       VECCOPY(mat[2], axis);
+       VecOrthoBasisf(mat[2], mat[0], mat[1]);
 
-       /* now we have a proper tangent-to-world matrix: let's invert it */
-       Mat3Inv(tsm, normat);
+       /* now we have a proper local-to-world matrix: let's invert it */
+       Mat3Inv(amat, mat);
 }
 
+float spec(float inp, int hard);
+
 /* error bound: material term */
-/* TODO: currently supporting only diffuse */
-static float calc_material_eb(float tsm[3][3], LightcutsCluster *clus, float 
*pos)
+/* TODO: currently supporting only lambertian diffuse and 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];
+       float tmin[3], tmax[3], eb_diff, eb_spec=0.0f;
        transform_aabb(tsm, clus->min, clus->max, tmin, tmax);
        if (clus->type != CLUSTER_SUN) {
-               VECADD(tmin, pos, tmin);
-               VECADD(tmax, pos, tmax);
+               VECADD(tmin, tspos, tmin);
+               VECADD(tmax, tspos, tmax);
        }
-       return MAX2(compute_cosine_bound(tmin, tmax), 0.0);
+       eb_diff= MAX2(compute_cosine_bound(tmin, tmax), 0.0) * shi->refl;
+       /* TODO: optimize */
+       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;
+               eb_spec= spec(MAX2(compute_cosine_bound(tmin, tmax), 0.0), 
shi->har) * shi->spec;
+       }
+       return eb_diff + eb_spec;
 }
 
 /* error bound: geometric term */
@@ -951,7 +968,7 @@
                float cos_t, angle;
                float tsm[3][3];
                
-               get_tangent_space_matrix(tsm, clus->cone_dir);
+               get_axis_matrix(tsm, clus->cone_dir);
                
                VECSUB(newmax, pos, clus->min);
                VECSUB(newmin, pos, clus->max);
@@ -975,21 +992,21 @@
        }
 }
 
-/*
- * what about intensity? which one should we use?
- * RESOLUTION: the one of the lamp, then adjusted
- */
+void single_light_contrib(LampRen *lar, ShadeInput *shi, float *pi, float 
*pi_noshad, float *pt);
 
-void lightcuts_do_lights(LightcutsData *lcd, LightContribFunc get_contrib, 
ShadeInput *shi, ShadeResult *shr)
+void lightcuts_do_lights(LightcutsData *lcd, ShadeInput *shi, ShadeResult *shr)
 {
-       /* TODO: show that this size is always sufficient */
        CutNode *cut_nodes;
        int free_node= 1;
        int it= 0;
        int used= 0;
-       float i, i_noshad;
+       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];
+       float noropp[3];
+       float mirdir[3];
        LightcutsCluster *array;
 
        /* 
@@ -1000,8 +1017,9 @@
        Heap *cut= BLI_heap_new();
 
        /* this is the total radiance estimate, continuously updated */
-       float totest[3]= {0.0f, 0.0f, 0.0f};
+       float totest_shad[3]= {0.0f, 0.0f, 0.0f};
        float totest_noshad[3]= {0.0f, 0.0f, 0.0f};
+       float totest_spec[3]= {0.0f, 0.0f, 0.0f};
 
 #ifdef LIGHTCUTS_DEBUG
        int dbg_convert[lcd->max_lights * 2]; /* from cluster id to index in 
cut_nodes */
@@ -1010,14 +1028,29 @@
 #endif
        
        /* XXX: shi->vn seems to point inside the mesh, investigate; works 
inverted like this */
-       VECCOPY(tspos, shi->vn);
-       VECNEG(tspos);
-       get_tangent_space_matrix(tsm, tspos);
+       VECCOPY(noropp, shi->vn);
+       VECNEG(noropp);
+       get_axis_matrix(tsm, noropp);
        
        /* get sample coordinates in tangent space */
        VECCOPY(tspos, shi->co);
        Mat3MulVecfl(tsm, tspos);
        VECNEG(tspos);
+       
+       /* create mirror direction space */
+       {
+               float nor2[3];
+               VECCOPY(nor2, noropp);
+               VECCOPY(mirdir, shi->co);
+               Normalize(mirdir);
+               VecMulf(nor2, -2 * Inpf(mirdir, nor2));
+               VecAddf(mirdir, nor2, mirdir);
+               
+               get_axis_matrix(msm, mirdir);
+               VECCOPY(mspos, shi->co);
+               Mat3MulVecfl(msm, mspos);
+               VECNEG(mspos);
+       }
 
        cut_nodes= lcd->cut_nodes + shi->thread * lcd->cut_nodes_size;
 
@@ -1035,16 +1068,19 @@
 
                                root->id= tree->root;
                                root->type= clus->type;
-                               root->error_bound= calc_geometric_eb(lcd, clus, 
shi->co) * calc_material_eb(tsm, clus, tspos) * shi->refl;
+                               root->error_bound= calc_geometric_eb(lcd, clus, 
shi->co) * calc_material_eb(clus, shi, tsm, tspos, msm, mspos);
 #ifdef LIGHTCUTS_DEBUG
                                dbg_convert[tree->root]= 0;
 #endif
                                if (root->error_bound > FLT_EPSILON) {
-                                       get_contrib(clus->lar, shi, &i, 
&i_noshad);
+                                       single_light_contrib(clus->lar, shi, 
&i, &i_noshad, &t);
                                        lcd->stat_rays_shot++;
                                        root->contr_factor= MAX2(i, 0.0f);
+                                       root->contr_factor_spec= MAX2(t, 0.0f);
                                        root->f_clus= root->contr_factor * 
clus->intensity;
-                                       VECADDFAC(totest, totest, clus->col, 
root->f_clus);
+                                       root->f_clus_spec= 
root->contr_factor_spec * clus->intensity;
+                                       VECADDFAC(totest_shad, totest_shad, 
clus->col, root->f_clus);
+                                       VECADDFAC(totest_spec, totest_spec, 
clus->col, root->f_clus_spec);
 
                                        if(shi->passflag & 
(SCE_PASS_DIFFUSE|SCE_PASS_SHADOW)) {
                                                root->contr_factor_noshad= 
MAX2(i_noshad, 0.0f);
@@ -1101,7 +1137,7 @@
                }
 #endif
 
-               if (LC_LUMINOSITY(totest) * lcd->error_rate > 
cn_hinode->error_bound * hinode->luminance) {
+               if (LC_LUMINOSITY2(totest_shad, totest_spec) * lcd->error_rate 
> cn_hinode->error_bound * hinode->luminance) {
                        break;
                } else {
                        LightcutsCluster *rep= &array[hinode->child1];
@@ -1124,7 +1160,8 @@
                         * but please note that it's the same quantity
                         * we are not calculating it in different ways
                         */
-                       VECADDFAC(totest, totest, hinode->col, 
-cn_hinode->f_clus);
+                       VECADDFAC(totest_shad, totest_shad, hinode->col, 
-cn_hinode->f_clus);
+                       VECADDFAC(totest_spec, totest_spec, hinode->col, 
-cn_hinode->f_clus_spec);
 #ifdef LIGHTCUTS_DEBUG
                        dbg_totlum-= cn_hinode->contr_factor * 
hinode->luminance;
 #endif
@@ -1132,12 +1169,15 @@
                        /* 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(tsm, rep, tspos) * shi->refl;
+                       cn_rep->error_bound= calc_geometric_eb(lcd, rep, 
shi->co) * calc_material_eb(rep, shi, tsm, tspos, msm, mspos);
 
                        if (cn_rep->error_bound > FLT_EPSILON) {
                                cn_rep->contr_factor= cn_hinode->contr_factor;
+                               cn_rep->contr_factor_spec= 
cn_hinode->contr_factor_spec;
                                cn_rep->f_clus= cn_hinode->contr_factor * 
rep->intensity;
-                               VECADDFAC(totest, totest, rep->col, 
cn_rep->f_clus);
+                               cn_rep->f_clus_spec= 
cn_hinode->contr_factor_spec * rep->intensity;
+                               VECADDFAC(totest_shad, totest_shad, rep->col, 
cn_rep->f_clus);
+                               VECADDFAC(totest_spec, totest_spec, rep->col, 
cn_rep->f_clus_spec);
 #ifdef LIGHTCUTS_DEBUG
                                dbg_totlum+= rep->luminance * 
cn_rep->contr_factor;
 #endif
@@ -1153,14 +1193,17 @@
                        /* 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(tsm, unrep, tspos) * shi->refl;
+                       cn_unrep->error_bound= calc_geometric_eb(lcd, unrep, 
shi->co) * calc_material_eb(unrep, shi, tsm, tspos, msm, mspos);
 
                        if (cn_unrep->error_bound > FLT_EPSILON) {
-                               get_contrib(unrep->lar, shi, &i, &i_noshad);
+                               single_light_contrib(unrep->lar, shi, &i, 
&i_noshad, &t);
                                lcd->stat_rays_shot++;
                                cn_unrep->contr_factor= MAX2(i, 0.0f);
+                               cn_unrep->contr_factor_spec= MAX2(t, 0.0f);
                                cn_unrep->f_clus= cn_unrep->contr_factor * 
unrep->intensity;
-                               VECADDFAC(totest, totest, unrep->col, 
cn_unrep->f_clus);
+                               cn_unrep->f_clus_spec= 
cn_unrep->contr_factor_spec * unrep->intensity;
+                               VECADDFAC(totest_shad, totest_shad, unrep->col, 
cn_unrep->f_clus);
+                               VECADDFAC(totest_spec, totest_spec, unrep->col, 
cn_unrep->f_clus_spec);
 #ifdef LIGHTCUTS_DEBUG
                                dbg_totlum+= unrep->luminance * 
cn_unrep->contr_factor;
 #endif
@@ -1192,9 +1235,13 @@
         * an updated TOTEST value (even thought numerically questionable?)
         */
 
-       shr->shad[0]+= totest[0]*shi->r;
-       shr->shad[1]+= totest[1]*shi->g;
-       shr->shad[2]+= totest[2]*shi->b;
+       shr->shad[0]+= totest_shad[0]*shi->r;
+       shr->shad[1]+= totest_shad[1]*shi->g;

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