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
path: root/source
diff options
context:
space:
mode:
authorTon Roosendaal <ton@blender.org>2004-05-15 22:07:09 +0400
committerTon Roosendaal <ton@blender.org>2004-05-15 22:07:09 +0400
commita4861c37bee39d201423dd9d44a116b60bdd3298 (patch)
tree64461d36f5a37fb8dcad06324d6afbb34547495c /source
parentb4ecf7d973d2a89162fea1571cbc0fbd565cf946 (diff)
Assuming the freeze is over and we can head towards 2.34: this is the
first commit for review and improvements on OSA (anti aliasing) in Blender. http://www.blender3d.org/cms/Rendering_engine.320.0.html Most relevant changes: - full check on subpixel sample locations - all subpixels are fully rendered (gives spec AA, procedural texture AA) - also unified render uses it - removed double-used code for unified render Whether or not this will be optional (better pics, but in some cases slow) is to further evaluate. For raytracing - for example - this cannot be simply done, since the new sampling system made raytrace code much simpler.
Diffstat (limited to 'source')
-rw-r--r--source/blender/render/intern/source/initrender.c65
-rw-r--r--source/blender/render/intern/source/jitter.c10
-rw-r--r--source/blender/render/intern/source/ray.c374
-rw-r--r--source/blender/render/intern/source/rendercore.c107
-rw-r--r--source/blender/render/intern/source/vanillaRenderPipe.c17
-rw-r--r--source/blender/render/intern/source/zbuf.c104
-rw-r--r--source/blender/render/intern/source/zbufferdatastruct.c2
7 files changed, 251 insertions, 428 deletions
diff --git a/source/blender/render/intern/source/initrender.c b/source/blender/render/intern/source/initrender.c
index 1b61a28af20..dc5bb340340 100644
--- a/source/blender/render/intern/source/initrender.c
+++ b/source/blender/render/intern/source/initrender.c
@@ -94,7 +94,7 @@
#include "zbuf.h"
#include "rendercore.h" /* part handler for the old renderer, shading functions */
#include "renderPreAndPost.h"
-#include "outerRenderLoop.h"
+#include "vanillaRenderPipe.h"
#include "renderHelp.h"
#include "jitter.h"
@@ -178,8 +178,8 @@ float calc_weight(float *weight, int i, int j)
fac*= fac;
for(a=0; a<R.osa; a++) {
- x= jit[a][0]-0.5+ i;
- y= jit[a][1]-0.5+ j;
+ x= jit[a][0] + i;
+ y= jit[a][1] + j;
dist= sqrt(x*x+y*y);
weight[a]= 0.0;
@@ -410,9 +410,11 @@ void RE_init_filt_mask(void)
for(a= (1<<R.osa)-1; a>0; a--) {
val= count_mask(a);
- i= (15.9*(fpy1[a & 255]+fpy2[a>>8])/val);
- i<<=4;
- i+= (15.9*(fpx1[a & 255]+fpx2[a>>8])/val);
+ i= 8+(15.9*(fpy1[a & 255]+fpy2[a>>8])/val);
+ CLAMP(i, 0, 15);
+ j= 8+(15.9*(fpx1[a & 255]+fpx2[a>>8])/val);
+ CLAMP(j, 0, 15);
+ i= j + (i<<4);
centmask[a]= i;
}
@@ -527,22 +529,15 @@ void RE_setwindowclip(int mode, int jmode)
}
- /* I think these offsets are wrong. They do not coincide with shadow */
- /* calculations, btw. */
- minx= R.xstart+.5;
- miny= R.ycor*(R.ystart+.5);
- maxx= R.xend+.4999;
- maxy= R.ycor*(R.yend+.4999);
- /* My guess: (or rather, what should be) */
- /* minx= R.xstart - 0.5; */
- /* miny= R.ycor * (R.ystart - 0.5); */
- /* Since the SCS-s map directly to the pixel center coordinates, we need */
- /* to stretch the clip area a bit, not just shift it. However, this gives*/
- /* nasty problems for parts... */
-
- /* Dunno who wrote previous comment, but I found an error with uncorrected
- blur offset in shadepixel(). Now solved with 2 globals, seems to work.
- The whole method how to retrieve the correct coordinate needs revision. (ton) */
+ /* revision / simplification of subpixel offsets:
+ - the matrix will go without offset from start (e.g. -100) to end (e.g. +99).
+ - filling in with zbuffer will set offset of 0.5. to make sure clipped faces fill in too
+ - in shadepixel() again that 0.5 offset is corrected
+ */
+ minx= R.xstart;
+ miny= R.ycor*(R.ystart);
+ maxx= R.xend;
+ maxy= R.ycor*(R.yend);
if(R.flag & R_SEC_FIELD) {
if(R.r.mode & R_ODDFIELD) {
@@ -766,11 +761,11 @@ void render() {
yafrayRender();
else {
/* not too neat... should improve... */
- if(R.r.mode & R_UNIFIED) {
- unifiedRenderingLoop();
- } else {
+ //if(R.r.mode & R_UNIFIED) {
+ // unifiedRenderingLoop();
+ //} else {
oldRenderLoop();
- }
+ //}
}
}
@@ -856,21 +851,25 @@ void oldRenderLoop(void) /* here the PART and FIELD loops */
if(RE_local_test_break()) break;
- /* ZBUFFER & SHADE: zbuffer stores integer distances, and integer face indices */
+ /* rectot is for result and integer face indices */
R.rectot= (unsigned int *)MEM_callocN(sizeof(int)*R.rectx*R.recty, "rectot");
- R.rectz = (unsigned int *)MEM_mallocN(sizeof(int)*R.rectx*R.recty, "rectz");
-
+
if(R.r.mode & R_MBLUR) {
RE_local_printrenderinfo(0.0, R.osa - blur);
if(G.background && blur<R.osa) printf("\n"); // newline for percentage print
}
else RE_local_printrenderinfo(0.0, -1);
- /* choose render pipeline type, and whether or not to use the */
- /* delta accumulation buffer. 3 choices. */
- if(R.r.mode & R_OSA) zbufshadeDA();
- else zbufshade();
+ if(R.r.mode & R_UNIFIED) {
+ zBufShadeAdvanced();
+ }
+ else {
+ R.rectz = (unsigned int *)MEM_mallocN(sizeof(int)*R.rectx*R.recty, "rectz");
+ if(R.r.mode & R_OSA) zbufshadeDA();
+ else zbufshade();
+ }
+
if(RE_local_test_break()) break;
/* exception */
diff --git a/source/blender/render/intern/source/jitter.c b/source/blender/render/intern/source/jitter.c
index 0254b82bed4..50f465f4932 100644
--- a/source/blender/render/intern/source/jitter.c
+++ b/source/blender/render/intern/source/jitter.c
@@ -178,19 +178,25 @@ void initjit(float *jitarr, int num)
}
MEM_freeN(jit2);
+
+ /* finally, move jittertab to be centered around (0,0) */
+ for(i=0; i<2*num; i+=2) {
+ jitarr[i] -= 0.5;
+ jitarr[i+1] -= 0.5;
+ }
+
}
void init_render_jit(int nr)
{
static int lastjit= 0;
-
+
if(lastjit==nr) return;
memset(jit, 0, 64*2*4);
initjit(jit[0], nr);
lastjit= nr;
-
}
/* eof */
diff --git a/source/blender/render/intern/source/ray.c b/source/blender/render/intern/source/ray.c
index 040c4a00caa..694f27faeb8 100644
--- a/source/blender/render/intern/source/ray.c
+++ b/source/blender/render/intern/source/ray.c
@@ -1381,40 +1381,6 @@ static void refraction(float *refract, float *n, float *view, float index)
refract[2]= index*view[2] + fac*n[2];
}
-static void calc_dx_dy_refract(float *ref, float *n, float *view, float index, int smooth)
-{
- float dref[3], dview[3], dnor[3];
-
- refraction(ref, n, view, index);
-
- dview[0]= view[0]+ O.dxview;
- dview[1]= view[1];
- dview[2]= view[2];
-
- if(smooth) {
- VECADD(dnor, n, O.dxno);
- refraction(dref, dnor, dview, index);
- }
- else {
- refraction(dref, n, dview, index);
- }
- VECSUB(O.dxrefract, ref, dref);
-
- dview[0]= view[0];
- dview[1]= view[1]+ O.dyview;
-
- if(smooth) {
- VECADD(dnor, n, O.dyno);
- refraction(dref, dnor, dview, index);
- }
- else {
- refraction(dref, n, dview, index);
- }
- VECSUB(O.dyrefract, ref, dref);
-
-}
-
-
/* orn = original face normal */
static void reflection(float *ref, float *n, float *view, float *orn)
{
@@ -1655,9 +1621,13 @@ static float *jitter_plane(LampRen *lar, int xs, int ys)
}
if(lar->ray_samp_type & LA_SAMP_JITTER) {
- static float jitter[2*256];
- jitter_plane_offset(lar->jitter, jitter, tot, lar->area_size, lar->area_sizey, BLI_frand(), BLI_frand());
- return jitter;
+ static int xold=0, yold=0;
+ /* new OSA allows to enter this function many times for 1 pixel */
+ if(xold!=xs || yold!=ys) {
+ jitter_plane_offset(lar->jitter, lar->jitter+2*tot, tot, lar->area_size, lar->area_sizey, BLI_frand(), BLI_frand());
+ xold= xs; yold= ys;
+ }
+ return lar->jitter+2*tot;
}
if(lar->ray_samp_type & LA_SAMP_DITHER) {
return lar->jitter + 2*tot*((xs & 1)+2*(ys & 1));
@@ -1683,128 +1653,42 @@ void ray_trace(ShadeInput *shi, ShadeResult *shr)
coh_test= 0; // reset coherence optimize
- if(R.r.mode & R_OSA) {
- float accum[3], rco[3], ref[3];
- float accur[3], refract[3], divr=0.0, div= 0.0;
- int j;
-
- if(do_tra) calc_dx_dy_refract(refract, shi->vn, shi->view, shi->matren->ang, vlr->flag & R_SMOOTH);
- if(do_mir) {
- if(vlr->flag & R_SMOOTH)
- reflection(ref, shi->vn, shi->view, vlr->n);
- else
- reflection(ref, shi->vn, shi->view, NULL);
- }
-
- accum[0]= accum[1]= accum[2]= 0.0;
- accur[0]= accur[1]= accur[2]= 0.0;
-
- for(j=0; j<R.osa; j++) {
- if(shi->mask & 1<<j) {
-
- rco[0]= shi->co[0] + (jit[j][0]-0.5)*O.dxco[0] + (jit[j][1]-0.5)*O.dyco[0];
- rco[1]= shi->co[1] + (jit[j][0]-0.5)*O.dxco[1] + (jit[j][1]-0.5)*O.dyco[1];
- rco[2]= shi->co[2] + (jit[j][0]-0.5)*O.dxco[2] + (jit[j][1]-0.5)*O.dyco[2];
-
- if(do_tra) {
- vec[0]= refract[0] + (jit[j][0]-0.5)*O.dxrefract[0] + (jit[j][1]-0.5)*O.dyrefract[0] ;
- vec[1]= refract[1] + (jit[j][0]-0.5)*O.dxrefract[1] + (jit[j][1]-0.5)*O.dyrefract[1] ;
- vec[2]= refract[2] + (jit[j][0]-0.5)*O.dxrefract[2] + (jit[j][1]-0.5)*O.dyrefract[2] ;
-
- traceray(shi->matren->ray_depth_tra, rco, vec, tracol, shi->vlr, shi->mask);
-
- VECADD(accur, accur, tracol);
- divr+= 1.0;
- }
-
- if(do_mir) {
- vec[0]= ref[0] + 2.0*(jit[j][0]-0.5)*O.dxref[0] + 2.0*(jit[j][1]-0.5)*O.dyref[0] ;
- vec[1]= ref[1] + 2.0*(jit[j][0]-0.5)*O.dxref[1] + 2.0*(jit[j][1]-0.5)*O.dyref[1] ;
- vec[2]= ref[2] + 2.0*(jit[j][0]-0.5)*O.dxref[2] + 2.0*(jit[j][1]-0.5)*O.dyref[2] ;
-
- /* prevent normal go to backside */
- i= vec[0]*vlr->n[0]+ vec[1]*vlr->n[1]+ vec[2]*vlr->n[2];
- if(i>0.0) {
- i+= .01;
- vec[0]-= i*vlr->n[0];
- vec[1]-= i*vlr->n[1];
- vec[2]-= i*vlr->n[2];
- }
-
- /* we use a new mask here, only shadow uses it */
- /* result in accum, this is copied to shade_lamp_loop */
- traceray(shi->matren->ray_depth, rco, vec, mircol, shi->vlr, 1<<j);
-
- VECADD(accum, accum, mircol);
- div+= 1.0;
- }
- }
- }
+ if(do_tra) {
+ float refract[3];
- if(divr!=0.0) {
- f= shr->alpha; f1= 1.0-f; f1/= divr;
- shr->diff[0]= f*shr->diff[0] + f1*accur[0];
- shr->diff[1]= f*shr->diff[1] + f1*accur[1];
- shr->diff[2]= f*shr->diff[2] + f1*accur[2];
- shr->alpha= 1.0;
- }
+ refraction(refract, shi->vn, shi->view, shi->matren->ang);
+ traceray(shi->matren->ray_depth_tra, shi->co, refract, tracol, shi->vlr, shi->mask);
- if(div!=0.0) {
- i= shi->matren->ray_mirror*fresnel_fac(shi->view, shi->vn, shi->matren->fresnel_mir_i, shi->matren->fresnel_mir);
+ f= shr->alpha; f1= 1.0-f;
+ shr->diff[0]= f*shr->diff[0] + f1*tracol[0];
+ shr->diff[1]= f*shr->diff[1] + f1*tracol[1];
+ shr->diff[2]= f*shr->diff[2] + f1*tracol[2];
+ shr->alpha= 1.0;
+ }
+
+ if(do_mir) {
+
+ i= shi->matren->ray_mirror*fresnel_fac(shi->view, shi->vn, shi->matren->fresnel_mir_i, shi->matren->fresnel_mir);
+ if(i!=0.0) {
fr= shi->matren->mirr;
fg= shi->matren->mirg;
fb= shi->matren->mirb;
+
+ if(vlr->flag & R_SMOOTH)
+ reflection(vec, shi->vn, shi->view, vlr->n);
+ else
+ reflection(vec, shi->vn, shi->view, NULL);
- /* result */
- f= i*fr*(1.0-shr->spec[0]); f1= 1.0-i; f/= div;
- shr->diff[0]= f*accum[0] + f1*shr->diff[0];
-
- f= i*fg*(1.0-shr->spec[1]); f1= 1.0-i; f/= div;
- shr->diff[1]= f*accum[1] + f1*shr->diff[1];
+ traceray(shi->matren->ray_depth, shi->co, vec, mircol, shi->vlr, shi->mask);
- f= i*fb*(1.0-shr->spec[2]); f1= 1.0-i; f/= div;
- shr->diff[2]= f*accum[2] + f1*shr->diff[2];
- }
- }
- else {
-
- if(do_tra) {
- float refract[3];
+ f= i*fr*(1.0-shr->spec[0]); f1= 1.0-i;
+ shr->diff[0]= f*mircol[0] + f1*shr->diff[0];
- refraction(refract, shi->vn, shi->view, shi->matren->ang);
- traceray(shi->matren->ray_depth_tra, shi->co, refract, tracol, shi->vlr, shi->mask);
+ f= i*fg*(1.0-shr->spec[1]); f1= 1.0-i;
+ shr->diff[1]= f*mircol[1] + f1*shr->diff[1];
- f= shr->alpha; f1= 1.0-f;
- shr->diff[0]= f*shr->diff[0] + f1*tracol[0];
- shr->diff[1]= f*shr->diff[1] + f1*tracol[1];
- shr->diff[2]= f*shr->diff[2] + f1*tracol[2];
- shr->alpha= 1.0;
- }
-
- if(do_mir) {
-
- i= shi->matren->ray_mirror*fresnel_fac(shi->view, shi->vn, shi->matren->fresnel_mir_i, shi->matren->fresnel_mir);
- if(i!=0.0) {
- fr= shi->matren->mirr;
- fg= shi->matren->mirg;
- fb= shi->matren->mirb;
-
- if(vlr->flag & R_SMOOTH)
- reflection(vec, shi->vn, shi->view, vlr->n);
- else
- reflection(vec, shi->vn, shi->view, NULL);
-
- traceray(shi->matren->ray_depth, shi->co, vec, mircol, shi->vlr, shi->mask);
-
- f= i*fr*(1.0-shr->spec[0]); f1= 1.0-i;
- shr->diff[0]= f*mircol[0] + f1*shr->diff[0];
-
- f= i*fg*(1.0-shr->spec[1]); f1= 1.0-i;
- shr->diff[1]= f*mircol[1] + f1*shr->diff[1];
-
- f= i*fb*(1.0-shr->spec[2]); f1= 1.0-i;
- shr->diff[2]= f*mircol[2] + f1*shr->diff[2];
- }
+ f= i*fb*(1.0-shr->spec[2]); f1= 1.0-i;
+ shr->diff[2]= f*mircol[2] + f1*shr->diff[2];
}
}
}
@@ -1971,10 +1855,10 @@ static void DistributedSpherical(float *sphere, int tot, int iter)
}
}
-static float *sphere_sampler(int type, int resol, float *nrm)
+static float *sphere_sampler(int type, int resol, int xs, int ys)
{
static float sphere[2*3*256], sphere1[2*3*256];
- static int last_distr= 0, tot;
+ int tot;
float *vec;
if(resol>16) return sphere;
@@ -1991,6 +1875,7 @@ static float *sphere_sampler(int type, int resol, float *nrm)
}
}
else {
+ static int last_distr= 0, xold=0xffff, yold=0;
float cosf, sinf, cost, sint;
float ang, *vec1;
int a;
@@ -1998,67 +1883,25 @@ static float *sphere_sampler(int type, int resol, float *nrm)
if(last_distr!=resol) DistributedSpherical(sphere, tot, 16);
last_distr= resol;
- // random rotation
- ang= BLI_frand();
- sinf= sin(ang); cosf= cos(ang);
- ang= BLI_frand();
- sint= sin(ang); cost= cos(ang);
-
- vec= sphere;
- vec1= sphere1;
- for (a=0; a<tot; a++, vec+=3, vec1+=3) {
- vec1[0]= cost*cosf*vec[0] - sinf*vec[1] + sint*cosf*vec[2];
- vec1[1]= cost*sinf*vec[0] + cosf*vec[1] + sint*sinf*vec[2];
- vec1[2]= -sint*vec[0] + cost*vec[2];
- }
- return sphere1;
- }
-#if 0
- { /* stratified uniform sampling */
- float gdiv = 1.0/resol;
- float gdiv2p = gdiv*2.0*M_PI;
- float d, z1, z2, sqz1, sz2, cz2;
- float ru[3], rv[3];
- int x, y;
-
- last_distr= 0;
-
-
- /* calculate the two perpendicular vectors */
- if ((nrm[0]==0.0) && (nrm[1]==0.0)) {
- if (nrm[2]<0) ru[0]=-1; else ru[0]=1;
- ru[1] = ru[2] = 0;
- rv[0] = rv[2] = 0;
- rv[1] = 1;
- }
- else {
- ru[0] = nrm[1];
- ru[1] = -nrm[0];
- ru[2] = 0.0;
- d = ru[0]*ru[0] + ru[1]*ru[1];
- if (d!=0) {
- d = 1.0/sqrt(d);
- ru[0] *= d;
- ru[1] *= d;
- }
- Crossf(rv, nrm, ru);
- }
-
- vec= sphere;
- for (x=0; x<resol; x++) {
- for (y=0; y<resol; y++, vec+=3) {
- z1 = (x + BLI_frand()) * gdiv;
- z2 = (y + BLI_frand()) * gdiv2p;
- if ((sqz1 = 1.0-z1*z1)<0) sqz1=0; else sqz1=sqrt(sqz1);
- sz2 = sin(z2);
- cz2 = cos(z2);
- vec[0] = sqz1*(cz2*ru[0] + sz2*rv[0]) + nrm[0]*z1;
- vec[1] = sqz1*(cz2*ru[1] + sz2*rv[1]) + nrm[1]*z1;
- vec[2] = sqz1*(cz2*ru[2] + sz2*rv[2]) + nrm[2]*z1;
+ if(xold!=xs || yold!=ys) {
+ xold=xs; yold=ys;
+
+ // random rotation
+ ang= BLI_frand();
+ sinf= sin(ang); cosf= cos(ang);
+ ang= BLI_frand();
+ sint= sin(ang); cost= cos(ang);
+
+ vec= sphere;
+ vec1= sphere1;
+ for (a=0; a<tot; a++, vec+=3, vec1+=3) {
+ vec1[0]= cost*cosf*vec[0] - sinf*vec[1] + sint*cosf*vec[2];
+ vec1[1]= cost*sinf*vec[0] + cosf*vec[1] + sint*sinf*vec[2];
+ vec1[2]= -sint*vec[0] + cost*vec[2];
}
}
+ return sphere1;
}
-#endif
return sphere;
}
@@ -2097,7 +1940,7 @@ void ray_ao(ShadeInput *shi, World *wrld, float *shadfac)
nrm= shi->vlr->n;
}
- vec= sphere_sampler(wrld->aomode, wrld->aosamp, nrm);
+ vec= sphere_sampler(wrld->aomode, wrld->aosamp, floor(shi->xs+0.5), floor(shi->ys+0.5) );
// warning: since we use full sphere now, and dotproduct is below, we do twice as much
tot= 2*wrld->aosamp*wrld->aosamp;
@@ -2117,6 +1960,7 @@ void ray_ao(ShadeInput *shi, World *wrld, float *shadfac)
actual++;
+ /* always set start/end, 3dda clips it */
VECCOPY(isec.start, shi->co);
isec.end[0] = shi->co[0] - maxdist*vec[0];
isec.end[1] = shi->co[1] - maxdist*vec[1];
@@ -2171,7 +2015,7 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac)
{
Isect isec;
Material stored;
- float fac, div=0.0, lampco[3];
+ float lampco[3];
if(shi->matren->mode & MA_SHADOW_TRA) {
isec.mode= DDA_SHADOW_TRA;
@@ -2194,108 +2038,76 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac)
/* shadow and soft not implemented yet */
if(lar->ray_totsamp<2 || isec.mode == DDA_SHADOW_TRA) {
- if(R.r.mode & R_OSA) {
- float accum[4]={0.0, 0.0, 0.0, 0.0};
- int j;
-
- fac= 0.0;
-
- for(j=0; j<R.osa; j++) {
- if(shi->mask & 1<<j) {
- /* set up isec */
- isec.start[0]= shi->co[0] + (jit[j][0]-0.5)*O.dxco[0] + (jit[j][1]-0.5)*O.dyco[0] ;
- isec.start[1]= shi->co[1] + (jit[j][0]-0.5)*O.dxco[1] + (jit[j][1]-0.5)*O.dyco[1] ;
- isec.start[2]= shi->co[2] + (jit[j][0]-0.5)*O.dxco[2] + (jit[j][1]-0.5)*O.dyco[2] ;
- VECCOPY(isec.end, lampco);
- isec.vlrorig= shi->vlr;
-
- if(isec.mode==DDA_SHADOW_TRA) {
- isec.col[0]= isec.col[1]= isec.col[2]= 1.0;
- isec.col[3]= 0.0; //alpha
-
- ray_trace_shadow_tra(&isec, DEPTH_SHADOW_TRA);
-
- accum[0]+= isec.col[0]; accum[1]+= isec.col[1];
- accum[2]+= isec.col[2]; accum[3]+= isec.col[3];
- }
- else if( d3dda(&isec) ) fac+= 1.0;
- div+= 1.0;
- }
- }
- if(isec.mode==DDA_SHADOW_TRA) {
- // alpha to 'light'
- accum[3]/= div;
- shadfac[3]= 1.0-accum[3];
- shadfac[0]= shadfac[3]+accum[0]*accum[3]/div;
- shadfac[1]= shadfac[3]+accum[1]*accum[3]/div;
- shadfac[2]= shadfac[3]+accum[2]*accum[3]/div;
- }
- else shadfac[3]= 1.0-fac/div;
- }
- else {
- /* set up isec */
- VECCOPY(isec.start, shi->co);
- VECCOPY(isec.end, lampco);
- isec.vlrorig= shi->vlr;
+ /* set up isec */
+ VECCOPY(isec.start, shi->co);
+ VECCOPY(isec.end, lampco);
+ isec.vlrorig= shi->vlr;
- if(isec.mode==DDA_SHADOW_TRA) {
- isec.col[0]= isec.col[1]= isec.col[2]= 1.0;
- isec.col[3]= 0.0; //alpha
+ if(isec.mode==DDA_SHADOW_TRA) {
+ isec.col[0]= isec.col[1]= isec.col[2]= 1.0;
+ isec.col[3]= 0.0; //alpha
- ray_trace_shadow_tra(&isec, DEPTH_SHADOW_TRA);
+ ray_trace_shadow_tra(&isec, DEPTH_SHADOW_TRA);
- VECCOPY(shadfac, isec.col);
- // alpha to 'light'
- shadfac[3]= 1.0-isec.col[3];
- shadfac[0]= shadfac[3]+shadfac[0]*isec.col[3];
- shadfac[1]= shadfac[3]+shadfac[1]*isec.col[3];
- shadfac[2]= shadfac[3]+shadfac[2]*isec.col[3];
- }
- else if( d3dda(&isec)) shadfac[3]= 0.0;
+ VECCOPY(shadfac, isec.col);
+ // alpha to 'light'
+ shadfac[3]= 1.0-isec.col[3];
+ shadfac[0]= shadfac[3]+shadfac[0]*isec.col[3];
+ shadfac[1]= shadfac[3]+shadfac[1]*isec.col[3];
+ shadfac[2]= shadfac[3]+shadfac[2]*isec.col[3];
}
+ else if( d3dda(&isec)) shadfac[3]= 0.0;
}
else {
/* area soft shadow */
float *jitlamp;
- float vec[3];
- int a, j=0;
+ float fac=0.0, div=0.0, vec[3];
+ int a, j= -1, mask;
isec.vlrorig= shi->vlr;
fac= 0.0;
- jitlamp= jitter_plane(lar, floor(shi->xs), floor(shi->ys));
+ jitlamp= jitter_plane(lar, floor(shi->xs+0.5), floor(shi->ys+0.5));
a= lar->ray_totsamp;
+ /* this correction to make sure we always take at least 1 sample */
+ mask= shi->mask;
+ if(a==4) mask |= (mask>>4)|(mask>>8);
+ else if(a==9) mask |= (mask>>9);
+
while(a--) {
+ if(R.r.mode & R_OSA) {
+ j++;
+ if(j>=R.osa) j= 0;
+ if(!(mask & (1<<j))) {
+ jitlamp+= 2;
+ continue;
+ }
+ }
+
vec[0]= jitlamp[0];
vec[1]= jitlamp[1];
vec[2]= 0.0;
Mat3MulVecfl(lar->mat, vec);
+ /* set start and end, d3dda clips it */
VECCOPY(isec.start, shi->co);
isec.end[0]= lampco[0]+vec[0];
isec.end[1]= lampco[1]+vec[1];
isec.end[2]= lampco[2]+vec[2];
- if(R.r.mode & R_OSA) {
- isec.start[0]= shi->co[0] + (jit[j][0]-0.5)*O.dxco[0] + (jit[j][1]-0.5)*O.dyco[0] ;
- isec.start[1]= shi->co[1] + (jit[j][0]-0.5)*O.dxco[1] + (jit[j][1]-0.5)*O.dyco[1] ;
- isec.start[2]= shi->co[2] + (jit[j][0]-0.5)*O.dxco[2] + (jit[j][1]-0.5)*O.dyco[2] ;
- j++;
- if(j>=R.osa) j= 0;
- }
-
if( d3dda(&isec) ) fac+= 1.0;
-
+ div+= 1.0;
jitlamp+= 2;
}
+
// sqrt makes nice umbra effect
if(lar->ray_samp_type & LA_SAMP_UMBRA)
- shadfac[3]= sqrt(1.0-fac/((float)lar->ray_totsamp));
+ shadfac[3]= sqrt(1.0-fac/div);
else
- shadfac[3]= 1.0-fac/((float)lar->ray_totsamp);
+ shadfac[3]= 1.0-fac/div;
}
if(shi->matren->mode & MA_SHADOW_TRA) {
diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c
index 24ef5d6dd0c..854a32e0fbc 100644
--- a/source/blender/render/intern/source/rendercore.c
+++ b/source/blender/render/intern/source/rendercore.c
@@ -349,13 +349,13 @@ void scanlinesky(char *rect, int y)
view[2]= 0.0;
}
else {
- view[0]= (x+(R.xstart)+1.0);
+ view[0]= (x+(R.xstart)+0.5);
if(R.flag & R_SEC_FIELD) {
- if(R.r.mode & R_ODDFIELD) view[1]= (y+R.ystart+0.5)*R.ycor;
- else view[1]= (y+R.ystart+1.5)*R.ycor;
+ if(R.r.mode & R_ODDFIELD) view[1]= (y+R.ystart)*R.ycor;
+ else view[1]= (y+R.ystart+1.0)*R.ycor;
}
- else view[1]= (y+R.ystart+1.0)*R.ycor;
+ else view[1]= (y+R.ystart+0.5)*R.ycor;
view[2]= -R.viewfac;
@@ -2392,13 +2392,13 @@ void *shadepixel(float x, float y, int vlaknr, int mask, float *col)
dvlak= v1->co[0]*vlr->n[0]+v1->co[1]*vlr->n[1]+v1->co[2]*vlr->n[2];
/* COXYZ AND VIEW VECTOR */
- shi.view[0]= (x+(R.xstart)+1.0+bluroffsx);
+ shi.view[0]= (x+(R.xstart)+bluroffsx +0.5);
if(R.flag & R_SEC_FIELD) {
- if(R.r.mode & R_ODDFIELD) shi.view[1]= (y+R.ystart+0.5)*R.ycor;
- else shi.view[1]= (y+R.ystart+1.5)*R.ycor;
+ if(R.r.mode & R_ODDFIELD) shi.view[1]= (y+R.ystart)*R.ycor;
+ else shi.view[1]= (y+R.ystart+1.0)*R.ycor;
}
- else shi.view[1]= (y+R.ystart+1.0+bluroffsy)*R.ycor;
+ else shi.view[1]= (y+R.ystart+bluroffsy+0.5)*R.ycor;
shi.view[2]= -R.viewfac;
@@ -2565,13 +2565,13 @@ void *shadepixel(float x, float y, int vlaknr, int mask, float *col)
if(R.flag & R_LAMPHALO) {
if(vlaknr<=0) { /* calc view vector and put shi.co at far */
- shi.view[0]= (x+(R.xstart)+1.0);
+ shi.view[0]= (x+(R.xstart)+0.5);
if(R.flag & R_SEC_FIELD) {
- if(R.r.mode & R_ODDFIELD) shi.view[1]= (y+R.ystart+0.5)*R.ycor;
- else shi.view[1]= (y+R.ystart+1.5)*R.ycor;
+ if(R.r.mode & R_ODDFIELD) shi.view[1]= (y+R.ystart)*R.ycor;
+ else shi.view[1]= (y+R.ystart+1.0)*R.ycor;
}
- else shi.view[1]= (y+R.ystart+1.0)*R.ycor;
+ else shi.view[1]= (y+R.ystart+0.5)*R.ycor;
shi.view[2]= -R.viewfac;
@@ -2599,7 +2599,7 @@ void shadepixel_short(float x, float y, int vlaknr, int mask, unsigned short *sh
float colf[4];
shadepixel(x, y, vlaknr, mask, colf);
-
+
if(colf[0]<=0.0) shortcol[0]= 0; else if(colf[0]>=1.0) shortcol[0]= 65535;
else shortcol[0]= 65535.0*colf[0];
if(colf[1]<=0.0) shortcol[1]= 0; else if(colf[1]>=1.0) shortcol[1]= 65535;
@@ -2660,16 +2660,14 @@ void addps(long *rd, int vlak, unsigned int z, short ronde)
{
static PixStr *prev;
PixStr *ps, *last = NULL;
- int vlakand;
if( IS_A_POINTER_CODE(*rd)) {
ps= (PixStr *) POINTER_FROM_CODE(*rd);
- vlakand= (vlak & 0x7FFFFF);
- if( (ps->vlak0 & 0x7FFFFF) == vlakand ) return;
+ if(ps->vlak0==vlak) return;
while(ps) {
- if( (ps->vlak & 0x7FFFFF) == vlakand ) {
+ if( ps->vlak == vlak ) {
ps->mask |= (1<<ronde);
return;
}
@@ -2871,8 +2869,8 @@ void zbufshadeDA(void) /* Delta Accum Pixel Struct */
xd= jit[v][0];
yd= jit[v][1];
- Zjitx= -xd;
- Zjity= -yd;
+ Zjitx= -xd -0.5;
+ Zjity= -yd -0.5;
if((R.r.mode & R_MBLUR)==0) RE_local_printrenderinfo(0.0, v);
@@ -2911,8 +2909,8 @@ void zbufshadeDA(void) /* Delta Accum Pixel Struct */
if(R.flag & (R_ZTRA+R_HALO) ) { /* to get back correct values of zbuffer Z for transp and halos */
xd= jit[0][0];
yd= jit[0][1];
- Zjitx= -xd;
- Zjity= -yd;
+ Zjitx= -xd -0.5;
+ Zjity= -yd -0.5;
RE_setwindowclip(0, -1);
if((R.r.mode & R_MBLUR)==0) RE_local_printrenderinfo(0.0, v);
zbufferall();
@@ -2937,9 +2935,39 @@ void zbufshadeDA(void) /* Delta Accum Pixel Struct */
if(y<R.recty) {
for(x=0; x<R.rectx; x++, rd++) {
-
- if( IS_A_POINTER_CODE(*rd)) {
+ int samp, curmask, face;
+
+ if( IS_A_POINTER_CODE(*rd))
ps= (PixStr *) POINTER_FROM_CODE(*rd);
+ else ps= NULL;
+
+ /* do all subpixels? */
+ if(TRUE) {
+ for(samp=0; samp<R.osa; samp++) {
+ curmask= 1<<samp;
+
+ if(ps) {
+ PixStr *ps1= ps;
+ while(ps1) {
+ if(ps1->mask & curmask) break;
+ ps1= ps1->next;
+ }
+ if(ps1) face= ps1->vlak;
+ else face= ps->vlak0;
+ }
+ else face= (int)*rd;
+
+ xs= (float)x + jit[samp][0];
+ ys= (float)y + jit[samp][1];
+ shadepixel_short(xs, ys, face, curmask, shortcol);
+
+ if(shortcol[3]) add_filt_mask(curmask, shortcol, rb1, rb2, rb3);
+ }
+ }
+ else { /* do collected faces together */
+
+ if(ps) face= ps->vlak0;
+ else face= (int)*rd;
mask= 0;
while(ps) {
@@ -2947,32 +2975,23 @@ void zbufshadeDA(void) /* Delta Accum Pixel Struct */
xs= (float)x+centLut[b & 15];
ys= (float)y+centLut[b>>4];
- shadepixel_short(xs, ys, ps->vlak, ps->mask, shortcol);
+ shadepixel_short(xs, ys, ps->vlak, curmask, shortcol);
- if(shortcol[3]) {
- add_filt_mask(ps->mask, shortcol, rb1, rb2, rb3);
- }
- mask |= ps->mask;
+ if(shortcol[3]) add_filt_mask(curmask, shortcol, rb1, rb2, rb3);
+ mask |= ps->mask;
ps= ps->next;
}
- ps= (PixStr *) POINTER_FROM_CODE(*rd);
- mask= (~mask) & fullmask;
-
- b= centmask[mask];
- xs= (float)x+centLut[b & 15];
- ys= (float)y+centLut[b>>4];
- shadepixel_short(xs, ys, ps->vlak0, mask, shortcol);
+ mask= (~mask) & fullmask;
+ if(mask) {
+ b= centmask[ps->mask];
+ xs= (float)x+centLut[b & 15];
+ ys= (float)y+centLut[b>>4];
- if(shortcol[3]) {
- add_filt_mask(mask, shortcol, rb1, rb2, rb3);
- }
- }
- else {
- shadepixel_short((float)x, (float)y, (int)*rd, fullmask, shortcol);
- if(shortcol[3]) {
- add_filt_mask(fullmask, shortcol, rb1, rb2, rb3);
+ shadepixel_short(xs, ys, face, mask, shortcol);
+
+ if(shortcol[3]) add_filt_mask(curmask, shortcol, rb1, rb2, rb3);
}
}
@@ -3066,7 +3085,7 @@ void zbufshade(void)
unsigned short *acol, shortcol[4];
char *charcol, *rt;
- Zjitx=Zjity= -.5;
+ Zjitx=Zjity= -0.5;
zbufferall();
diff --git a/source/blender/render/intern/source/vanillaRenderPipe.c b/source/blender/render/intern/source/vanillaRenderPipe.c
index d39f1fbac01..07ee01a9cbd 100644
--- a/source/blender/render/intern/source/vanillaRenderPipe.c
+++ b/source/blender/render/intern/source/vanillaRenderPipe.c
@@ -175,7 +175,7 @@ void zBufShadeAdvanced()
int y, keepLooping = 1;
float xjit = 0.0, yjit = 0.0;
- Zjitx=Zjity= -0.5; /* jitter preset: 0.5 pixel */
+ Zjitx=Zjity= -0.5; /* jitter preset: -0.5 pixel */
/* EDGE: for edge rendering we should compute a larger buffer, but this */
/* may require modifications at a deeper level. For now, we just */
@@ -198,8 +198,8 @@ void zBufShadeAdvanced()
osaNr = 1;
xjit = jit[0][0];
yjit = jit[0][1];
- jit[0][0] = 0.45;
- jit[0][1] = 0.45;
+ jit[0][0] = 0.0;
+ jit[0][1] = 0.0;
}
RE_setwindowclip(0, -1); /* just to be sure, reset the view matrix */
@@ -328,8 +328,8 @@ void calcZBufLine(int y)
/* They are added in zbufclip() */
/* Negative: these offsets are added to the vertex coordinates */
/* so it equals translating viewpoint over the positive vector. */
- Zjitx= -jit[Zsample][0];
- Zjity= -jit[Zsample][1];
+ Zjitx= -jit[Zsample][0]-0.5;
+ Zjity= -jit[Zsample][1]-0.5;
keepLooping = fillZBufDistances();
@@ -1482,12 +1482,13 @@ int calcDepth(float x, float y, void *data, int type)
/* jitter has been added to x, y ! */
/* view vector view: screen coords */
- view[0]= (x+(R.xstart) + 0.5 );
+ view[0]= (x+(R.xstart)+0.5);
if(R.flag & R_SEC_FIELD) {
if(R.r.mode & R_ODDFIELD) view[1]= (y + R.ystart)*R.ycor;
- else view[1]= (y+R.ystart + 1.0)*R.ycor;
- } else view[1]= (y+R.ystart + 0.5 )*R.ycor;
+ else view[1]= (y + R.ystart + 1.0)*R.ycor;
+ }
+ else view[1]= (y + R.ystart + 0.5)*R.ycor;
/* for pano, another rotation in the xz plane is needed.... */
diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c
index df34757adeb..a6c50ed6d5d 100644
--- a/source/blender/render/intern/source/zbuf.c
+++ b/source/blender/render/intern/source/zbuf.c
@@ -1041,35 +1041,23 @@ void zbufinvulGL(float *v1, float *v2, float *v3) /* fills in R.rectot the valu
{
double x0,y0,z0;
double x1,y1,z1,x2,y2,z2,xx1;
- double zxd,zyd,zy0,tmp;
+ double zxd,zyd,zy0,tmp, zverg, zd;
float *minv,*maxv,*midv;
unsigned int *rectpofs,*rp;
- int *rz,zverg,zvlak,x;
- int my0,my2,sn1,sn2,rectx,zd,*rectzofs;
+ int *rz,zvlak,x;
+ int my0,my2,sn1,sn2,rectx,*rectzofs;
int y,omsl,xs0,xs1,xs2,xs3, dx0,dx1,dx2;
/* MIN MAX */
if(v1[1]<v2[1]) {
- if(v2[1]<v3[1]) {
- minv=v1; midv=v2; maxv=v3;
- }
- else if(v1[1]<v3[1]) {
- minv=v1; midv=v3; maxv=v2;
- }
- else {
- minv=v3; midv=v1; maxv=v2;
- }
+ if(v2[1]<v3[1]) { minv=v1; midv=v2; maxv=v3; }
+ else if(v1[1]<v3[1]) { minv=v1; midv=v3; maxv=v2; }
+ else { minv=v3; midv=v1; maxv=v2; }
}
else {
- if(v1[1]<v3[1]) {
- minv=v2; midv=v1; maxv=v3;
- }
- else if(v2[1]<v3[1]) {
- minv=v2; midv=v3; maxv=v1;
- }
- else {
- minv=v3; midv=v2; maxv=v1;
- }
+ if(v1[1]<v3[1]) { minv=v2; midv=v1; maxv=v3; }
+ else if(v2[1]<v3[1]) { minv=v2; midv=v3; maxv=v1; }
+ else { minv=v3; midv=v2; maxv=v1; }
}
if(minv[1] == maxv[1]) return; /* no zero sized faces */
@@ -1084,7 +1072,7 @@ void zbufinvulGL(float *v1, float *v2, float *v3) /* fills in R.rectot the valu
/* EDGES : THE LONGEST */
xx1= maxv[1]-minv[1];
- if(xx1!=0.0) {
+ if(xx1>2.0/65536.0) {
z0= (maxv[0]-minv[0])/xx1;
tmp= -65536.0*z0;
@@ -1099,7 +1087,7 @@ void zbufinvulGL(float *v1, float *v2, float *v3) /* fills in R.rectot the valu
}
/* EDGES : THE TOP ONE */
xx1= maxv[1]-midv[1];
- if(xx1!=0.0) {
+ if(xx1>2.0/65536.0) {
z0= (maxv[0]-midv[0])/xx1;
tmp= -65536.0*z0;
@@ -1114,7 +1102,7 @@ void zbufinvulGL(float *v1, float *v2, float *v3) /* fills in R.rectot the valu
}
/* EDGES : BOTTOM ONE */
xx1= midv[1]-minv[1];
- if(xx1!=0.0) {
+ if(xx1>2.0/65536.0) {
z0= (midv[0]-minv[0])/xx1;
tmp= -65536.0*z0;
@@ -1160,7 +1148,7 @@ void zbufinvulGL(float *v1, float *v2, float *v3) /* fills in R.rectot the valu
zxd= -x0/z0;
zyd= -y0/z0;
zy0= my2*zyd+xx1;
- zd= (int)CLAMPIS(zxd, INT_MIN, INT_MAX);
+ zd= zxd;
/* start-offset in rect */
rectx= R.rectx;
@@ -1193,14 +1181,14 @@ void zbufinvulGL(float *v1, float *v2, float *v3) /* fills in R.rectot the valu
if(sn2>=rectx) sn2= rectx-1;
if(sn1<0) sn1= 0;
- zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX);
+ zverg= sn1*zxd+zy0;
rz= rectzofs+sn1;
rp= rectpofs+sn1;
x= sn2-sn1;
while(x>=0) {
if(zverg< *rz) {
- *rz= zverg;
+ *rz= floor(zverg);
*rp= zvlak;
}
zverg+= zd;
@@ -1238,13 +1226,13 @@ void zbufinvulGL(float *v1, float *v2, float *v3) /* fills in R.rectot the valu
if(sn2>=rectx) sn2= rectx-1;
if(sn1<0) sn1= 0;
- zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX);
+ zverg= sn1*zxd+zy0;
rz= rectzofs+sn1;
rp= rectpofs+sn1;
x= sn2-sn1;
while(x>=0) {
if(zverg< *rz) {
- *rz= zverg;
+ *rz= floor(zverg);
*rp= zvlak;
}
zverg+= zd;
@@ -1993,7 +1981,7 @@ void zbuffershad(LampRen *lar)
Zmulx= ((float)R.rectx)/2.0;
Zmuly= ((float)R.recty)/2.0;
- Zjitx= Zjity= -.5;
+ Zjitx= Zjity= -0.5;
fillrect(R.rectz,R.rectx,R.recty,0x7FFFFFFE);
@@ -2093,7 +2081,7 @@ void zbuffer_abuf()
Material *ma=0;
int v, len;
- Zjitx= Zjity= -.5;
+ Zjitx= Zjity= -0.5;
Zmulx= ((float)R.rectx)/2.0;
Zmuly= ((float)R.recty)/2.0;
@@ -2109,8 +2097,8 @@ void zbuffer_abuf()
copyto_abufz(Zsample); /* init zbuffer */
if(R.r.mode & R_OSA) {
- Zjitx= -jit[Zsample][0];
- Zjity= -jit[Zsample][1];
+ Zjitx= -jit[Zsample][0]-0.5;
+ Zjity= -jit[Zsample][1]-0.5;
}
for(v=0; v<R.totvlak; v++) {
@@ -2172,12 +2160,31 @@ int vergzvlak(const void *a1, const void *a2)
void shadetrapixel(float x, float y, int vlak, int mask, unsigned short *shortcol)
{
+
if( (vlak & 0x7FFFFF) > R.totvlak) {
printf("error in shadetrapixel nr: %d\n", (vlak & 0x7FFFFF));
return;
}
-
- shadepixel_short(x, y, vlak, mask, shortcol);
+ if(R.r.mode & R_OSA) {
+ int intcol[4]={0,0,0,0};
+ int a, tot=0;
+
+ for(a=0; a<R.osa; a++) {
+ if(mask & (1<<a)) {
+ shadepixel_short(x+jit[a][0], y+jit[a][1], vlak, 1<<a, shortcol);
+ intcol[0]+= shortcol[0];
+ intcol[1]+= shortcol[1];
+ intcol[2]+= shortcol[2];
+ intcol[3]+= shortcol[3];
+ tot++;
+ }
+ }
+ shortcol[0]= intcol[0]/tot;
+ shortcol[1]= intcol[1]/tot;
+ shortcol[2]= intcol[2]/tot;
+ shortcol[3]= intcol[3]/tot;
+ }
+ else shadepixel_short(x, y, vlak, mask, shortcol);
}
extern unsigned short usegamtab;
@@ -2244,15 +2251,7 @@ void abufsetrow(int y)
}
if(totvlak==1) {
- if(R.r.mode & R_OSA ) {
- b= centmask[ ap->mask[0] ];
- xs= (float)x+centLut[b & 15];
- ys= (float)y+centLut[b>>4];
- }
- else {
- xs= x; ys= y;
- }
- shadetrapixel(xs, ys, ap->p[0], ap->mask[0], shortcol);
+ shadetrapixel((float)x, (float)y, ap->p[0], ap->mask[0], shortcol);
nr= count_mask(ap->mask[0]);
if( (R.r.mode & R_OSA) && nr<R.osa) {
@@ -2288,15 +2287,7 @@ void abufsetrow(int y)
while(totvlak>0) {
totvlak--;
- if(R.r.mode & R_OSA) {
- b= centmask[ zrow[totvlak][2] ];
- xs= (float)x+centLut[b & 15];
- ys= (float)y+centLut[b>>4];
- }
- else {
- xs= x; ys= y;
- }
- shadetrapixel(xs, ys, zrow[totvlak][1], 0xFFFF, shortcol);
+ shadetrapixel((float)x, (float)y, zrow[totvlak][1], 0xFFFF, shortcol);
a= count_mask(zrow[totvlak][2]);
if( (R.r.mode & R_OSA ) && a<R.osa) {
@@ -2310,12 +2301,7 @@ void abufsetrow(int y)
if(a==R.osa) break;
totvlak--;
- b= centmask[ zrow[totvlak][2] ];
-
- xs= (float)x+centLut[b & 15];
- ys= (float)y+centLut[b>>4];
-
- shadetrapixel(xs, ys, zrow[totvlak][1], zrow[totvlak][2], shortcol);
+ shadetrapixel((float)x, (float)y, zrow[totvlak][1], zrow[totvlak][2], shortcol);
sval= addtosampcol(sampcol, shortcol, zrow[totvlak][2]);
}
scol= sampcol;
diff --git a/source/blender/render/intern/source/zbufferdatastruct.c b/source/blender/render/intern/source/zbufferdatastruct.c
index 7406854df66..79f4d854616 100644
--- a/source/blender/render/intern/source/zbufferdatastruct.c
+++ b/source/blender/render/intern/source/zbufferdatastruct.c
@@ -70,7 +70,7 @@
/* if defined: all jittersamples are stored individually. _very_ serious */
/* performance hit ! also gives some buffer size problems in big scenes */
-/* #define RE_INDIVIDUAL_SUBPIXELS */
+#define RE_INDIVIDUAL_SUBPIXELS
/* ------------------------------------------------------------------------- */