[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [15423] branches/soc-2008-unclezeiv/source /blender/render/intern: Phong specularity is now supported, but more extensive testing is required.
Davide Vercelli
davide.vercelli at gmail.com
Fri Jul 4 04:04:17 CEST 2008
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. @@
More information about the Bf-blender-cvs
mailing list