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:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>2008-10-07 19:01:44 +0400
committerBrecht Van Lommel <brechtvanlommel@pandora.be>2008-10-07 19:01:44 +0400
commit94a9fa4711be6411002bdd32ffbb01c7402f4920 (patch)
tree22c8efaa75886c840044ad1c58b0450c6d29a44c /source/blender/render/intern/source/rayshade.c
parent0d7d520ffa3cf52829f765687766db694b92f2b1 (diff)
Fix for bug #13363: ray (qmc) shadows had some light leaking issues,
due to jittering of the start position for antialiasing in a pixel. Now it distributes the start position over the fixed osa sample positions, instead of of random positions in space. The ugly bit is that a custom ordering was defined for osa 8/11/16 to ensure that the first 4 are distributed relatively fair for adaptive sampling to decide if more samples need to be taken.
Diffstat (limited to 'source/blender/render/intern/source/rayshade.c')
-rw-r--r--source/blender/render/intern/source/rayshade.c104
1 files changed, 62 insertions, 42 deletions
diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c
index 9d457e7f0fc..f822d41bb85 100644
--- a/source/blender/render/intern/source/rayshade.c
+++ b/source/blender/render/intern/source/rayshade.c
@@ -1792,21 +1792,62 @@ void ray_ao(ShadeInput *shi, float *shadfac)
ray_ao_spheresamp(shi, shadfac);
}
+static void ray_shadow_jittered_coords(ShadeInput *shi, int max, float jitco[RE_MAX_OSA][3], int *totjitco)
+{
+ /* magic numbers for reordering sample positions to give better
+ * results with adaptive sample, when it usually only takes 4 samples */
+ int order8[8] = {0, 1, 5, 6, 2, 3, 4, 7};
+ int order11[11] = {1, 3, 8, 10, 0, 2, 4, 5, 6, 7, 9};
+ int order16[16] = {1, 3, 9, 12, 0, 6, 7, 8, 13, 2, 4, 5, 10, 11, 14, 15};
+ int count = count_mask(shi->mask);
+
+ /* for better antialising shadow samples are distributed over the subpixel
+ * sample coordinates, this only works for raytracing depth 0 though */
+ if(!shi->strand && shi->depth == 0 && count > 1 && count <= max) {
+ float xs, ys, zs, view[3];
+ int samp, ordsamp, tot= 0;
+
+ for(samp=0; samp<R.osa; samp++) {
+ if(R.osa == 8) ordsamp = order8[samp];
+ else if(R.osa == 11) ordsamp = order11[samp];
+ else if(R.osa == 16) ordsamp = order16[samp];
+ else ordsamp = samp;
+
+ if(shi->mask & (1<<ordsamp)) {
+ /* zbuffer has this inverse corrected, ensures xs,ys are inside pixel */
+ xs= (float)shi->scanco[0] + R.jit[ordsamp][0] + 0.5f;
+ ys= (float)shi->scanco[1] + R.jit[ordsamp][1] + 0.5f;
+ zs= shi->scanco[2];
+
+ shade_input_calc_viewco(shi, xs, ys, zs, view, NULL, jitco[tot], NULL, NULL);
+ tot++;
+ }
+ }
+
+ *totjitco= tot;
+ }
+ else {
+ VECCOPY(jitco[0], shi->co);
+ *totjitco= 1;
+ }
+}
static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float *shadfac, Isect *isec)
{
QMCSampler *qsa=NULL;
- QMCSampler *qsa_jit=NULL;
int samples=0;
- float samp3d[3], jit[3], jitbias= 0.0f;
+ float samp3d[3];
float fac=0.0f, vec[3];
float colsq[4];
float adapt_thresh = lar->adapt_thresh;
- int max_samples = lar->ray_totsamp;
- float pos[3];
+ int min_adapt_samples=4, max_samples = lar->ray_totsamp;
+ float *co;
int do_soft=1, full_osa=0;
+ float jitco[RE_MAX_OSA][3];
+ int totjitco;
+
colsq[0] = colsq[1] = colsq[2] = 0.0;
if(isec->mode==RE_RAY_SHADOW_TRA) {
shadfac[0]= shadfac[1]= shadfac[2]= shadfac[3]= 0.0f;
@@ -1823,21 +1864,16 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float *
if (do_soft) max_samples = lar->ray_totsamp;
else max_samples = (R.osa > 4)?R.osa:5;
}
-
- if(shi->vlr && ((shi->vlr->flag & R_FULL_OSA) == 0))
- jitbias= 0.5f*(VecLength(shi->dxco) + VecLength(shi->dyco));
+
+ ray_shadow_jittered_coords(shi, max_samples, jitco, &totjitco);
/* sampling init */
- if (lar->ray_samp_method==LA_SAMP_HALTON) {
+ if (lar->ray_samp_method==LA_SAMP_HALTON)
qsa = get_thread_qmcsampler(&R, shi->thread, SAMP_TYPE_HALTON, max_samples);
- qsa_jit = get_thread_qmcsampler(&R, shi->thread, SAMP_TYPE_HALTON, max_samples);
- } else if (lar->ray_samp_method==LA_SAMP_HAMMERSLEY) {
+ else if (lar->ray_samp_method==LA_SAMP_HAMMERSLEY)
qsa = get_thread_qmcsampler(&R, shi->thread, SAMP_TYPE_HAMMERSLEY, max_samples);
- qsa_jit = get_thread_qmcsampler(&R, shi->thread, SAMP_TYPE_HAMMERSLEY, max_samples);
- }
QMC_initPixel(qsa, shi->thread);
- QMC_initPixel(qsa_jit, shi->thread);
VECCOPY(vec, lampco);
@@ -1845,18 +1881,11 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float *
while (samples < max_samples) {
isec->faceorig= (RayFace*)shi->vlr;
isec->oborig= RAY_OBJECT_SET(&R, shi->obi);
-
+
/* manually jitter the start shading co-ord per sample
* based on the pre-generated OSA texture sampling offsets,
* for anti-aliasing sharp shadow edges. */
- VECCOPY(pos, shi->co);
- if (shi->vlr && !full_osa) {
- QMC_sampleRect(jit, qsa_jit, shi->thread, samples, 1.0, 1.0);
-
- pos[0] += shi->dxco[0]*jit[0] + shi->dyco[0]*jit[1];
- pos[1] += shi->dxco[1]*jit[0] + shi->dyco[1]*jit[1];
- pos[2] += shi->dxco[2]*jit[0] + shi->dyco[2]*jit[1];
- }
+ co = jitco[samples % totjitco];
if (do_soft) {
/* sphere shadow source */
@@ -1864,9 +1893,9 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float *
float ru[3], rv[3], v[3], s[3];
/* calc tangent plane vectors */
- v[0] = pos[0] - lampco[0];
- v[1] = pos[1] - lampco[1];
- v[2] = pos[2] - lampco[2];
+ v[0] = co[0] - lampco[0];
+ v[1] = co[1] - lampco[1];
+ v[2] = co[2] - lampco[2];
Normalize(v);
VecOrthoBasisf(v, ru, rv);
@@ -1879,13 +1908,6 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float *
s[2] = samp3d[0]*ru[2] + samp3d[1]*rv[2];
VECCOPY(samp3d, s);
-
- if(jitbias != 0.0f) {
- /* bias away somewhat to avoid self intersection */
- pos[0] -= jitbias*v[0];
- pos[1] -= jitbias*v[1];
- pos[2] -= jitbias*v[2];
- }
}
else {
/* sampling, returns quasi-random vector in [sizex,sizey]^2 plane */
@@ -1901,20 +1923,20 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float *
VECCOPY(isec->end, vec);
}
- if(jitbias != 0.0f && !(do_soft && lar->type==LA_LOCAL)) {
+ if(shi->strand) {
/* bias away somewhat to avoid self intersection */
+ float jitbias= 0.5f*(VecLength(shi->dxco) + VecLength(shi->dyco));
float v[3];
- VECSUB(v, pos, isec->end);
+ VECSUB(v, co, isec->end);
Normalize(v);
- pos[0] -= jitbias*v[0];
- pos[1] -= jitbias*v[1];
- pos[2] -= jitbias*v[2];
+ co[0] -= jitbias*v[0];
+ co[1] -= jitbias*v[1];
+ co[2] -= jitbias*v[2];
}
- VECCOPY(isec->start, pos);
-
+ VECCOPY(isec->start, co);
/* trace the ray */
if(isec->mode==RE_RAY_SHADOW_TRA) {
@@ -1941,7 +1963,7 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float *
if ((lar->ray_samp_method == LA_SAMP_HALTON)) {
/* adaptive sampling - consider samples below threshold as in shadow (or vice versa) and exit early */
- if ((max_samples > 4) && (adapt_thresh > 0.0) && (samples > max_samples / 3)) {
+ if ((max_samples > min_adapt_samples) && (adapt_thresh > 0.0) && (samples > max_samples / 3)) {
if (isec->mode==RE_RAY_SHADOW_TRA) {
if ((shadfac[3] / samples > (1.0-adapt_thresh)) || (shadfac[3] / samples < adapt_thresh))
break;
@@ -1963,8 +1985,6 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float *
} else
shadfac[3]= 1.0f-fac/samples;
- if (qsa_jit)
- release_thread_qmcsampler(&R, shi->thread, qsa_jit);
if (qsa)
release_thread_qmcsampler(&R, shi->thread, qsa);
}