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>2006-10-15 15:50:46 +0400
committerTon Roosendaal <ton@blender.org>2006-10-15 15:50:46 +0400
commit9fa438b4e94b0d61dde3e535b9d3fbc04db9a10b (patch)
treec99d85cbb02f3b6456e57ab2568fbd85fb4110db /source
parent3b0adf0bf4f7ab61460aadc18ebeef05bb6332d9 (diff)
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.
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/intern/object.c1
-rw-r--r--source/blender/makesdna/DNA_lamp_types.h1
-rw-r--r--source/blender/render/intern/include/zbuf.h1
-rw-r--r--source/blender/render/intern/source/convertblender.c7
-rw-r--r--source/blender/render/intern/source/initrender.c14
-rw-r--r--source/blender/render/intern/source/shadbuf.c7
-rw-r--r--source/blender/render/intern/source/zbuf.c72
-rw-r--r--source/blender/src/buttons_shading.c21
8 files changed, 94 insertions, 30 deletions
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 47654dc15e4..fd0bd47430e 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -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;
}
diff --git a/source/blender/makesdna/DNA_lamp_types.h b/source/blender/makesdna/DNA_lamp_types.h
index bc233b14fa4..22696c48878 100644
--- a/source/blender/makesdna/DNA_lamp_types.h
+++ b/source/blender/makesdna/DNA_lamp_types.h
@@ -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
diff --git a/source/blender/render/intern/include/zbuf.h b/source/blender/render/intern/include/zbuf.h
index ebad8f241f7..cd8ad8626db 100644
--- a/source/blender/render/intern/include/zbuf.h
+++ b/source/blender/render/intern/include/zbuf.h
@@ -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;
diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c
index dc509bfa7d8..aedb5aa13c0 100644
--- a/source/blender/render/intern/source/convertblender.c
+++ b/source/blender/render/intern/source/convertblender.c
@@ -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;
diff --git a/source/blender/render/intern/source/initrender.c b/source/blender/render/intern/source/initrender.c
index 30beae1c467..15e7ff63293 100644
--- a/source/blender/render/intern/source/initrender.c
+++ b/source/blender/render/intern/source/initrender.c
@@ -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;
diff --git a/source/blender/render/intern/source/shadbuf.c b/source/blender/render/intern/source/shadbuf.c
index 2194d202351..73889b6578a 100644
--- a/source/blender/render/intern/source/shadbuf.c
+++ b/source/blender/render/intern/source/shadbuf.c
@@ -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);
diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c
index deb5031ebf3..dc096fc0495 100644
--- a/source/blender/render/intern/source/zbuf.c
+++ b/source/blender/render/intern/source/zbuf.c
@@ -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);
}
diff --git a/source/blender/src/buttons_shading.c b/source/blender/src/buttons_shading.c
index 7798d50a663..c7bfef675ee 100644
--- a/source/blender/src/buttons_shading.c
+++ b/source/blender/src/buttons_shading.c
@@ -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 */