[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [15864] branches/soc-2008-unclezeiv/source /blender/render/intern/source: Added support for "Bias" a.k.a.
Davide Vercelli
davide.vercelli at gmail.com
Tue Jul 29 13:53:44 CEST 2008
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. @@
More information about the Bf-blender-cvs
mailing list