[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [15349] branches/soc-2008-unclezeiv/source /blender/render/intern/source/lightcuts.c: added tree building and geometric error bound for oriented lights; the only thing missing now is the correct computation of the similarity metric during tree building
Davide Vercelli
davide.vercelli at gmail.com
Wed Jun 25 03:05:00 CEST 2008
Revision: 15349
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=15349
Author: unclezeiv
Date: 2008-06-25 03:04:21 +0200 (Wed, 25 Jun 2008)
Log Message:
-----------
added tree building and geometric error bound for oriented lights; the only thing missing now is the correct computation of the similarity metric during tree building
Modified Paths:
--------------
branches/soc-2008-unclezeiv/source/blender/render/intern/source/lightcuts.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-06-24 22:19:00 UTC (rev 15348)
+++ branches/soc-2008-unclezeiv/source/blender/render/intern/source/lightcuts.c 2008-06-25 01:04:21 UTC (rev 15349)
@@ -121,6 +121,7 @@
LightcutsTree trees[_TREES_SIZE];
float max_local_dist; /* maximum distance for local lights */
+ float max_spot_dist; /* maximum distance for oriented lights */
int light_counter;
@@ -174,7 +175,7 @@
return angle_new;
}
-static float lightcuts_compute_metric(float c, LightcutsCluster * one, LightcutsCluster * two)
+static float lightcuts_compute_metric(float csq, LightcutsCluster * one, LightcutsCluster * two)
{
float diff[3], min[3], max[3];
@@ -189,7 +190,7 @@
if (one->type == CLUSTER_SPOT) {
float cos_a= cosf(get_bounding_cone(one, two, NULL));
float term = (1 - cos_a) * (1 - cos_a);
- return (one->luminance + two->luminance) * (VEC_LEN_SQ(diff) + c * term);
+ return (one->luminance + two->luminance) * (VEC_LEN_SQ(diff) + csq * term);
}
return (one->luminance + two->luminance) * VEC_LEN_SQ(diff);
@@ -222,6 +223,10 @@
VECCOPY(dest->max, one->max);
DO_MINMAX(two->min, dest->min, dest->max);
DO_MINMAX(two->max, dest->min, dest->max);
+
+ /* if LA_SPOT, compute new bounding cone */
+ if (one->type == CLUSTER_SPOT)
+ dest->cone_angle= get_bounding_cone(one, two, dest->cone_dir);
/* the representative light is chosen randomly among children */
if (BLI_frand() * (one->luminance + two->luminance) < one->luminance) {
@@ -313,6 +318,12 @@
clus->min[2]= -lar->vec[2];
VECCOPY(clus->max, clus->min);
break;
+ case LA_SPOT:
+ VECCOPY(clus->min, lar->co);
+ VECCOPY(clus->max, lar->co);
+ VECCOPY(clus->cone_dir, lar->vec);
+ clus->cone_angle= 0.0f;
+ break;
}
clus->lar = lar;
@@ -366,7 +377,7 @@
LightcutsCluster *array= tree->array;
Heap * heap = BLI_heap_new();
- /* TODO: taylor size: done. current TODO is "check if it works" */
+ /* TODO: tailor size: done. current TODO is "check if it works" */
LightcutsClusterPair *pair_array= MEM_callocN(sizeof(LightcutsClusterPair) * tree->counter * 2, "pair_array");
for (i = 0; i < tree->counter; i++)
@@ -489,7 +500,8 @@
re->lcdata = lcd = MEM_callocN(sizeof(LightcutsData), "LightcutsData");
pointlights= &lcd->pointlights;
- lcd->max_local_dist = MAXFLOAT;
+ lcd->max_local_dist= MAXFLOAT;
+ lcd->max_spot_dist= MAXFLOAT;
lcd->light_counter= 0;
for(go=lights->first; go; go= go->next) {
@@ -516,6 +528,13 @@
case LA_SUN:
lcd->trees[TREE_SUN].counter++;
break;
+ case LA_SPOT:
+ /* TODO: check if it's a valid spot */
+ if (lar->dist < lcd->max_spot_dist)
+ lcd->max_spot_dist= lar->dist;
+
+ lcd->trees[TREE_SPOT].counter++;
+ break;
default:
continue;
}
@@ -575,11 +594,13 @@
#endif
}
- /* XXX: whis should be equal to re->r.lightcuts_max_lights when light generation is in place */
+ /* XXX: this should be equal to re->r.lightcuts_max_lights when light generation is in place */
lcd->max_lights= lcd->light_counter;
lcd->error_rate= re->r.lightcuts_max_error;
lcd->max_cut= MIN2(re->r.lightcuts_max_cut, lcd->light_counter);
lcd->start_time= PIL_check_seconds_timer();
+ /* XXX: TODO: get proper scene diagonal */
+ lcd->bb_diag_sq= 11.747*11.747;
re->i.infostr= "Building light trees";
re->stats_draw(&re->i);
@@ -589,7 +610,7 @@
if (lcd->trees[i].counter > 0) {
lightcuts_fill_array(pointlights, &lcd->trees[i], i);
printf("Lightcuts: building %s tree - ", tree_names[i]);
- lightcuts_build_tree(&lcd->trees[i], 0.0f);
+ lightcuts_build_tree(&lcd->trees[i], lcd->bb_diag_sq);
/* TODO: put square of scene bounding box diagonale instead of 0.0f */
}
}
@@ -647,15 +668,20 @@
}
/* fill in tangent space matrix tsm given normal and position; please note, it's also a translation matrix */
-static void get_tangent_space_matrix(float tsm[4][4], float *nor, float *pos)
+/* TODO: scrap the translation part, use a 3x3 and transform the vector when needed */
+static void get_tangent_space_matrix(float tsm[4][4], float *nor, float *pos, int negate)
{
float normat[4][4];
/* warning: we fill it transposed as it's easier */
/* XXX: shi->vn seems to point inside the mesh, investigate; works inverted like this */
- normat[2][0] = -nor[0];
- normat[2][1] = -nor[1];
- normat[2][2] = -nor[2];
+ if (negate) {
+ normat[2][0] = -nor[0];
+ normat[2][1] = -nor[1];
+ normat[2][2] = -nor[2];
+ }
+ else
+ VECCOPY(normat[2], nor);
VecOrthoBasisf(normat[2], normat[0], normat[1]);
@@ -682,26 +708,56 @@
/* TODO: missing LA_SPOT eb */
static float calc_geometric_eb(LightcutsData *lcd, LightcutsCluster *clus, float *pos)
{
- if (clus->type==CLUSTER_LOCAL) {
- /* find the nearest point in the bounding box */
- float *min= clus->min;
- float *max= clus->max;
- float nearest[3];
- float len_sq;
- nearest[0]= pos[0] < min[0] ? min[0] : (pos[0] > max[0] ? max[0] : pos[0]);
- nearest[1]= pos[1] < min[1] ? min[1] : (pos[1] > max[1] ? max[1] : pos[1]);
- nearest[2]= pos[2] < min[2] ? min[2] : (pos[2] > max[2] ? max[2] : pos[2]);
+ /* find the nearest point in the bounding box */
+ float *min= clus->min;
+ float *max= clus->max;
+ float nearest[3];
+ float len_sq;
+
+ if (clus->type == CLUSTER_SUN)
+ return 1.0f;
+
+ nearest[0]= pos[0] < min[0] ? min[0] : (pos[0] > max[0] ? max[0] : pos[0]);
+ nearest[1]= pos[1] < min[1] ? min[1] : (pos[1] > max[1] ? max[1] : pos[1]);
+ nearest[2]= pos[2] < min[2] ? min[2] : (pos[2] > max[2] ? max[2] : pos[2]);
- VECSUB(nearest, nearest, pos);
- len_sq= VEC_LEN_SQ(nearest);
+ VECSUB(nearest, nearest, pos);
+ len_sq= VEC_LEN_SQ(nearest);
+ /*
+ * TODO: could take the various supported attenuation functions into account,
+ * using the worst case among the one found while creating the tree
+ */
+ if (clus->type == CLUSTER_LOCAL)
+ return lcd->max_local_dist / (lcd->max_local_dist + len_sq);
+ else {
+ float newmin[3], transmin[3];
+ float newmax[3], transmax[3];
+ float cos_t, angle;
+ float tsm[4][4];
+
+ get_tangent_space_matrix(tsm, clus->cone_dir, pos, 0);
+
+ VECSUB(newmax, pos, clus->min);
+ VECSUB(newmin, pos, clus->max);
+
+ transform_aabb(tsm, newmin, newmax, transmin, transmax, 0);
+
+ cos_t= compute_cosine_bound(transmin, transmax);
+ angle= acosf(cos_t);
+
+ if (angle < clus->cone_angle)
+ return 1.0;
+ return lcd->max_spot_dist / (lcd->max_spot_dist + len_sq) * MAX2(0.0f, cosf(angle - clus->cone_angle));
+
/*
- * TODO: could take the various supported attenuation functions into account,
- * using the worst case among the one found while creating the tree
+ * cos(a+b) = cos_a*cos_b - sin_a*sin_b
+ * cos(angle-ca) = cos_t * cos_ca - sin_T * sin_ca
+ * - cos_ca and sin_ca precomputable in initial step
+ * - cos_t we have it already
+ * - sin_t it's sqrt(1 - cos_t * cos_t)... is it faster?
*/
- return lcd->max_local_dist / (lcd->max_local_dist + len_sq);
}
- return 1.0f;
}
/*
@@ -736,7 +792,7 @@
float dbg_totlum = 0.0f;
#endif
- get_tangent_space_matrix(tsm, shi->vn, shi->co);
+ get_tangent_space_matrix(tsm, shi->vn, shi->co, 1);
cut_nodes= lcd->cut_nodes + shi->thread * lcd->cut_nodes_size;
@@ -951,7 +1007,9 @@
"Average cut size: %.2f\n"
"Shadow rays: %.2f (%.2f%%)\n"
"---------------\n",
- lcd->stat_samples, lcd->light_counter, lcd->trees[TREE_LOCAL].counter, lcd->trees[TREE_SUN].counter, 0, lcd->max_cut,
+ lcd->stat_samples, lcd->light_counter,
+ lcd->trees[TREE_LOCAL].counter, lcd->trees[TREE_SUN].counter, lcd->trees[TREE_SPOT].counter,
+ lcd->max_cut,
(float)lcd->stat_cut_size / (float)lcd->stat_samples,
(float)lcd->stat_rays_shot / (float)lcd->stat_samples,
100.0f * lcd->stat_rays_shot / (float)(lcd->stat_samples * lcd->light_counter));
More information about the Bf-blender-cvs
mailing list