forked from bartvdbraak/blender
Another shadowbuffer goodie: the "Halfway trick"
http://www.blender3d.org/cms/Shadow_buffer__Halfway.786.0.html Simply said: by using the average of the nearest and 2nd nearest Z value in Shadowbuffers you can reduce bias errors very well. For backwards compatibility it is a new buffer type though.
This commit is contained in:
parent
3b0adf0bf4
commit
9fa438b4e9
@ -580,6 +580,7 @@ void *add_lamp(void)
|
||||
la->ray_samp= la->ray_sampy= la->ray_sampz= 1;
|
||||
la->area_size=la->area_sizey=la->area_sizez= 1.0;
|
||||
la->buffers= 1;
|
||||
la->buftype= LA_SHADBUF_HALFWAY;
|
||||
|
||||
return la;
|
||||
}
|
||||
|
@ -115,6 +115,7 @@ typedef struct Lamp {
|
||||
/* buftype, no flag */
|
||||
#define LA_SHADBUF_REGULAR 0
|
||||
#define LA_SHADBUF_IRREGULAR 1
|
||||
#define LA_SHADBUF_HALFWAY 2
|
||||
|
||||
/* bufflag, auto clipping */
|
||||
#define LA_SHADBUF_AUTO_START 1
|
||||
|
@ -77,6 +77,7 @@ typedef struct ZSpan {
|
||||
float zmulx, zmuly, zofsx, zofsy; /* transform from hoco to zbuf co */
|
||||
|
||||
int *rectz, *arectz; /* zbuffers, arectz is for transparant */
|
||||
int *rectz1; /* seconday z buffer for shadowbuffer (2nd closest z) */
|
||||
int *rectp; /* polygon index buffer */
|
||||
APixstr *apixbuf, *curpstr; /* apixbuf for transparent */
|
||||
struct ListBase *apsmbase;
|
||||
|
@ -2155,11 +2155,15 @@ static void initshadowbuf(Render *re, LampRen *lar, float mat[][4])
|
||||
shb->d= lar->clipsta;
|
||||
shb->clipend= lar->clipend;
|
||||
|
||||
/* bias is percentage, made 2x karger because of correction for angle of incidence */
|
||||
/* bias is percentage, made 2x larger because of correction for angle of incidence */
|
||||
/* when a ray is closer to parallel of a face, bias value is increased during render */
|
||||
shb->bias= (0.02*lar->bias)*0x7FFFFFFF;
|
||||
shb->bias= shb->bias*(100/re->r.size);
|
||||
|
||||
/* halfway method (average of first and 2nd z) reduces bias issues */
|
||||
if(lar->buftype==LA_SHADBUF_HALFWAY)
|
||||
shb->bias= 0.1f*shb->bias;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -2227,6 +2231,7 @@ static LampRen *add_render_lamp(Render *re, Object *ob)
|
||||
lar->shadhalostep = la->shadhalostep;
|
||||
lar->clipsta = la->clipsta;
|
||||
lar->clipend = la->clipend;
|
||||
|
||||
lar->bias = la->bias;
|
||||
|
||||
lar->type= la->type;
|
||||
|
@ -478,15 +478,15 @@ void RE_SetCamera(Render *re, Object *camera)
|
||||
clipend= cam->clipend;
|
||||
}
|
||||
else if(camera->type==OB_LAMP) {
|
||||
/* fac= cos( PI*((float)(256- la->spsi))/512.0 ); */
|
||||
|
||||
/* phi= acos(fac); */
|
||||
/* lens= 16.0*fac/sin(phi); */
|
||||
lens= re->lens;
|
||||
Lamp *la= camera->data;
|
||||
float fac= cos( M_PI*la->spotsize/360.0 );
|
||||
float phi= acos(fac);
|
||||
|
||||
lens= 16.0*fac/sin(phi);
|
||||
if(lens==0.0f)
|
||||
lens= 35.0;
|
||||
clipsta= 0.1;
|
||||
clipend= 1000.0;
|
||||
clipsta= la->clipsta;
|
||||
clipend= la->clipend;
|
||||
}
|
||||
else { /* envmap exception... */
|
||||
lens= re->lens;
|
||||
|
@ -369,6 +369,9 @@ void makeshadowbuf(Render *re, LampRen *lar)
|
||||
float wsize, *jitbuf, twozero[2]= {0.0f, 0.0f}, angle, temp;
|
||||
int *rectz, samples;
|
||||
|
||||
/* XXXX EVIL! this global is used in clippyra(), zbuf.c */
|
||||
R.clipcrop= 1.0f;
|
||||
|
||||
if(lar->bufflag & (LA_SHADBUF_AUTO_START|LA_SHADBUF_AUTO_END))
|
||||
shadowbuf_autoclip(re, lar);
|
||||
|
||||
@ -386,8 +389,8 @@ void makeshadowbuf(Render *re, LampRen *lar)
|
||||
|
||||
i_window(-wsize, wsize, -wsize, wsize, shb->d, shb->clipend, shb->winmat);
|
||||
MTC_Mat4MulMat4(shb->persmat, shb->viewmat, shb->winmat);
|
||||
|
||||
if(lar->buftype==LA_SHADBUF_REGULAR) {
|
||||
|
||||
if(ELEM(lar->buftype, LA_SHADBUF_REGULAR, LA_SHADBUF_HALFWAY)) {
|
||||
/* jitter, weights */
|
||||
shb->jit= give_jitter_tab(shb->samp);
|
||||
make_jitter_weight_tab(shb, lar->filtertype);
|
||||
|
@ -682,7 +682,7 @@ static void zbufline(ZSpan *zspan, int zvlnr, float *vec1, float *vec2)
|
||||
|
||||
static void zbufline_onlyZ(ZSpan *zspan, int zvlnr, float *vec1, float *vec2)
|
||||
{
|
||||
int *rectz;
|
||||
int *rectz, *rectz1= NULL;
|
||||
int start, end, x, y, oldx, oldy, ofs;
|
||||
int dz, vergz, maxtest= 0;
|
||||
float dx, dy;
|
||||
@ -716,6 +716,8 @@ static void zbufline_onlyZ(ZSpan *zspan, int zvlnr, float *vec1, float *vec2)
|
||||
if(vergz>0x50000000 && dz>0) maxtest= 1; // prevent overflow
|
||||
|
||||
rectz= zspan->rectz + oldy*zspan->rectx+ start;
|
||||
if(zspan->rectz1)
|
||||
rectz1= zspan->rectz1 + oldy*zspan->rectx+ start;
|
||||
|
||||
if(dy<0) ofs= -zspan->rectx;
|
||||
else ofs= zspan->rectx;
|
||||
@ -726,18 +728,24 @@ static void zbufline_onlyZ(ZSpan *zspan, int zvlnr, float *vec1, float *vec2)
|
||||
if(y!=oldy) {
|
||||
oldy= y;
|
||||
rectz+= ofs;
|
||||
if(rectz1) rectz1+= ofs;
|
||||
}
|
||||
|
||||
if(x>=0 && y>=0 && y<zspan->recty) {
|
||||
if(vergz<*rectz) {
|
||||
if(vergz < *rectz) {
|
||||
if(rectz1) *rectz1= *rectz;
|
||||
*rectz= vergz;
|
||||
}
|
||||
else if(rectz1 && vergz < *rectz1)
|
||||
*rectz1= vergz;
|
||||
}
|
||||
|
||||
v1[1]+= dy;
|
||||
|
||||
if(maxtest && (vergz > 0x7FFFFFF0 - dz)) vergz= 0x7FFFFFF0;
|
||||
else vergz+= dz;
|
||||
|
||||
if(rectz1) rectz1++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -765,6 +773,8 @@ static void zbufline_onlyZ(ZSpan *zspan, int zvlnr, float *vec1, float *vec2)
|
||||
if(vergz>0x50000000 && dz>0) maxtest= 1; // prevent overflow
|
||||
|
||||
rectz= zspan->rectz + start*zspan->rectx+ oldx;
|
||||
if(zspan->rectz1)
|
||||
rectz1= zspan->rectz1 + start*zspan->rectx+ oldx;
|
||||
|
||||
if(dx<0) ofs= -1;
|
||||
else ofs= 1;
|
||||
@ -775,17 +785,24 @@ static void zbufline_onlyZ(ZSpan *zspan, int zvlnr, float *vec1, float *vec2)
|
||||
if(x!=oldx) {
|
||||
oldx= x;
|
||||
rectz+= ofs;
|
||||
if(rectz1) rectz1+= ofs;
|
||||
}
|
||||
|
||||
if(x>=0 && y>=0 && x<zspan->rectx) {
|
||||
if(vergz<*rectz) {
|
||||
if(vergz < *rectz) {
|
||||
if(rectz1) *rectz1= *rectz;
|
||||
*rectz= vergz;
|
||||
}
|
||||
else if(rectz1 && vergz < *rectz1)
|
||||
*rectz1= vergz;
|
||||
}
|
||||
|
||||
v1[0]+= dx;
|
||||
if(maxtest && (vergz > 0x7FFFFFF0 - dz)) vergz= 0x7FFFFFF0;
|
||||
else vergz+= dz;
|
||||
|
||||
if(rectz1)
|
||||
rectz1+=zspan->rectx;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1183,14 +1200,15 @@ static void zbuffillGL4(ZSpan *zspan, int zvlnr, float *v1, float *v2, float *v3
|
||||
* @param v3 [4 floats, world coordinates] third vertex
|
||||
*/
|
||||
|
||||
/* now: filling two Z values, the closest and 2nd closest */
|
||||
static void zbuffillGL_onlyZ(ZSpan *zspan, int zvlnr, float *v1, float *v2, float *v3, float *v4)
|
||||
{
|
||||
double zxd, zyd, zy0, zverg;
|
||||
float x0,y0,z0;
|
||||
float x1,y1,z1,x2,y2,z2,xx1;
|
||||
float *span1, *span2;
|
||||
int *rz, x, y;
|
||||
int sn1, sn2, rectx, *rectzofs, my0, my2;
|
||||
int *rz, *rz1, x, y;
|
||||
int sn1, sn2, rectx, *rectzofs, *rectzofs1= NULL, my0, my2;
|
||||
|
||||
/* init */
|
||||
zbuf_init_span(zspan);
|
||||
@ -1237,6 +1255,8 @@ static void zbuffillGL_onlyZ(ZSpan *zspan, int zvlnr, float *v1, float *v2, floa
|
||||
/* start-offset in rect */
|
||||
rectx= zspan->rectx;
|
||||
rectzofs= (zspan->rectz+rectx*my2);
|
||||
if(zspan->rectz1)
|
||||
rectzofs1= (zspan->rectz1+rectx*my2);
|
||||
|
||||
/* correct span */
|
||||
sn1= (my0 + my2)/2;
|
||||
@ -1261,20 +1281,30 @@ static void zbuffillGL_onlyZ(ZSpan *zspan, int zvlnr, float *v1, float *v2, floa
|
||||
if(sn2>=sn1) {
|
||||
zverg= (double)sn1*zxd + zy0;
|
||||
rz= rectzofs+sn1;
|
||||
rz1= rectzofs1+sn1;
|
||||
x= sn2-sn1;
|
||||
|
||||
while(x>=0) {
|
||||
if( (int)zverg < *rz) {
|
||||
*rz= (int)zverg;
|
||||
int zvergi= (int)zverg;
|
||||
/* option: maintain two depth values, closest and 2nd closest */
|
||||
if(zvergi < *rz) {
|
||||
if(rectzofs1) *rz1= *rz;
|
||||
*rz= zvergi;
|
||||
}
|
||||
else if(rectzofs1 && zvergi < *rz1)
|
||||
*rz1= zvergi;
|
||||
|
||||
zverg+= zxd;
|
||||
|
||||
rz++;
|
||||
rz1++;
|
||||
x--;
|
||||
}
|
||||
}
|
||||
|
||||
zy0-=zyd;
|
||||
rectzofs-= rectx;
|
||||
if(rectzofs1) rectzofs1-= rectx;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1309,6 +1339,7 @@ static void clippyra(float *labda, float *v1, float *v2, int *b2, int *b3, int a
|
||||
v13= v1[3];
|
||||
}
|
||||
else {
|
||||
/* XXXXX EVIL! this is a R global, whilst this function can be called for shadow, before R was set */
|
||||
dw= R.clipcrop*(v2[3]-v1[3]);
|
||||
v13= R.clipcrop*v1[3];
|
||||
}
|
||||
@ -1425,7 +1456,7 @@ void zbufclip(ZSpan *zspan, int zvlnr, float *f1, float *f2, float *f3, int c1,
|
||||
{
|
||||
float *vlzp[32][3], labda[3][2];
|
||||
float vez[400], *trias[40];
|
||||
|
||||
|
||||
if(c1 | c2 | c3) { /* not in middle */
|
||||
if(c1 & c2 & c3) { /* completely out */
|
||||
return;
|
||||
@ -1445,6 +1476,7 @@ void zbufclip(ZSpan *zspan, int zvlnr, float *f1, float *f2, float *f3, int c1,
|
||||
clipflag[1]= ( (c1 & 3) | (c2 & 3) | (c3 & 3) );
|
||||
clipflag[2]= ( (c1 & 12) | (c2 & 12) | (c3 & 12) );
|
||||
}
|
||||
else clipflag[1]=clipflag[2]= 0;
|
||||
|
||||
for(b=0;b<3;b++) {
|
||||
|
||||
@ -1454,7 +1486,7 @@ void zbufclip(ZSpan *zspan, int zvlnr, float *f1, float *f2, float *f3, int c1,
|
||||
|
||||
for(v=0; v<clvlo; v++) {
|
||||
|
||||
if(vlzp[v][0]!=0) { /* face is still there */
|
||||
if(vlzp[v][0]!=NULL) { /* face is still there */
|
||||
b2= b3 =0; /* clip flags */
|
||||
|
||||
if(b==0) arg= 2;
|
||||
@ -1466,13 +1498,14 @@ void zbufclip(ZSpan *zspan, int zvlnr, float *f1, float *f2, float *f3, int c1,
|
||||
clippyra(labda[2], vlzp[v][2],vlzp[v][0], &b2,&b3, arg);
|
||||
|
||||
if(b2==0 && b3==1) {
|
||||
/* completely 'in' */;
|
||||
/* completely 'in', but we copy because of last for() loop in this section */;
|
||||
vlzp[clvl][0]= vlzp[v][0];
|
||||
vlzp[clvl][1]= vlzp[v][1];
|
||||
vlzp[clvl][2]= vlzp[v][2];
|
||||
vlzp[v][0]= NULL;
|
||||
clvl++;
|
||||
} else if(b3==0) {
|
||||
vlzp[v][0]=0;
|
||||
vlzp[v][0]= NULL;
|
||||
/* completely 'out' */;
|
||||
} else {
|
||||
b1=0;
|
||||
@ -1492,7 +1525,7 @@ void zbufclip(ZSpan *zspan, int zvlnr, float *f1, float *f2, float *f3, int c1,
|
||||
}
|
||||
}
|
||||
|
||||
vlzp[v][0]=0;
|
||||
vlzp[v][0]= NULL;
|
||||
if(b1>2) {
|
||||
for(b3=3; b3<=b1; b3++) {
|
||||
vlzp[clvl][0]= trias[0];
|
||||
@ -1861,11 +1894,15 @@ void zbuffer_shadow(Render *re, LampRen *lar, int *rectz, int size, float jitx,
|
||||
/* the buffers */
|
||||
zspan.rectz= rectz;
|
||||
fillrect(rectz, size, size, 0x7FFFFFFE);
|
||||
if(lar->buftype==LA_SHADBUF_HALFWAY) {
|
||||
zspan.rectz1= MEM_mallocN(size*size*sizeof(int), "seconday z buffer");
|
||||
fillrect(zspan.rectz1, size, size, 0x7FFFFFFE);
|
||||
}
|
||||
|
||||
/* filling methods */
|
||||
zspan.zbuflinefunc= zbufline_onlyZ;
|
||||
zspan.zbuffunc= zbuffillGL_onlyZ;
|
||||
|
||||
|
||||
for(a=0; a<re->totvlak; a++) {
|
||||
|
||||
if((a & 255)==0) vlr= re->blovl[a>>8];
|
||||
@ -1889,6 +1926,15 @@ void zbuffer_shadow(Render *re, LampRen *lar, int *rectz, int size, float jitx,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* merge buffers */
|
||||
if(lar->buftype==LA_SHADBUF_HALFWAY) {
|
||||
for(a=size*size -1; a>=0; a--)
|
||||
rectz[a]= (rectz[a]>>1) + (zspan.rectz1[a]>>1);
|
||||
|
||||
MEM_freeN(zspan.rectz1);
|
||||
}
|
||||
|
||||
zbuf_free_span(&zspan);
|
||||
}
|
||||
|
||||
|
@ -2148,8 +2148,15 @@ static void lamp_panel_spot(Object *ob, Lamp *la)
|
||||
uiDefButBitS(block, TOG, LA_SHAD_RAY, B_SHADRAY,"Ray Shadow",10,180,80,19,&la->mode, 0, 0, 0, 0, "Use ray tracing for shadow");
|
||||
if(la->type==LA_SPOT) {
|
||||
uiDefButBitS(block, TOG, LA_SHAD_BUF, B_SHADBUF, "Buf.Shadow",10,160,80,19,&la->mode, 0, 0, 0, 0, "Lets spotlight produce shadows using shadow buffer");
|
||||
if(la->mode & LA_SHAD_BUF)
|
||||
uiDefButC(block, MENU, B_REDR, "Classical %x0|Irregular %x1", 10,140,80,19,&la->buftype, 0, 0, 0, 0, "Buffer type, Irregular buffer produces sharp shadow always, but doesn't support ZTransp shadow receiving");
|
||||
if(la->mode & LA_SHAD_BUF) {
|
||||
char *tip= "Regular buffer type";
|
||||
if(la->buftype==LA_SHADBUF_IRREGULAR)
|
||||
tip= "Irregular buffer produces sharp shadow always, but it doesn't show up for raytracing";
|
||||
else if(la->buftype==LA_SHADBUF_HALFWAY)
|
||||
tip= "Regular buffer, averaginng the closest and 2nd closest Z value for reducing biasing";
|
||||
|
||||
uiDefButC(block, MENU, B_REDR, "Classical %x0|Classic-Halfway %x2|Irregular %x1", 10,140,80,19,&la->buftype, 0, 0, 0, 0, tip);
|
||||
}
|
||||
}
|
||||
uiBlockEndAlign(block);
|
||||
|
||||
@ -2169,12 +2176,12 @@ static void lamp_panel_spot(Object *ob, Lamp *la)
|
||||
uiDefButF(block, NUMSLI,B_LAMPREDRAW,"HaloInt ", 100,135,200,19,&la->haint, 0.0, 5.0, 0, 0, "Sets the intensity of the spotlight halo");
|
||||
|
||||
if(la->mode & LA_SHAD_BUF) {
|
||||
if(la->buftype==LA_SHADBUF_REGULAR) {
|
||||
if(ELEM(la->buftype, LA_SHADBUF_REGULAR, LA_SHADBUF_HALFWAY)) {
|
||||
uiBlockBeginAlign(block);
|
||||
uiDefButS(block, NUM,B_SBUFF,"ShadowBufferSize:", 100,110,200,19, &la->bufsize,512,10240, 0, 0, "Sets the size of the shadow buffer to nearest multiple of 16");
|
||||
uiDefButS(block, ROW,B_NOP, "Box", 100,90,65,19, &la->filtertype, 0.0, LA_SHADBUF_BOX, 0, 0, "Apply Box filter for shadowbuffer");
|
||||
uiDefButS(block, ROW,B_NOP, "Tent", 165,90,65,19, &la->filtertype, 0.0, LA_SHADBUF_TENT, 0, 0, "Apply Tent filter for shadowbuffer");
|
||||
uiDefButS(block, ROW,B_NOP, "Gauss", 230,90,70,19, &la->filtertype, 0.0, LA_SHADBUF_GAUSS, 0, 0, "Apply Gauss filter for shadowbuffer");
|
||||
uiDefButS(block, ROW,B_NOP, "Box", 100,90,65,19, &la->filtertype, 0.0, LA_SHADBUF_BOX, 0, 0, "Apply Box filter for shadowbuffer samples");
|
||||
uiDefButS(block, ROW,B_NOP, "Tent", 165,90,65,19, &la->filtertype, 0.0, LA_SHADBUF_TENT, 0, 0, "Apply Tent filter for shadowbuffer samples");
|
||||
uiDefButS(block, ROW,B_NOP, "Gauss", 230,90,70,19, &la->filtertype, 0.0, LA_SHADBUF_GAUSS, 0, 0, "Apply Gauss filter for shadowbuffer samples");
|
||||
|
||||
// uiDefButS(block, ROW,B_NOP,"SubSamples: 1", 100,90,140,19, &la->buffers, 1.0, 1.0, 0, 0, "Amount of lampbuffer subsamples, a value of larger than 1 halves the shadowbuffer size");
|
||||
// uiDefButS(block, ROW,B_NOP,"4", 240,90,30,19, &la->buffers, 1.0, 4.0, 0, 0, "Amount of lampbuffer subsamples, this halves the actual shadowbuffer size");
|
||||
@ -2183,7 +2190,7 @@ static void lamp_panel_spot(Object *ob, Lamp *la)
|
||||
uiBlockBeginAlign(block);
|
||||
uiDefButS(block, NUM,B_LAMPREDRAW,"Samples:", 100,60,100,19, &la->samp,1.0,16.0, 0, 0, "Sets the number of shadow map samples");
|
||||
uiDefButS(block, NUM,B_NOP,"Halo step:", 200,60,100,19, &la->shadhalostep, 0.0, 12.0, 0, 0, "Sets the volumetric halo sampling frequency");
|
||||
uiDefButF(block, NUM,B_LAMPREDRAW,"Bias:", 100,40,100,19, &la->bias, 0.01, 5.0, 1, 0, "Sets the shadow map sampling bias");
|
||||
uiDefButF(block, NUM,B_LAMPREDRAW,"Bias:", 100,40,100,19, &la->bias, 0.001, 5.0, 1, 0, "Sets the shadow map sampling bias");
|
||||
uiDefButF(block, NUM,B_LAMPREDRAW,"Soft:", 200,40,100,19, &la->soft,1.0,100.0, 100, 0, "Sets the size of the shadow sample area");
|
||||
}
|
||||
else { /* LA_SHADBUF_IRREGULAR */
|
||||
|
Loading…
Reference in New Issue
Block a user