Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Ebb <matt@mke3.net>2010-01-04 02:45:13 +0300
committerMatt Ebb <matt@mke3.net>2010-01-04 02:45:13 +0300
commitf02dde5de7f1d54f489a124cea128bc993b708d7 (patch)
tree5da5e306b841ca2463c0de63d34a942f6fb5cc2a /source/blender/render
parent1f33d574c2d18f0037f5e168dbd1a54d23dad6d7 (diff)
Patch from Raul Fernandez Hernandez - volume render multiple scattering fixes
Also: Changed 'Spread' value to be proportional to the light cache voxel grid (i.e. 0.5 spreads half the width of the grid), so that it's independent of light cache resolution. This means that results should be similar as you increase/ decrease resolution.
Diffstat (limited to 'source/blender/render')
-rw-r--r--source/blender/render/intern/source/volume_precache.c147
-rw-r--r--source/blender/render/intern/source/volumetric.c2
2 files changed, 85 insertions, 64 deletions
diff --git a/source/blender/render/intern/source/volume_precache.c b/source/blender/render/intern/source/volume_precache.c
index e9162b7367f..80a6dd9d6a0 100644
--- a/source/blender/render/intern/source/volume_precache.c
+++ b/source/blender/render/intern/source/volume_precache.c
@@ -21,7 +21,7 @@
*
* The Original Code is: all of this file.
*
- * Contributor(s): Matt Ebb.
+ * Contributor(s): Matt Ebb, Ra˙l Fern·ndez Hern·ndez (Farsthary).
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -134,9 +134,10 @@ static float get_avg_surrounds(float *cache, int *res, int xx, int yy, int zz)
for (x=-1; x <= 1; x++) {
x_ = xx+x;
if (x_ >= 0 && x_ <= res[0]-1) {
-
- if (cache[ V_I(x_, y_, z_, res) ] > 0.0f) {
- tot += cache[ V_I(x_, y_, z_, res) ];
+ const int i= V_I(x_, y_, z_, res);
+
+ if (cache[i] > 0.0f) {
+ tot += cache[i];
added++;
}
@@ -164,12 +165,14 @@ static void lightcache_filter(VolumePrecache *vp)
for (y=0; y < vp->res[1]; y++) {
for (x=0; x < vp->res[0]; x++) {
/* trigger for outside mesh */
- if (vp->data_r[ V_I(x, y, z, vp->res) ] < -0.f)
- vp->data_r[ V_I(x, y, z, vp->res) ] = get_avg_surrounds(vp->data_r, vp->res, x, y, z);
- if (vp->data_g[ V_I(x, y, z, vp->res) ] < -0.f)
- vp->data_g[ V_I(x, y, z, vp->res) ] = get_avg_surrounds(vp->data_g, vp->res, x, y, z);
- if (vp->data_b[ V_I(x, y, z, vp->res) ] < -0.f)
- vp->data_b[ V_I(x, y, z, vp->res) ] = get_avg_surrounds(vp->data_b, vp->res, x, y, z);
+ const int i= V_I(x, y, z, vp->res);
+
+ if (vp->data_r[i] < -0.f)
+ vp->data_r[i] = get_avg_surrounds(vp->data_r, vp->res, x, y, z);
+ if (vp->data_g[i] < -0.f)
+ vp->data_g[i] = get_avg_surrounds(vp->data_g, vp->res, x, y, z);
+ if (vp->data_b[i] < -0.f)
+ vp->data_b[i] = get_avg_surrounds(vp->data_b, vp->res, x, y, z);
}
}
}
@@ -194,12 +197,13 @@ static void lightcache_filter2(VolumePrecache *vp)
for (y=0; y < vp->res[1]; y++) {
for (x=0; x < vp->res[0]; x++) {
/* trigger for outside mesh */
- if (vp->data_r[ V_I(x, y, z, vp->res) ] < -0.f)
- new_r[ V_I(x, y, z, vp->res) ] = get_avg_surrounds(vp->data_r, vp->res, x, y, z);
- if (vp->data_g[ V_I(x, y, z, vp->res) ] < -0.f)
- new_g[ V_I(x, y, z, vp->res) ] = get_avg_surrounds(vp->data_g, vp->res, x, y, z);
- if (vp->data_b[ V_I(x, y, z, vp->res) ] < -0.f)
- new_b[ V_I(x, y, z, vp->res) ] = get_avg_surrounds(vp->data_b, vp->res, x, y, z);
+ const int i= V_I(x, y, z, vp->res);
+ if (vp->data_r[i] < -0.f)
+ new_r[i] = get_avg_surrounds(vp->data_r, vp->res, x, y, z);
+ if (vp->data_g[i] < -0.f)
+ new_g[i] = get_avg_surrounds(vp->data_g, vp->res, x, y, z);
+ if (vp->data_b[i] < -0.f)
+ new_b[i] = get_avg_surrounds(vp->data_b, vp->res, x, y, z);
}
}
}
@@ -216,9 +220,21 @@ static void lightcache_filter2(VolumePrecache *vp)
static inline int ms_I(int x, int y, int z, int *n) //has a pad of 1 voxel surrounding the core for boundary simulation
{
- return z*(n[1]+2)*(n[0]+2) + y*(n[0]+2) + x;
+ /* different ordering to light cache */
+ return x*(n[1]+2)*(n[2]+2) + y*(n[2]+2) + z;
+}
+
+static inline int v_I_pad(int x, int y, int z, int *n) //has a pad of 1 voxel surrounding the core for boundary simulation
+{
+ /* same ordering to light cache, with padding */
+ return z*(n[1]+2)*(n[0]+2) + y*(n[0]+2) + x;
}
+static inline int lc_to_ms_I(int x, int y, int z, int *n)
+{
+ /* converting light cache index to multiple scattering index */
+ return (x-1)*(n[1]*n[2]) + (y-1)*(n[2]) + z-1;
+}
/* *** multiple scattering approximation *** */
@@ -232,9 +248,11 @@ static float total_ss_energy(VolumePrecache *vp)
for (z=0; z < res[2]; z++) {
for (y=0; y < res[1]; y++) {
for (x=0; x < res[0]; x++) {
- if (vp->data_r[ V_I(x, y, z, res) ] > 0.f) energy += vp->data_r[ V_I(x, y, z, res) ];
- if (vp->data_g[ V_I(x, y, z, res) ] > 0.f) energy += vp->data_g[ V_I(x, y, z, res) ];
- if (vp->data_b[ V_I(x, y, z, res) ] > 0.f) energy += vp->data_b[ V_I(x, y, z, res) ];
+ const int i=V_I(x, y, z, res);
+
+ if (vp->data_r[i] > 0.f) energy += vp->data_r[i];
+ if (vp->data_g[i] > 0.f) energy += vp->data_g[i];
+ if (vp->data_b[i] > 0.f) energy += vp->data_b[i];
}
}
}
@@ -244,14 +262,14 @@ static float total_ss_energy(VolumePrecache *vp)
static float total_ms_energy(float *sr, float *sg, float *sb, int *res)
{
- int x, y, z, i;
+ int x, y, z;
float energy=0.f;
for (z=1;z<=res[2];z++) {
for (y=1;y<=res[1];y++) {
for (x=1;x<=res[0];x++) {
-
- i = ms_I(x,y,z,res);
+ const int i = ms_I(x,y,z,res);
+
if (sr[i] > 0.f) energy += sr[i];
if (sg[i] > 0.f) energy += sg[i];
if (sb[i] > 0.f) energy += sb[i];
@@ -262,7 +280,7 @@ static float total_ms_energy(float *sr, float *sg, float *sb, int *res)
return energy;
}
-static void ms_diffuse(int b, float* x0, float* x, float diff, int *n)
+static void ms_diffuse(float *x0, float *x, float diff, int *n) //n is the unpadded resolution
{
int i, j, k, l;
const float dt = VOL_MS_TIMESTEP;
@@ -276,10 +294,9 @@ static void ms_diffuse(int b, float* x0, float* x, float diff, int *n)
{
for (i=1; i<=n[0]; i++)
{
- x[ms_I(i,j,k,n)] = (x0[ms_I(i,j,k,n)] + a*(
- x[ms_I(i-1,j,k,n)]+x[ms_I(i+1,j,k,n)]+
- x[ms_I(i,j-1,k,n)]+x[ms_I(i,j+1,k,n)]+
- x[ms_I(i,j,k-1,n)]+x[ms_I(i,j,k+1,n)]))/(1+6*a);
+ x[v_I_pad(i,j,k,n)] = (x0[v_I_pad(i,j,k,n)]) + a*( x0[v_I_pad(i-1,j,k,n)]+ x0[v_I_pad(i+1,j,k,n)]+ x0[v_I_pad(i,j-1,k,n)]+
+ x0[v_I_pad(i,j+1,k,n)]+ x0[v_I_pad(i,j,k-1,n)]+x0[v_I_pad(i,j,k+1,n)]
+ ) / (1+6*a);
}
}
}
@@ -289,7 +306,7 @@ static void ms_diffuse(int b, float* x0, float* x, float diff, int *n)
void multiple_scattering_diffusion(Render *re, VolumePrecache *vp, Material *ma)
{
const float diff = ma->vol.ms_diff * 0.001f; /* compensate for scaling for a nicer UI range */
- const float simframes = ma->vol.ms_steps;
+ const int simframes = (int)(ma->vol.ms_spread * (float)MAX3(vp->res[0], vp->res[1], vp->res[2]));
const int shade_type = ma->vol.shade_type;
float fac = ma->vol.ms_intensity;
@@ -299,7 +316,6 @@ void multiple_scattering_diffusion(Render *re, VolumePrecache *vp, Material *ma)
double time, lasttime= PIL_check_seconds_timer();
float total;
float c=1.0f;
- int i;
float origf; /* factor for blending in original light cache */
float energy_ss, energy_ms;
@@ -324,22 +340,22 @@ void multiple_scattering_diffusion(Render *re, VolumePrecache *vp, Material *ma)
{
for (x=1; x<=n[0]; x++)
{
- i = V_I((x-1), (y-1), (z-1), n);
+ const int i = lc_to_ms_I(x, y ,z, n); //lc index
+ const int j = ms_I(x, y, z, n); //ms index
+
time= PIL_check_seconds_timer();
- c++;
-
- if (vp->data_r[i] > 0.f)
- sr[ms_I(x,y,z,n)] += vp->data_r[i];
- if (vp->data_g[i] > 0.f)
- sg[ms_I(x,y,z,n)] += vp->data_g[i];
- if (vp->data_b[i] > 0.f)
- sb[ms_I(x,y,z,n)] += vp->data_b[i];
+ c++;
+ if (vp->data_r[i] > 0.0f)
+ sr[j] += vp->data_r[i];
+ if (vp->data_g[i] > 0.0f)
+ sg[j] += vp->data_g[i];
+ if (vp->data_b[i] > 0.0f)
+ sb[j] += vp->data_b[i];
/* Displays progress every second */
if(time-lasttime>1.0f) {
char str[64];
- sprintf(str, "Simulating multiple scattering: %d%%", (int)
- (100.0f * (c / total)));
+ sprintf(str, "Simulating multiple scattering: %d%%", (int)(100.0f * (c / total)));
re->i.infostr= str;
re->stats_draw(re->sdh, &re->i);
re->i.infostr= NULL;
@@ -348,14 +364,14 @@ void multiple_scattering_diffusion(Render *re, VolumePrecache *vp, Material *ma)
}
}
}
- SWAP(float *, sr, sr0);
- SWAP(float *, sg, sg0);
- SWAP(float *, sb, sb0);
-
+ SWAP(float *,sr,sr0);
+ SWAP(float *,sg,sg0);
+ SWAP(float *,sb,sb0);
+
/* main diffusion simulation */
- ms_diffuse(0, sr0, sr, diff, n);
- ms_diffuse(0, sg0, sg, diff, n);
- ms_diffuse(0, sb0, sb, diff, n);
+ ms_diffuse(sr0, sr, diff, n);
+ ms_diffuse(sg0, sg, diff, n);
+ ms_diffuse(sb0, sb, diff, n);
if (re->test_break(re->tbh)) break;
}
@@ -379,10 +395,12 @@ void multiple_scattering_diffusion(Render *re, VolumePrecache *vp, Material *ma)
{
for (x=1;x<=n[0];x++)
{
- int index=(x-1)*n[1]*n[2] + (y-1)*n[2] + z-1;
- vp->data_r[index] = origf * vp->data_r[index] + fac * sr[ms_I(x,y,z,n)];
- vp->data_g[index] = origf * vp->data_g[index] + fac * sg[ms_I(x,y,z,n)];
- vp->data_b[index] = origf * vp->data_b[index] + fac * sb[ms_I(x,y,z,n)];
+ const int i = lc_to_ms_I(x, y ,z, n); //lc index
+ const int j = ms_I(x, y, z, n); //ms index
+
+ vp->data_r[i] = origf * vp->data_r[i] + fac * sr[j];
+ vp->data_g[i] = origf * vp->data_g[i] + fac * sg[j];
+ vp->data_b[i] = origf * vp->data_b[i] + fac * sb[j];
}
}
}
@@ -426,7 +444,7 @@ static void *vol_precache_part(void *data)
ShadeInput *shi = pa->shi;
float scatter_col[3] = {0.f, 0.f, 0.f};
float co[3];
- int x, y, z;
+ int x, y, z, i;
const int res[3]= {pa->res[0], pa->res[1], pa->res[2]};
for (z= pa->minz; z < pa->maxz; z++) {
@@ -437,12 +455,14 @@ static void *vol_precache_part(void *data)
for (x=pa->minx; x < pa->maxx; x++) {
co[0] = pa->bbmin[0] + (pa->voxel[0] * (x + 0.5f));
+
+ i= V_I(x, y, z, res);
// don't bother if the point is not inside the volume mesh
if (!point_inside_obi(tree, obi, co)) {
- obi->volume_precache->data_r[ V_I(x, y, z, res) ] = -1.0f;
- obi->volume_precache->data_g[ V_I(x, y, z, res) ] = -1.0f;
- obi->volume_precache->data_b[ V_I(x, y, z, res) ] = -1.0f;
+ obi->volume_precache->data_r[i] = -1.0f;
+ obi->volume_precache->data_g[i] = -1.0f;
+ obi->volume_precache->data_b[i] = -1.0f;
continue;
}
@@ -450,9 +470,9 @@ static void *vol_precache_part(void *data)
normalize_v3(shi->view);
vol_get_scattering(shi, scatter_col, co);
- obi->volume_precache->data_r[ V_I(x, y, z, res) ] = scatter_col[0];
- obi->volume_precache->data_g[ V_I(x, y, z, res) ] = scatter_col[1];
- obi->volume_precache->data_b[ V_I(x, y, z, res) ] = scatter_col[2];
+ obi->volume_precache->data_r[i] = scatter_col[0];
+ obi->volume_precache->data_g[i] = scatter_col[1];
+ obi->volume_precache->data_b[i] = scatter_col[2];
}
}
}
@@ -684,12 +704,13 @@ void vol_precache_objectinstance_threads(Render *re, ObjectInstanceRen *obi, Mat
//tree= NULL;
}
- lightcache_filter(obi->volume_precache);
-
if (ELEM(ma->vol.shade_type, MA_VOL_SHADE_MULTIPLE, MA_VOL_SHADE_SHADEDPLUSMULTIPLE))
{
- multiple_scattering_diffusion(re, vp, ma);
+ /* this should be before the filtering */
+ multiple_scattering_diffusion(re, obi->volume_precache, ma);
}
+
+ lightcache_filter(obi->volume_precache);
}
static int using_lightcache(Material *ma)
@@ -741,7 +762,7 @@ int point_inside_volume_objectinstance(Render *re, ObjectInstanceRen *obi, float
RayObject *tree;
int inside=0;
- tree = makeraytree_object(re, obi); //create_raytree_obi(obi, obi->obr->boundbox[0], obi->obr->boundbox[1]);
+ tree = makeraytree_object(re, obi);
if (!tree) return 0;
inside = point_inside_obi(tree, obi, co);
diff --git a/source/blender/render/intern/source/volumetric.c b/source/blender/render/intern/source/volumetric.c
index 32ab2980316..e44064de606 100644
--- a/source/blender/render/intern/source/volumetric.c
+++ b/source/blender/render/intern/source/volumetric.c
@@ -493,7 +493,7 @@ void vol_shade_one_lamp(struct ShadeInput *shi, float *co, LampRen *lar, float *
if (shi->mat->vol.shade_type == MA_VOL_SHADE_SHADOWED) {
mul_v3_fl(lacol, vol_get_shadow(shi, lar, co));
}
- else if (shi->mat->vol.shade_type == MA_VOL_SHADE_SHADED)
+ else if (ELEM3(shi->mat->vol.shade_type, MA_VOL_SHADE_SHADED, MA_VOL_SHADE_MULTIPLE, MA_VOL_SHADE_SHADEDPLUSMULTIPLE))
{
Isect is;