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>2009-10-12 23:41:40 +0400
committerBrecht Van Lommel <brechtvanlommel@pandora.be>2009-10-12 23:41:40 +0400
commit10198e99ff398380696e3408f752280e6bb5106d (patch)
tree834b81d39ae9561ace7b2c607f2015cc03ce7af7 /source/blender/render/intern/source
parentb5f820cd874a7b3ca1de81103b99969429adfd6c (diff)
Deep Shadow Buffer
Since the deep shadow buffer summer of code project is not actively under development anymore, I decided to build my own DSM implementation from scratch, based on reusing as much existing shadow buffer code as possible. It's not very advanced, but implements the basic algorithm. Just enough so we can do shading tests with it, optimizations and other improvements can be done later. Supported: * Classical shadow buffer options: filter, soft, bias, .. * Multiple sample buffers, merged into one. * Halfway trick to support lower bias. * Compression with user defined threshold. * Non-textured alpha transparency, using Casting Alpha value. * Strand render. Not Supported: * Tiling disk cache, so can use a lot of memory. * Per part rendering for lower memory usage during creation. * Colored shadow. * Textured color/alpha shadow. * Mipmaps for faster filtering. * Volume shadows. Usage Hints: * Use sample buffers + smaller size rather than large size. * For example 512 size x 9 sample buffers instead of 2048 x 1. * Compression threshold 0.05 works, but is on the conservative side.
Diffstat (limited to 'source/blender/render/intern/source')
-rw-r--r--source/blender/render/intern/source/convertblender.c4
-rw-r--r--source/blender/render/intern/source/rendercore.c2
-rw-r--r--source/blender/render/intern/source/shadbuf.c488
-rw-r--r--source/blender/render/intern/source/shadeinput.c13
-rw-r--r--source/blender/render/intern/source/strand.c71
-rw-r--r--source/blender/render/intern/source/zbuf.c166
6 files changed, 615 insertions, 129 deletions
diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c
index af7d7a02bba..072083e58a7 100644
--- a/source/blender/render/intern/source/convertblender.c
+++ b/source/blender/render/intern/source/convertblender.c
@@ -3402,9 +3402,10 @@ static void initshadowbuf(Render *re, LampRen *lar, float mat[][4])
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)
+ if(ELEM(lar->buftype, LA_SHADBUF_HALFWAY, LA_SHADBUF_DEEP))
shb->bias= 0.1f*shb->bias;
+ shb->compressthresh= lar->compressthresh;
}
static void area_lamp_vectors(LampRen *lar)
@@ -3486,6 +3487,7 @@ static GroupObject *add_render_lamp(Render *re, Object *ob)
lar->clipend = la->clipend;
lar->bias = la->bias;
+ lar->compressthresh = la->compressthresh;
lar->type= la->type;
lar->mode= la->mode;
diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c
index f3db64295a3..6c18592b8d2 100644
--- a/source/blender/render/intern/source/rendercore.c
+++ b/source/blender/render/intern/source/rendercore.c
@@ -524,7 +524,7 @@ static void add_filt_passes(RenderLayer *rl, int curmask, int rectx, int offset,
case SCE_PASS_RAYHITS:
/* */
- col= &shr->rayhits;
+ col= shr->rayhits;
pixsize= 4;
break;
}
diff --git a/source/blender/render/intern/source/shadbuf.c b/source/blender/render/intern/source/shadbuf.c
index 48305d31e10..50e0321a6eb 100644
--- a/source/blender/render/intern/source/shadbuf.c
+++ b/source/blender/render/intern/source/shadbuf.c
@@ -49,8 +49,8 @@
#include "render_types.h"
#include "renderdatabase.h"
#include "rendercore.h"
-
#include "shadbuf.h"
+#include "shading.h"
#include "zbuf.h"
/* XXX, could be better implemented... this is for endian issues
@@ -166,6 +166,326 @@ static void make_jitter_weight_tab(Render *re, ShadBuf *shb, short filtertype)
}
}
+static int verg_deepsample(const void *poin1, const void *poin2)
+{
+ const DeepSample *ds1= (const DeepSample*)poin1;
+ const DeepSample *ds2= (const DeepSample*)poin2;
+
+ if(ds1->z < ds2->z) return -1;
+ else if(ds1->z == ds2->z) return 0;
+ else return 1;
+}
+
+static int compress_deepsamples(DeepSample *dsample, int tot, float epsilon)
+{
+ /* uses doubles to avoid overflows and other numerical issues,
+ could be improved */
+ DeepSample *ds, *newds;
+ float v;
+ double slope, slopemin, slopemax, min, max, div, newmin, newmax;
+ int a, first, z, newtot= 0;
+
+ /*if(print) {
+ for(a=0, ds=dsample; a<tot; a++, ds++)
+ printf("%lf,%f ", ds->z/(double)0x7FFFFFFF, ds->v);
+ printf("\n");
+ }*/
+
+ /* read from and write into same array */
+ ds= dsample;
+ newds= dsample;
+ a= 0;
+
+ /* as long as we are not at the end of the array */
+ for(a++, ds++; a<tot; a++, ds++) {
+ slopemin= 0.0f;
+ slopemax= 0.0f;
+ first= 1;
+
+ for(; a<tot; a++, ds++) {
+ //dz= ds->z - newds->z;
+ if(ds->z == newds->z) {
+ /* still in same z position, simply check
+ visibility difference against epsilon */
+ if(!(fabs(newds->v - ds->v) <= epsilon)) {
+ break;
+ }
+ }
+ else {
+ /* compute slopes */
+ div= (double)0x7FFFFFFF/((double)ds->z - (double)newds->z);
+ min= ((ds->v - epsilon) - newds->v)*div;
+ max= ((ds->v + epsilon) - newds->v)*div;
+
+ /* adapt existing slopes */
+ if(first) {
+ newmin= min;
+ newmax= max;
+ first= 0;
+ }
+ else {
+ newmin= MAX2(slopemin, min);
+ newmax= MIN2(slopemax, max);
+
+ /* verify if there is still space between the slopes */
+ if(newmin > newmax) {
+ ds--;
+ a--;
+ break;
+ }
+ }
+
+ slopemin= newmin;
+ slopemax= newmax;
+ }
+ }
+
+ if(a == tot) {
+ ds--;
+ a--;
+ }
+
+ /* always previous z */
+ z= ds->z;
+
+ if(first || a==tot-1) {
+ /* if slopes were not initialized, use last visibility */
+ v= ds->v;
+ }
+ else {
+ /* compute visibility at center between slopes at z */
+ slope= (slopemin+slopemax)*0.5;
+ v= newds->v + slope*((z - newds->z)/(double)0x7FFFFFFF);
+ }
+
+ newds++;
+ newtot++;
+
+ newds->z= z;
+ newds->v= v;
+ }
+
+ if(newtot == 0 || (newds->v != (newds-1)->v))
+ newtot++;
+
+ /*if(print) {
+ for(a=0, ds=dsample; a<newtot; a++, ds++)
+ printf("%lf,%f ", ds->z/(double)0x7FFFFFFF, ds->v);
+ printf("\n");
+ }*/
+
+ return newtot;
+}
+
+static float deep_alpha(Render *re, int obinr, int facenr, int strand)
+{
+ ObjectInstanceRen *obi= &re->objectinstance[obinr];
+ Material *ma;
+
+ if(strand) {
+ StrandRen *strand= RE_findOrAddStrand(obi->obr, facenr-1);
+ ma= strand->buffer->ma;
+ }
+ else {
+ VlakRen *vlr= RE_findOrAddVlak(obi->obr, (facenr-1) & RE_QUAD_MASK);
+ ma= vlr->mat;
+ }
+
+ return ma->shad_alpha;
+}
+
+static void compress_deepshadowbuf(Render *re, ShadBuf *shb, APixstr *apixbuf, APixstrand *apixbufstrand)
+{
+ ShadSampleBuf *shsample;
+ DeepSample *ds[RE_MAX_OSA], *sampleds[RE_MAX_OSA], *dsb, *newbuf;
+ APixstr *ap, *apn;
+ APixstrand *aps, *apns;
+ float visibility, totbuf= shb->totbuf;
+ int a, b, c, tot, minz, found, size= shb->size, prevtot, newtot;
+ int sampletot[RE_MAX_OSA], totsample = 0, totsamplec = 0;
+
+ shsample= MEM_callocN( sizeof(ShadSampleBuf), "shad sample buf");
+ BLI_addtail(&shb->buffers, shsample);
+
+ shsample->totbuf= MEM_callocN(sizeof(int)*size*size, "deeptotbuf");
+ shsample->deepbuf= MEM_callocN(sizeof(DeepSample*)*size*size, "deepbuf");
+
+ ap= apixbuf;
+ aps= apixbufstrand;
+ for(a=0; a<size*size; a++, ap++, aps++) {
+ /* count number of samples */
+ for(c=0; c<totbuf; c++)
+ sampletot[c]= 0;
+
+ tot= 0;
+ for(apn=ap; apn; apn=apn->next)
+ for(b=0; b<4; b++)
+ if(apn->p[b])
+ for(c=0; c<totbuf; c++)
+ if(apn->mask[b] & (1<<c))
+ sampletot[c]++;
+
+ if(apixbufstrand) {
+ for(apns=aps; apns; apns=apns->next)
+ for(b=0; b<4; b++)
+ if(apns->p[b])
+ for(c=0; c<totbuf; c++)
+ if(apns->mask[b] & (1<<c))
+ sampletot[c]++;
+ }
+
+ for(c=0; c<totbuf; c++)
+ tot += sampletot[c];
+
+ if(tot == 0) {
+ shsample->deepbuf[a]= NULL;
+ shsample->totbuf[a]= 0;
+ continue;
+ }
+
+ /* fill samples */
+ ds[0]= sampleds[0]= MEM_callocN(sizeof(DeepSample)*tot*2, "deepsample");
+ for(c=1; c<totbuf; c++)
+ ds[c]= sampleds[c]= sampleds[c-1] + sampletot[c-1]*2;
+
+ for(apn=ap; apn; apn=apn->next) {
+ for(b=0; b<4; b++) {
+ if(apn->p[b]) {
+ for(c=0; c<totbuf; c++) {
+ if(apn->mask[b] & (1<<c)) {
+ /* two entries to create step profile */
+ ds[c]->z= apn->z[b];
+ ds[c]->v= 1.0f; /* not used */
+ ds[c]++;
+ ds[c]->z= apn->z[b];
+ ds[c]->v= deep_alpha(re, apn->obi[b], apn->p[b], 0);
+ ds[c]++;
+ }
+ }
+ }
+ }
+ }
+
+ if(apixbufstrand) {
+ for(apns=aps; apns; apns=apns->next) {
+ for(b=0; b<4; b++) {
+ if(apns->p[b]) {
+ for(c=0; c<totbuf; c++) {
+ if(apns->mask[b] & (1<<c)) {
+ /* two entries to create step profile */
+ ds[c]->z= apns->z[b];
+ ds[c]->v= 1.0f; /* not used */
+ ds[c]++;
+ ds[c]->z= apns->z[b];
+ ds[c]->v= deep_alpha(re, apns->obi[b], apns->p[b], 1);
+ ds[c]++;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ for(c=0; c<totbuf; c++) {
+ /* sort by increasing z */
+ qsort(sampleds[c], sampletot[c], sizeof(DeepSample)*2, verg_deepsample);
+
+ /* sum visibility, replacing alpha values */
+ visibility= 1.0f;
+ ds[c]= sampleds[c];
+
+ for(b=0; b<sampletot[c]; b++) {
+ /* two entries creating step profile */
+ ds[c]->v= visibility;
+ ds[c]++;
+
+ visibility *= 1.0f-ds[c]->v;
+ ds[c]->v= visibility;
+ ds[c]++;
+ }
+
+ /* halfway trick, probably won't work well for volumes? */
+ ds[c]= sampleds[c];
+ for(b=0; b<sampletot[c]; b++) {
+ if(b+1 < sampletot[c]) {
+ ds[c]->z= (ds[c]->z>>1) + ((ds[c]+2)->z>>1);
+ ds[c]++;
+ ds[c]->z= (ds[c]->z>>1) + ((ds[c]+2)->z>>1);
+ ds[c]++;
+ }
+ else {
+ ds[c]->z= (ds[c]->z>>1) + (0x7FFFFFFF>>1);
+ ds[c]++;
+ ds[c]->z= (ds[c]->z>>1) + (0x7FFFFFFF>>1);
+ ds[c]++;
+ }
+ }
+
+ /* init for merge loop */
+ ds[c]= sampleds[c];
+ sampletot[c] *= 2;
+ }
+
+ shsample->deepbuf[a]= MEM_callocN(sizeof(DeepSample)*tot*2, "deepsample");
+ shsample->totbuf[a]= 0;
+
+ /* merge buffers */
+ dsb= shsample->deepbuf[a];
+ while(1) {
+ minz= 0;
+ found= 0;
+
+ for(c=0; c<totbuf; c++) {
+ if(sampletot[c] && (!found || ds[c]->z < minz)) {
+ minz= ds[c]->z;
+ found= 1;
+ }
+ }
+
+ if(!found)
+ break;
+
+ dsb->z= minz;
+ dsb->v= 0.0f;
+
+ visibility= 0.0f;
+ for(c=0; c<totbuf; c++) {
+ if(sampletot[c] && ds[c]->z == minz) {
+ ds[c]++;
+ sampletot[c]--;
+ }
+
+ if(sampleds[c] == ds[c])
+ visibility += 1.0f/totbuf;
+ else
+ visibility += (ds[c]-1)->v/totbuf;
+ }
+
+ dsb->v= visibility;
+ dsb++;
+ shsample->totbuf[a]++;
+ }
+
+ prevtot= shsample->totbuf[a];
+ totsample += prevtot;
+
+ newtot= compress_deepsamples(shsample->deepbuf[a], prevtot, shb->compressthresh);
+ shsample->totbuf[a]= newtot;
+ totsamplec += newtot;
+
+ if(newtot < prevtot) {
+ newbuf= MEM_mallocN(sizeof(DeepSample)*newtot, "cdeepsample");
+ memcpy(newbuf, shsample->deepbuf[a], sizeof(DeepSample)*newtot);
+ MEM_freeN(shsample->deepbuf[a]);
+ shsample->deepbuf[a]= newbuf;
+ }
+
+ MEM_freeN(sampleds[0]);
+ }
+
+ //printf("%d -> %d, ratio %f\n", totsample, totsamplec, (float)totsamplec/(float)totsample);
+}
+
/* create Z tiles (for compression): this system is 24 bits!!! */
static void compress_shadowbuf(ShadBuf *shb, int *rectz, int square)
{
@@ -176,7 +496,7 @@ static void compress_shadowbuf(ShadBuf *shb, int *rectz, int square)
int a, x, y, minx, miny, byt1, byt2;
char *rc, *rcline, *ctile, *zt;
- shsample= MEM_mallocN( sizeof(ShadSampleBuf), "shad sample buf");
+ shsample= MEM_callocN( sizeof(ShadSampleBuf), "shad sample buf");
BLI_addtail(&shb->buffers, shsample);
shsample->zbuf= MEM_mallocN( sizeof(uintptr_t)*(size*size)/256, "initshadbuf2");
@@ -277,7 +597,6 @@ static void compress_shadowbuf(ShadBuf *shb, int *rectz, int square)
}
MEM_freeN(rcline);
-
}
/* sets start/end clipping. lar->shb should be initialized */
@@ -381,11 +700,54 @@ static void shadowbuf_autoclip(Render *re, LampRen *lar)
}
}
+static void makeflatshadowbuf(Render *re, LampRen *lar, float *jitbuf)
+{
+ ShadBuf *shb= lar->shb;
+ int *rectz, samples;
+
+ /* zbuffering */
+ rectz= MEM_mapallocN(sizeof(int)*shb->size*shb->size, "makeshadbuf");
+
+ for(samples=0; samples<shb->totbuf; samples++) {
+ zbuffer_shadow(re, shb->persmat, lar, rectz, shb->size, jitbuf[2*samples], jitbuf[2*samples+1]);
+ /* create Z tiles (for compression): this system is 24 bits!!! */
+ compress_shadowbuf(shb, rectz, lar->mode & LA_SQUARE);
+
+ if(re->test_break(re->tbh))
+ break;
+ }
+
+ MEM_freeN(rectz);
+}
+
+static void makedeepshadowbuf(Render *re, LampRen *lar, float *jitbuf)
+{
+ ShadBuf *shb= lar->shb;
+ APixstr *apixbuf;
+ APixstrand *apixbufstrand= NULL;
+ ListBase apsmbase= {NULL, NULL};
+
+ /* zbuffering */
+ apixbuf= MEM_callocN(sizeof(APixstr)*shb->size*shb->size, "APixbuf");
+ if(re->totstrand)
+ apixbufstrand= MEM_callocN(sizeof(APixstrand)*shb->size*shb->size, "APixbufstrand");
+
+ zbuffer_abuf_shadow(re, lar, shb->persmat, apixbuf, apixbufstrand, &apsmbase, shb->size,
+ shb->totbuf, (float(*)[2])jitbuf);
+
+ /* create Z tiles (for compression): this system is 24 bits!!! */
+ compress_deepshadowbuf(re, shb, apixbuf, apixbufstrand);
+
+ MEM_freeN(apixbuf);
+ if(apixbufstrand)
+ MEM_freeN(apixbufstrand);
+ freepsA(&apsmbase);
+}
+
void makeshadowbuf(Render *re, LampRen *lar)
{
ShadBuf *shb= lar->shb;
float wsize, *jitbuf, twozero[2]= {0.0f, 0.0f}, angle, temp;
- int *rectz, samples;
if(lar->bufflag & (LA_SHADBUF_AUTO_START|LA_SHADBUF_AUTO_END))
shadowbuf_autoclip(re, lar);
@@ -405,31 +767,26 @@ void makeshadowbuf(Render *re, LampRen *lar)
i_window(-wsize, wsize, -wsize, wsize, shb->d, shb->clipend, shb->winmat);
Mat4MulMat4(shb->persmat, shb->viewmat, shb->winmat);
- if(ELEM(lar->buftype, LA_SHADBUF_REGULAR, LA_SHADBUF_HALFWAY)) {
+ if(ELEM3(lar->buftype, LA_SHADBUF_REGULAR, LA_SHADBUF_HALFWAY, LA_SHADBUF_DEEP)) {
+ shb->totbuf= lar->buffers;
+
/* jitter, weights - not threadsafe! */
BLI_lock_thread(LOCK_CUSTOM1);
shb->jit= give_jitter_tab(get_render_shadow_samples(&re->r, shb->samp));
make_jitter_weight_tab(re, shb, lar->filtertype);
BLI_unlock_thread(LOCK_CUSTOM1);
- shb->totbuf= lar->buffers;
if(shb->totbuf==4) jitbuf= give_jitter_tab(2);
else if(shb->totbuf==9) jitbuf= give_jitter_tab(3);
else jitbuf= twozero;
/* zbuffering */
- rectz= MEM_mapallocN(sizeof(int)*shb->size*shb->size, "makeshadbuf");
-
- for(samples=0; samples<shb->totbuf; samples++) {
- zbuffer_shadow(re, shb->persmat, lar, rectz, shb->size, jitbuf[2*samples], jitbuf[2*samples+1]);
- /* create Z tiles (for compression): this system is 24 bits!!! */
- compress_shadowbuf(shb, rectz, lar->mode & LA_SQUARE);
-
- if(re->test_break(re->tbh))
- break;
+ if(lar->buftype == LA_SHADBUF_DEEP) {
+ makedeepshadowbuf(re, lar, jitbuf);
+ shb->totbuf= 1;
}
-
- MEM_freeN(rectz);
+ else
+ makeflatshadowbuf(re, lar, jitbuf);
/* printf("lampbuf %d\n", sizeoflampbuf(shb)); */
}
@@ -539,17 +896,27 @@ void freeshadowbuf(LampRen *lar)
ShadSampleBuf *shsample;
int b, v;
- v= (shb->size*shb->size)/256;
-
for(shsample= shb->buffers.first; shsample; shsample= shsample->next) {
- intptr_t *ztile= shsample->zbuf;
- char *ctile= shsample->cbuf;
-
- for(b=0; b<v; b++, ztile++, ctile++)
- if(*ctile) MEM_freeN((void *) *ztile);
-
- MEM_freeN(shsample->zbuf);
- MEM_freeN(shsample->cbuf);
+ if(shsample->deepbuf) {
+ v= shb->size*shb->size;
+ for(b=0; b<v; b++)
+ if(shsample->deepbuf[b])
+ MEM_freeN(shsample->deepbuf[b]);
+
+ MEM_freeN(shsample->deepbuf);
+ MEM_freeN(shsample->totbuf);
+ }
+ else {
+ intptr_t *ztile= shsample->zbuf;
+ char *ctile= shsample->cbuf;
+
+ v= (shb->size*shb->size)/256;
+ for(b=0; b<v; b++, ztile++, ctile++)
+ if(*ctile) MEM_freeN((void *) *ztile);
+
+ MEM_freeN(shsample->zbuf);
+ MEM_freeN(shsample->cbuf);
+ }
}
BLI_freelistN(&shb->buffers);
@@ -567,6 +934,9 @@ static int firstreadshadbuf(ShadBuf *shb, ShadSampleBuf *shsample, int **rz, int
int ofs;
char *ct;
+ if(shsample->deepbuf)
+ return 0;
+
/* always test borders of shadowbuffer */
if(xs<0) xs= 0; else if(xs>=shb->size) xs= shb->size-1;
if(ys<0) ys= 0; else if(ys>=shb->size) ys= shb->size-1;
@@ -587,6 +957,67 @@ static int firstreadshadbuf(ShadBuf *shb, ShadSampleBuf *shsample, int **rz, int
return 0;
}
+static float readdeepvisibility(DeepSample *dsample, int tot, int z, int bias, float *biast)
+{
+ DeepSample *ds, *prevds;
+ float t;
+ int a;
+
+ /* tricky stuff here; we use ints which can overflow easily with bias values */
+
+ ds= dsample;
+ for(a=0; a<tot && (z-bias > ds->z); a++, ds++)
+ ;
+
+ if(a == tot) {
+ if(biast)
+ *biast= 0.0f;
+ return (ds-1)->v; /* completely behind all samples */
+ }
+
+ /* check if this read needs bias blending */
+ if(biast) {
+ if(z > ds->z)
+ *biast= (float)(z - ds->z)/(float)bias;
+ else
+ *biast= 0.0f;
+ }
+
+ if(a == 0)
+ return 1.0f; /* completely in front of all samples */
+
+ prevds= ds-1;
+ t= (float)(z-bias - prevds->z)/(float)(ds->z - prevds->z);
+ return t*ds->v + (1.0f-t)*prevds->v;
+}
+
+static float readdeepshadowbuf(ShadBuf *shb, ShadSampleBuf *shsample, int bias, int xs, int ys, int zs)
+{
+ float v, biasv, biast;
+ int ofs, tot;
+
+ if(zs < - 0x7FFFFE00 + bias)
+ return 1.0; /* extreme close to clipstart */
+
+ /* calc z */
+ ofs= ys*shb->size + xs;
+ tot= shsample->totbuf[ofs];
+ if(tot == 0)
+ return 1.0f;
+
+ v= readdeepvisibility(shsample->deepbuf[ofs], tot, zs, bias, &biast);
+
+ if(biast != 0.0f) {
+ /* in soft bias area */
+ biasv= readdeepvisibility(shsample->deepbuf[ofs], tot, zs, 0, 0);
+
+ biast= biast*biast;
+ return (1.0f-biast)*v + biast*biasv;
+ }
+
+ return v;
+}
+
/* return 1.0 : fully in light */
static float readshadowbuf(ShadBuf *shb, ShadSampleBuf *shsample, int bias, int xs, int ys, int zs)
{
@@ -603,6 +1034,9 @@ static float readshadowbuf(ShadBuf *shb, ShadSampleBuf *shsample, int bias, int
if(xs<0) xs= 0; else if(xs>=shb->size) xs= shb->size-1;
if(ys<0) ys= 0; else if(ys>=shb->size) ys= shb->size-1;
+ if(shsample->deepbuf)
+ return readdeepshadowbuf(shb, shsample, bias, xs, ys, zs);
+
/* calc z */
ofs= (ys>>4)*(shb->size>>4) + (xs>>4);
ct= shsample->cbuf+ofs;
diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c
index 30ff213b95b..79ee6c89460 100644
--- a/source/blender/render/intern/source/shadeinput.c
+++ b/source/blender/render/intern/source/shadeinput.c
@@ -1232,7 +1232,7 @@ void shade_input_set_shade_texco(ShadeInput *shi)
s3= RE_vertren_get_sticky(obr, v3, 0);
if(s1 && s2 && s3) {
- float winmat[4][4], ho1[4], ho2[4], ho3[4];
+ float obwinmat[4][4], winmat[4][4], ho1[4], ho2[4], ho3[4];
float Zmulx, Zmuly;
float hox, hoy, l, dl, u, v;
float s00, s01, s10, s11, detsh;
@@ -1240,14 +1240,15 @@ void shade_input_set_shade_texco(ShadeInput *shi)
/* old globals, localized now */
Zmulx= ((float)R.winx)/2.0f; Zmuly= ((float)R.winy)/2.0f;
+ zbuf_make_winmat(&R, winmat);
if(shi->obi->flag & R_TRANSFORMED)
- zbuf_make_winmat(&R, shi->obi->mat, winmat);
+ Mat4MulMat4(obwinmat, obi->mat, winmat);
else
- zbuf_make_winmat(&R, NULL, winmat);
+ Mat4CpyMat4(obwinmat, winmat);
- zbuf_render_project(winmat, v1->co, ho1);
- zbuf_render_project(winmat, v2->co, ho2);
- zbuf_render_project(winmat, v3->co, ho3);
+ zbuf_render_project(obwinmat, v1->co, ho1);
+ zbuf_render_project(obwinmat, v2->co, ho2);
+ zbuf_render_project(obwinmat, v3->co, ho3);
s00= ho3[0]/ho3[3] - ho1[0]/ho1[3];
s01= ho3[1]/ho3[3] - ho1[1]/ho1[3];
diff --git a/source/blender/render/intern/source/strand.c b/source/blender/render/intern/source/strand.c
index d00076a80e8..61080c7d807 100644
--- a/source/blender/render/intern/source/strand.c
+++ b/source/blender/render/intern/source/strand.c
@@ -417,6 +417,8 @@ typedef struct StrandPart {
intptr_t *rectdaps;
int rectx, recty;
int sample;
+ int shadow;
+ float (*jit)[2];
StrandSegment *segment;
float t[3], s[3];
@@ -525,7 +527,7 @@ static void do_strand_fillac(void *handle, int x, int y, float u, float v, float
}
}
else {
- bufferz= spart->rectz[offset];
+ bufferz= (spart->rectz)? spart->rectz[offset]: 0x7FFFFFFF;
if(spart->rectmask)
maskz= spart->rectmask[offset];
}
@@ -560,8 +562,10 @@ static void do_strand_fillac(void *handle, int x, int y, float u, float v, float
CHECK_ASSIGN(0);
}
- strand_shade_refcount(cache, sseg->v[1]);
- strand_shade_refcount(cache, sseg->v[2]);
+ if(cache) {
+ strand_shade_refcount(cache, sseg->v[1]);
+ strand_shade_refcount(cache, sseg->v[2]);
+ }
spart->totapixbuf[offset]++;
}
}
@@ -596,23 +600,16 @@ static void do_scanconvert_strand(Render *re, StrandPart *spart, ZSpan *zspan, f
VECCOPY(jco3, co3);
VECCOPY(jco4, co4);
- if(re->osa) {
- jx= -re->jit[sample][0];
- jy= -re->jit[sample][1];
+ if(spart->jit) {
+ jx= -spart->jit[sample][0];
+ jy= -spart->jit[sample][1];
jco1[0] += jx; jco1[1] += jy;
jco2[0] += jx; jco2[1] += jy;
jco3[0] += jx; jco3[1] += jy;
jco4[0] += jx; jco4[1] += jy;
- }
- else if(re->i.curblur) {
- jx= -re->jit[re->i.curblur-1][0];
- jy= -re->jit[re->i.curblur-1][1];
- jco1[0] += jx; jco1[1] += jy;
- jco2[0] += jx; jco2[1] += jy;
- jco3[0] += jx; jco3[1] += jy;
- jco4[0] += jx; jco4[1] += jy;
+ /* XXX mblur? */
}
spart->sample= sample;
@@ -756,7 +753,7 @@ void render_strand_segment(Render *re, float winmat[][4], StrandPart *spart, ZSp
}
/* render call to fill in strands */
-int zbuffer_strands_abuf(Render *re, RenderPart *pa, RenderLayer *rl, APixstrand *apixbuf, ListBase *apsmbase, StrandShadeCache *cache)
+int zbuffer_strands_abuf(Render *re, RenderPart *pa, APixstrand *apixbuf, ListBase *apsmbase, unsigned int lay, int negzmask, float winmat[][4], int winx, int winy, int sample, float (*jit)[2], float clipcrop, int shadow, StrandShadeCache *cache)
{
ObjectRen *obr;
ObjectInstanceRen *obi;
@@ -768,7 +765,7 @@ int zbuffer_strands_abuf(Render *re, RenderPart *pa, RenderLayer *rl, APixstrand
StrandSegment sseg;
StrandSortSegment *sortsegments = NULL, *sortseg, *firstseg;
MemArena *memarena;
- float z[4], bounds[4], winmat[4][4];
+ float z[4], bounds[4], obwinmat[4][4];
int a, b, c, i, totsegment, clip[4];
if(re->test_break(re->tbh))
@@ -788,27 +785,31 @@ int zbuffer_strands_abuf(Render *re, RenderPart *pa, RenderLayer *rl, APixstrand
spart.rectz= pa->rectz;
spart.rectmask= pa->rectmask;
spart.cache= cache;
+ spart.shadow= shadow;
+ spart.jit= jit;
- zbuf_alloc_span(&zspan, pa->rectx, pa->recty, re->clipcrop);
+ zbuf_alloc_span(&zspan, pa->rectx, pa->recty, clipcrop);
/* needed for transform from hoco to zbuffer co */
- zspan.zmulx= ((float)re->winx)/2.0;
- zspan.zmuly= ((float)re->winy)/2.0;
+ zspan.zmulx= ((float)winx)/2.0;
+ zspan.zmuly= ((float)winy)/2.0;
zspan.zofsx= -pa->disprect.xmin;
zspan.zofsy= -pa->disprect.ymin;
/* to center the sample position */
- zspan.zofsx -= 0.5f;
- zspan.zofsy -= 0.5f;
+ if(!shadow) {
+ zspan.zofsx -= 0.5f;
+ zspan.zofsy -= 0.5f;
+ }
zspan.apsmbase= apsmbase;
/* clipping setup */
- bounds[0]= (2*pa->disprect.xmin - re->winx-1)/(float)re->winx;
- bounds[1]= (2*pa->disprect.xmax - re->winx+1)/(float)re->winx;
- bounds[2]= (2*pa->disprect.ymin - re->winy-1)/(float)re->winy;
- bounds[3]= (2*pa->disprect.ymax - re->winy+1)/(float)re->winy;
+ bounds[0]= (2*pa->disprect.xmin - winx-1)/(float)winx;
+ bounds[1]= (2*pa->disprect.xmax - winx+1)/(float)winx;
+ bounds[2]= (2*pa->disprect.ymin - winy-1)/(float)winy;
+ bounds[3]= (2*pa->disprect.ymax - winy+1)/(float)winy;
memarena= BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE);
firstseg= NULL;
@@ -819,14 +820,14 @@ int zbuffer_strands_abuf(Render *re, RenderPart *pa, RenderLayer *rl, APixstrand
for(obi=re->instancetable.first, i=0; obi; obi=obi->next, i++) {
obr= obi->obr;
- if(!obr->strandbuf || !(obr->strandbuf->lay & rl->lay))
+ if(!obr->strandbuf || !(obr->strandbuf->lay & lay))
continue;
/* compute matrix and try clipping whole object */
if(obi->flag & R_TRANSFORMED)
- zbuf_make_winmat(re, obi->mat, winmat);
+ Mat4MulMat4(obwinmat, obi->mat, winmat);
else
- zbuf_make_winmat(re, NULL, winmat);
+ Mat4CpyMat4(obwinmat, winmat);
if(clip_render_object(obi->obr->boundbox, bounds, winmat))
continue;
@@ -843,14 +844,14 @@ int zbuffer_strands_abuf(Render *re, RenderPart *pa, RenderLayer *rl, APixstrand
svert= strand->vert;
/* keep clipping and z depth for 4 control points */
- clip[1]= strand_test_clip(winmat, &zspan, bounds, svert->co, &z[1]);
- clip[2]= strand_test_clip(winmat, &zspan, bounds, (svert+1)->co, &z[2]);
+ clip[1]= strand_test_clip(obwinmat, &zspan, bounds, svert->co, &z[1]);
+ clip[2]= strand_test_clip(obwinmat, &zspan, bounds, (svert+1)->co, &z[2]);
clip[0]= clip[1]; z[0]= z[1];
for(b=0; b<strand->totvert-1; b++, svert++) {
/* compute 4th point clipping and z depth */
if(b < strand->totvert-2) {
- clip[3]= strand_test_clip(winmat, &zspan, bounds, (svert+2)->co, &z[3]);
+ clip[3]= strand_test_clip(obwinmat, &zspan, bounds, (svert+2)->co, &z[3]);
}
else {
clip[3]= clip[2]; z[3]= z[2];
@@ -900,7 +901,11 @@ int zbuffer_strands_abuf(Render *re, RenderPart *pa, RenderLayer *rl, APixstrand
obi= &re->objectinstance[sortseg->obi];
obr= obi->obr;
- zbuf_make_winmat(re, NULL, winmat);
+
+ if(obi->flag & R_TRANSFORMED)
+ Mat4MulMat4(obwinmat, obi->mat, winmat);
+ else
+ Mat4CpyMat4(obwinmat, winmat);
sseg.obi= obi;
sseg.strand= RE_findOrAddStrand(obr, sortseg->strand);
@@ -917,7 +922,7 @@ int zbuffer_strands_abuf(Render *re, RenderPart *pa, RenderLayer *rl, APixstrand
spart.segment= &sseg;
- render_strand_segment(re, winmat, &spart, &zspan, 1, &sseg);
+ render_strand_segment(re, obwinmat, &spart, &zspan, 1, &sseg);
}
}
diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c
index 3b3a8568933..a7b9867715f 100644
--- a/source/blender/render/intern/source/zbuf.c
+++ b/source/blender/render/intern/source/zbuf.c
@@ -271,7 +271,7 @@ static APixstr *addpsmainA(ListBase *lb)
return psm->ps;
}
-static void freepsA(ListBase *lb)
+void freepsA(ListBase *lb)
{
APixstrMain *psm, *psmnext;
@@ -1760,12 +1760,12 @@ static int zbuf_shadow_project(ZbufProjectCache *cache, int index, float winmat[
}
}
-static void zbuffer_part_bounds(Render *re, RenderPart *pa, float *bounds)
+static void zbuffer_part_bounds(int winx, int winy, RenderPart *pa, float *bounds)
{
- bounds[0]= (2*pa->disprect.xmin - re->winx-1)/(float)re->winx;
- bounds[1]= (2*pa->disprect.xmax - re->winx+1)/(float)re->winx;
- bounds[2]= (2*pa->disprect.ymin - re->winy-1)/(float)re->winy;
- bounds[3]= (2*pa->disprect.ymax - re->winy+1)/(float)re->winy;
+ bounds[0]= (2*pa->disprect.xmin - winx-1)/(float)winx;
+ bounds[1]= (2*pa->disprect.xmax - winx+1)/(float)winx;
+ bounds[2]= (2*pa->disprect.ymin - winy-1)/(float)winy;
+ bounds[3]= (2*pa->disprect.ymax - winy+1)/(float)winy;
}
static int zbuf_part_project(ZbufProjectCache *cache, int index, float winmat[][4], float *bounds, float *co, float *ho)
@@ -1803,7 +1803,7 @@ void zbuf_render_project(float winmat[][4], float *co, float *ho)
projectvert(vec, winmat, ho);
}
-void zbuf_make_winmat(Render *re, float duplimat[][4], float winmat[][4])
+void zbuf_make_winmat(Render *re, float winmat[][4])
{
float panomat[4][4];
@@ -1814,13 +1814,8 @@ void zbuf_make_winmat(Render *re, float duplimat[][4], float winmat[][4])
panomat[2][0]= -re->panosi;
panomat[2][2]= re->panoco;
- if(duplimat)
- Mat4MulSerie(winmat, re->winmat, panomat, duplimat, 0, 0, 0, 0, 0);
- else
- Mat4MulMat4(winmat, panomat, re->winmat);
+ Mat4MulMat4(winmat, panomat, re->winmat);
}
- else if(duplimat)
- Mat4MulMat4(winmat, duplimat, re->winmat);
else
Mat4CpyMat4(winmat, re->winmat);
}
@@ -2047,12 +2042,15 @@ void zbuffer_solid(RenderPart *pa, RenderLayer *rl, void(*fillfunc)(RenderPart*,
Material *ma=0;
ObjectInstanceRen *obi;
ObjectRen *obr;
- float winmat[4][4], bounds[4], ho1[4], ho2[4], ho3[4], ho4[4]={0};
+ float obwinmat[4][4], winmat[4][4], bounds[4];
+ float ho1[4], ho2[4], ho3[4], ho4[4]={0};
unsigned int lay= rl->lay, lay_zmask= rl->lay_zmask;
int i, v, zvlnr, zsample, samples, c1, c2, c3, c4=0;
short nofill=0, env=0, wire=0, zmaskpass=0;
short all_z= (rl->layflag & SCE_LAY_ALL_Z) && !(rl->layflag & SCE_LAY_ZMASK);
short neg_zmask= (rl->layflag & SCE_LAY_ZMASK) && (rl->layflag & SCE_LAY_NEG_ZMASK);
+
+ zbuf_make_winmat(&R, winmat);
samples= (R.osa? R.osa: 1);
samples= MIN2(4, samples-pa->sample);
@@ -2060,7 +2058,7 @@ void zbuffer_solid(RenderPart *pa, RenderLayer *rl, void(*fillfunc)(RenderPart*,
for(zsample=0; zsample<samples; zsample++) {
zspan= &zspans[zsample];
- zbuffer_part_bounds(&R, pa, bounds);
+ zbuffer_part_bounds(R.winx, R.winy, pa, bounds);
zbuf_alloc_span(zspan, pa->rectx, pa->recty, R.clipcrop);
/* needed for transform from hoco to zbuffer co */
@@ -2135,9 +2133,9 @@ void zbuffer_solid(RenderPart *pa, RenderLayer *rl, void(*fillfunc)(RenderPart*,
continue;
if(obi->flag & R_TRANSFORMED)
- zbuf_make_winmat(&R, obi->mat, winmat);
+ Mat4MulMat4(obwinmat, obi->mat, winmat);
else
- zbuf_make_winmat(&R, NULL, winmat);
+ Mat4CpyMat4(obwinmat, winmat);
if(clip_render_object(obi->obr->boundbox, bounds, winmat))
continue;
@@ -2182,14 +2180,14 @@ void zbuffer_solid(RenderPart *pa, RenderLayer *rl, void(*fillfunc)(RenderPart*,
v3= vlr->v3;
v4= vlr->v4;
- c1= zbuf_part_project(cache, v1->index, winmat, bounds, v1->co, ho1);
- c2= zbuf_part_project(cache, v2->index, winmat, bounds, v2->co, ho2);
- c3= zbuf_part_project(cache, v3->index, winmat, bounds, v3->co, ho3);
+ c1= zbuf_part_project(cache, v1->index, obwinmat, bounds, v1->co, ho1);
+ c2= zbuf_part_project(cache, v2->index, obwinmat, bounds, v2->co, ho2);
+ c3= zbuf_part_project(cache, v3->index, obwinmat, bounds, v3->co, ho3);
/* partclipping doesn't need viewplane clipping */
partclip= c1 & c2 & c3;
if(v4) {
- c4= zbuf_part_project(cache, v4->index, winmat, bounds, v4->co, ho4);
+ c4= zbuf_part_project(cache, v4->index, obwinmat, bounds, v4->co, ho4);
partclip &= c4;
}
@@ -2511,11 +2509,13 @@ void zbuffer_sss(RenderPart *pa, unsigned int lay, void *handle, void (*func)(vo
VlakRen *vlr= NULL;
VertRen *v1, *v2, *v3, *v4;
Material *ma=0, *sss_ma= R.sss_mat;
- float winmat[4][4], bounds[4], ho1[4], ho2[4], ho3[4], ho4[4]={0};
+ float obwinmat[4][4], winmat[4][4], bounds[4];
+ float ho1[4], ho2[4], ho3[4], ho4[4]={0};
int i, v, zvlnr, c1, c2, c3, c4=0;
short nofill=0, env=0, wire=0;
- zbuffer_part_bounds(&R, pa, bounds);
+ zbuf_make_winmat(&R, winmat);
+ zbuffer_part_bounds(R.winx, R.winy, pa, bounds);
zbuf_alloc_span(&zspan, pa->rectx, pa->recty, R.clipcrop);
zspan.sss_handle= handle;
@@ -2551,9 +2551,9 @@ void zbuffer_sss(RenderPart *pa, unsigned int lay, void *handle, void (*func)(vo
continue;
if(obi->flag & R_TRANSFORMED)
- zbuf_make_winmat(&R, obi->mat, winmat);
+ Mat4MulMat4(obwinmat, obi->mat, winmat);
else
- zbuf_make_winmat(&R, NULL, winmat);
+ Mat4CpyMat4(obwinmat, winmat);
if(clip_render_object(obi->obr->boundbox, bounds, winmat))
continue;
@@ -3181,6 +3181,11 @@ static void copyto_abufz(RenderPart *pa, int *arectz, int *rectmask, int sample)
int x, y, *rza, *rma;
intptr_t *rd;
+ if((R.osa==0 && !pa->rectz) || !pa->rectdaps) {
+ fillrect(arectz, pa->rectx, pa->recty, 0x7FFFFFFE);
+ return;
+ }
+
if(R.osa==0) {
memcpy(arectz, pa->rectz, sizeof(int)*pa->rectx*pa->recty);
if(rectmask && pa->rectmask)
@@ -3222,7 +3227,7 @@ static void copyto_abufz(RenderPart *pa, int *arectz, int *rectmask, int sample)
* Do accumulation z buffering.
*/
-static int zbuffer_abuf(RenderPart *pa, APixstr *APixbuf, ListBase *apsmbase, RenderLayer *rl, unsigned int lay)
+static int zbuffer_abuf(Render *re, RenderPart *pa, APixstr *APixbuf, ListBase *apsmbase, unsigned int lay, int negzmask, float winmat[][4], int winx, int winy, int samples, float (*jit)[2], float clipcrop, int shadow)
{
ZbufProjectCache cache[ZBUF_PROJECT_CACHE_SIZE];
ZSpan zspans[16], *zspan; /* MAX_OSA */
@@ -3232,28 +3237,27 @@ static int zbuffer_abuf(RenderPart *pa, APixstr *APixbuf, ListBase *apsmbase, Re
VlakRen *vlr=NULL;
VertRen *v1, *v2, *v3, *v4;
float vec[3], hoco[4], mul, zval, fval;
- float winmat[4][4], bounds[4], ho1[4], ho2[4], ho3[4], ho4[4]={0};
+ float obwinmat[4][4], bounds[4], ho1[4], ho2[4], ho3[4], ho4[4]={0};
int i, v, zvlnr, c1, c2, c3, c4=0, dofill= 0;
- int zsample, samples, polygon_offset;
+ int zsample, polygon_offset;
- zbuffer_part_bounds(&R, pa, bounds);
- samples= (R.osa? R.osa: 1);
+ zbuffer_part_bounds(winx, winy, pa, bounds);
for(zsample=0; zsample<samples; zsample++) {
zspan= &zspans[zsample];
- zbuf_alloc_span(zspan, pa->rectx, pa->recty, R.clipcrop);
+ zbuf_alloc_span(zspan, pa->rectx, pa->recty, re->clipcrop);
/* needed for transform from hoco to zbuffer co */
- zspan->zmulx= ((float)R.winx)/2.0;
- zspan->zmuly= ((float)R.winy)/2.0;
+ zspan->zmulx= ((float)winx)/2.0;
+ zspan->zmuly= ((float)winy)/2.0;
/* the buffers */
zspan->arectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "Arectz");
zspan->apixbuf= APixbuf;
zspan->apsmbase= apsmbase;
- if((rl->layflag & SCE_LAY_ZMASK) && (rl->layflag & SCE_LAY_NEG_ZMASK))
+ if(negzmask)
zspan->rectmask= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "Arectmask");
/* filling methods */
@@ -3263,36 +3267,35 @@ static int zbuffer_abuf(RenderPart *pa, APixstr *APixbuf, ListBase *apsmbase, Re
copyto_abufz(pa, zspan->arectz, zspan->rectmask, zsample); /* init zbuffer */
zspan->mask= 1<<zsample;
- if(R.osa) {
- zspan->zofsx= -pa->disprect.xmin - R.jit[zsample][0];
- zspan->zofsy= -pa->disprect.ymin - R.jit[zsample][1];
- }
- else if(R.i.curblur) {
- zspan->zofsx= -pa->disprect.xmin - R.jit[R.i.curblur-1][0];
- zspan->zofsy= -pa->disprect.ymin - R.jit[R.i.curblur-1][1];
+ if(jit) {
+ zspan->zofsx= -pa->disprect.xmin + jit[zsample][0];
+ zspan->zofsy= -pa->disprect.ymin + jit[zsample][1];
}
else {
zspan->zofsx= -pa->disprect.xmin;
zspan->zofsy= -pa->disprect.ymin;
}
- /* to center the sample position */
- zspan->zofsx -= 0.5f;
- zspan->zofsy -= 0.5f;
+
+ if(!shadow) {
+ /* to center the sample position */
+ zspan->zofsx -= 0.5f;
+ zspan->zofsy -= 0.5f;
+ }
}
/* we use this to test if nothing was filled in */
zvlnr= 0;
- for(i=0, obi=R.instancetable.first; obi; i++, obi=obi->next) {
+ for(i=0, obi=re->instancetable.first; obi; i++, obi=obi->next) {
obr= obi->obr;
if(!(obi->lay & lay))
continue;
if(obi->flag & R_TRANSFORMED)
- zbuf_make_winmat(&R, obi->mat, winmat);
+ Mat4MulMat4(obwinmat, obi->mat, winmat);
else
- zbuf_make_winmat(&R, NULL, winmat);
+ Mat4CpyMat4(obwinmat, winmat);
if(clip_render_object(obi->obr->boundbox, bounds, winmat))
continue;
@@ -3306,7 +3309,7 @@ static int zbuffer_abuf(RenderPart *pa, APixstr *APixbuf, ListBase *apsmbase, Re
if(vlr->mat!=ma) {
ma= vlr->mat;
- dofill= ((ma->mode & MA_TRANSP) && (ma->mode & MA_ZTRANSP)) && !(ma->mode & MA_ONLYCAST);
+ dofill= shadow || (((ma->mode & MA_TRANSP) && (ma->mode & MA_ZTRANSP)) && !(ma->mode & MA_ONLYCAST));
}
if(dofill) {
@@ -3318,27 +3321,27 @@ static int zbuffer_abuf(RenderPart *pa, APixstr *APixbuf, ListBase *apsmbase, Re
v3= vlr->v3;
v4= vlr->v4;
- c1= zbuf_part_project(cache, v1->index, winmat, bounds, v1->co, ho1);
- c2= zbuf_part_project(cache, v2->index, winmat, bounds, v2->co, ho2);
- c3= zbuf_part_project(cache, v3->index, winmat, bounds, v3->co, ho3);
+ c1= zbuf_part_project(cache, v1->index, obwinmat, bounds, v1->co, ho1);
+ c2= zbuf_part_project(cache, v2->index, obwinmat, bounds, v2->co, ho2);
+ c3= zbuf_part_project(cache, v3->index, obwinmat, bounds, v3->co, ho3);
/* partclipping doesn't need viewplane clipping */
partclip= c1 & c2 & c3;
if(v4) {
- c4= zbuf_part_project(cache, v4->index, winmat, bounds, v4->co, ho4);
+ c4= zbuf_part_project(cache, v4->index, obwinmat, bounds, v4->co, ho4);
partclip &= c4;
}
if(partclip==0) {
/* a little advantage for transp rendering (a z offset) */
- if( ma->zoffs != 0.0) {
+ if(!shadow && ma->zoffs != 0.0) {
mul= 0x7FFFFFFF;
zval= mul*(1.0+ho1[2]/ho1[3]);
VECCOPY(vec, v1->co);
/* z is negative, otherwise its being clipped */
vec[2]-= ma->zoffs;
- projectverto(vec, R.winmat, hoco);
+ projectverto(vec, obwinmat, hoco);
fval= mul*(1.0+hoco[2]/hoco[3]);
polygon_offset= (int) fabs(zval - fval );
@@ -3376,13 +3379,13 @@ static int zbuffer_abuf(RenderPart *pa, APixstr *APixbuf, ListBase *apsmbase, Re
}
}
if((v & 255)==255)
- if(R.test_break(R.tbh))
+ if(re->test_break(re->tbh))
break;
}
}
}
- if(R.test_break(R.tbh)) break;
+ if(re->test_break(re->tbh)) break;
}
for(zsample=0; zsample<samples; zsample++) {
@@ -3396,6 +3399,51 @@ static int zbuffer_abuf(RenderPart *pa, APixstr *APixbuf, ListBase *apsmbase, Re
return zvlnr;
}
+static int zbuffer_abuf_render(RenderPart *pa, APixstr *APixbuf, APixstrand *APixbufstrand, ListBase *apsmbase, RenderLayer *rl, StrandShadeCache *sscache)
+{
+ float winmat[4][4], (*jit)[2];
+ int samples, negzmask, doztra= 0;
+
+ samples= (R.osa)? R.osa: 1;
+ negzmask= ((rl->layflag & SCE_LAY_ZMASK) && (rl->layflag & SCE_LAY_NEG_ZMASK));
+
+ if(R.osa)
+ jit= R.jit;
+ else if(R.i.curblur)
+ jit= &R.jit[R.i.curblur-1];
+ else
+ jit= NULL;
+
+ zbuf_make_winmat(&R, winmat);
+
+ if(rl->layflag & SCE_LAY_ZTRA)
+ doztra+= zbuffer_abuf(&R, pa, APixbuf, apsmbase, rl->lay, negzmask, winmat, R.winx, R.winy, samples, jit, R.clipcrop, 0);
+ if((rl->layflag & SCE_LAY_STRAND) && APixbufstrand)
+ doztra+= zbuffer_strands_abuf(&R, pa, APixbufstrand, apsmbase, rl->lay, negzmask, winmat, R.winx, R.winy, samples, jit, R.clipcrop, 0, sscache);
+
+ return doztra;
+}
+
+void zbuffer_abuf_shadow(Render *re, LampRen *lar, float winmat[][4], APixstr *APixbuf, APixstrand *APixbufstrand, ListBase *apsmbase, int size, int samples, float (*jit)[2])
+{
+ RenderPart pa;
+ int lay= -1;
+
+ if(lar->mode & LA_LAYER) lay= lar->lay;
+
+ memset(&pa, 0, sizeof(RenderPart));
+ pa.rectx= size;
+ pa.recty= size;
+ pa.disprect.xmin= 0;
+ pa.disprect.ymin= 0;
+ pa.disprect.xmax= size;
+ pa.disprect.ymax= size;
+
+ zbuffer_abuf(re, &pa, APixbuf, apsmbase, lay, 0, winmat, size, size, samples, jit, 1.0f, 1);
+ if(APixbufstrand)
+ zbuffer_strands_abuf(re, &pa, APixbufstrand, apsmbase, lay, 0, winmat, size, size, samples, jit, 1.0f, 1, NULL);
+}
+
/* different rules for speed in transparent pass... */
/* speed pointer NULL = sky, we clear */
/* else if either alpha is full or no solid was filled in: copy speed */
@@ -3902,11 +3950,7 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas
sampalpha= 1.0f;
/* fill the Apixbuf */
- doztra= 0;
- if(rl->layflag & SCE_LAY_ZTRA)
- doztra+= zbuffer_abuf(pa, APixbuf, &apsmbase, rl, rl->lay);
- if((rl->layflag & SCE_LAY_STRAND) && APixbufstrand)
- doztra+= zbuffer_strands_abuf(&R, pa, rl, APixbufstrand, &apsmbase, sscache);
+ doztra= zbuffer_abuf_render(pa, APixbuf, APixbufstrand, &apsmbase, rl, sscache);
if(doztra == 0) {
/* nothing filled in */