Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>2008-01-28 19:54:52 +0300
committerBrecht Van Lommel <brechtvanlommel@pandora.be>2008-01-28 19:54:52 +0300
commitf25d2dbb411a2eb6095a53893759a3fc29904ffd (patch)
tree6231d841fd896af26868682a8534854feb32edec
parent703f248ab4bd918ba6a202a20b73dc6293851759 (diff)
Strands now mix together correctly with ZTransp.
They now also store a list of samples per pixel, and then get shaded together with the ztransp samples. This comes with a slight speed hit, but mainly memory might be a concern. However, testing some peach scenes I haven't problems.
-rw-r--r--source/blender/render/intern/include/render_types.h8
-rw-r--r--source/blender/render/intern/include/rendercore.h2
-rw-r--r--source/blender/render/intern/include/strand.h9
-rw-r--r--source/blender/render/intern/include/zbuf.h18
-rw-r--r--source/blender/render/intern/source/envmap.c2
-rw-r--r--source/blender/render/intern/source/rendercore.c73
-rw-r--r--source/blender/render/intern/source/renderdatabase.c58
-rw-r--r--source/blender/render/intern/source/strand.c945
-rw-r--r--source/blender/render/intern/source/zbuf.c157
9 files changed, 477 insertions, 795 deletions
diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h
index de5c5485004..3a8a491a852 100644
--- a/source/blender/render/intern/include/render_types.h
+++ b/source/blender/render/intern/include/render_types.h
@@ -176,7 +176,6 @@ struct Render
ListBase lampren; /* storage, for free */
ListBase objecttable;
- struct RenderBuckets *strandbuckets;
struct ObjectInstanceRen *objectinstance;
ListBase instancetable;
@@ -334,6 +333,8 @@ typedef struct HaloRen
struct Material *mat;
} HaloRen;
+/* ------------------------------------------------------------------------- */
+
typedef struct StrandVert {
float co[3];
float strandco;
@@ -351,6 +352,11 @@ typedef struct StrandSurface {
int totvert, totface;
} StrandSurface;
+typedef struct StrandBound {
+ int start, end;
+ float bbox[2][3];
+} StrandBound;
+
typedef struct StrandBuffer {
struct StrandBuffer *next, *prev;
struct StrandVert *vert;
diff --git a/source/blender/render/intern/include/rendercore.h b/source/blender/render/intern/include/rendercore.h
index d569028fc50..4ca644c6381 100644
--- a/source/blender/render/intern/include/rendercore.h
+++ b/source/blender/render/intern/include/rendercore.h
@@ -91,8 +91,6 @@ void zbufshadeDA_tile(struct RenderPart *pa);
void zbufshade_sss_tile(struct RenderPart *pa);
-void addps(struct ListBase *lb, long *rd, int obi, int facenr, int z, unsigned short mask);
-
int get_sample_layers(struct RenderPart *pa, struct RenderLayer *rl, struct RenderLayer **rlpp);
diff --git a/source/blender/render/intern/include/strand.h b/source/blender/render/intern/include/strand.h
index 8e34fa27342..f001bc42112 100644
--- a/source/blender/render/intern/include/strand.h
+++ b/source/blender/render/intern/include/strand.h
@@ -88,13 +88,20 @@ typedef struct StrandSegment {
int shaded;
} StrandSegment;
+struct StrandShadeCache;
+typedef struct StrandShadeCache StrandShadeCache;
+
void strand_eval_point(StrandSegment *sseg, StrandPoint *spoint);
void render_strand_segment(struct Render *re, float winmat[][4], struct StrandPart *spart, struct ZSpan *zspan, int totzspan, StrandSegment *sseg);
-void project_strands(Render *re, void (*projectfunc)(float *, float mat[][4], float *), int do_pano, int do_buckets);
struct StrandSurface *cache_strand_surface(struct Render *re, struct ObjectRen *obr, struct DerivedMesh *dm, float mat[][4], int timeoffset);
void free_strand_surface(struct Render *re);
+struct StrandShadeCache *strand_shade_cache_create(void);
+void strand_shade_cache_free(struct StrandShadeCache *cache);
+void strand_shade_segment(struct Render *re, struct StrandShadeCache *cache, struct StrandSegment *sseg, struct ShadeSample *ssamp, float t, float s, int addpassflag);
+void strand_shade_unref(struct StrandShadeCache *cache, struct StrandVert *svert);
+
struct RenderBuckets *init_buckets(struct Render *re);
void add_buckets_primitive(struct RenderBuckets *buckets, float *min, float *max, void *prim);
void free_buckets(struct RenderBuckets *buckets);
diff --git a/source/blender/render/intern/include/zbuf.h b/source/blender/render/intern/include/zbuf.h
index 8feb18a7ab8..2a16bde829b 100644
--- a/source/blender/render/intern/include/zbuf.h
+++ b/source/blender/render/intern/include/zbuf.h
@@ -36,6 +36,8 @@ struct LampRen;
struct VlakRen;
struct ListBase;
struct ZSpan;
+struct APixstrand;
+struct StrandShadeCache;
void fillrect(int *rect, int x, int y, int val);
@@ -51,9 +53,9 @@ void zbuffer_shadow(struct Render *re, float winmat[][4], struct LampRen *lar, i
void zbuffer_solid(struct RenderPart *pa, struct RenderLayer *rl, void (*fillfunc)(struct RenderPart*, struct ZSpan*, int, void*), void *data);
unsigned short *zbuffer_transp_shade(struct RenderPart *pa, struct RenderLayer *rl, float *pass, struct ListBase *psmlist);
-unsigned short *zbuffer_strands_shade(struct Render *re, struct RenderPart *pa, struct RenderLayer *rl, float *pass);
void convert_zbuf_to_distbuf(struct RenderPart *pa, struct RenderLayer *rl);
void zbuffer_sss(RenderPart *pa, unsigned int lay, void *handle, void (*func)(void*, int, int, int, int, int));
+int zbuffer_strands_abuf(struct Render *re, struct RenderPart *pa, struct RenderLayer *rl, struct APixstrand *apixbuf, struct ListBase *apsmbase, struct StrandShadeCache *cache);
typedef struct APixstr {
unsigned short mask[4]; /* jitter mask */
@@ -64,10 +66,20 @@ typedef struct APixstr {
struct APixstr *next;
} APixstr;
+typedef struct APixstrand {
+ unsigned short mask[4]; /* jitter mask */
+ int z[4]; /* distance */
+ int p[4]; /* index */
+ int obi[4]; /* object instance */
+ int seg[4]; /* for strands, segment number */
+ float u[4], v[4]; /* for strands, u,v coordinate in segment */
+ struct APixstrand *next;
+} APixstrand;
+
typedef struct APixstrMain
{
struct APixstrMain *next, *prev;
- struct APixstr *ps;
+ void *ps;
} APixstrMain;
/* span fill in method, is also used to localize data for zbuffering */
@@ -85,11 +97,13 @@ typedef struct ZSpan {
int *rectp; /* polygon index buffer */
int *recto; /* object buffer */
APixstr *apixbuf, *curpstr; /* apixbuf for transparent */
+ APixstrand *curpstrand; /* same for strands */
struct ListBase *apsmbase;
int polygon_offset; /* offset in Z */
float shad_alpha; /* copy from material, used by irregular shadbuf */
int mask, apsmcounter; /* in use by apixbuf */
+ int apstrandmcounter;
float clipcrop; /* for shadow, was in R global before */
diff --git a/source/blender/render/intern/source/envmap.c b/source/blender/render/intern/source/envmap.c
index 6d93d91ae97..81d5c8ea9ed 100644
--- a/source/blender/render/intern/source/envmap.c
+++ b/source/blender/render/intern/source/envmap.c
@@ -152,7 +152,6 @@ static Render *envmap_render_copy(Render *re, EnvMap *env)
envre->totlamp= re->totlamp;
envre->lights= re->lights;
envre->objecttable= re->objecttable;
- envre->strandbuckets= re->strandbuckets;
envre->customdata_names= re->customdata_names;
envre->raytree= re->raytree;
envre->totinstance= re->totinstance;
@@ -173,7 +172,6 @@ static void envmap_free_render_copy(Render *envre)
envre->totinstance= 0;
envre->lights.first= envre->lights.last= NULL;
envre->objecttable.first= envre->objecttable.last= NULL;
- envre->strandbuckets= NULL;
envre->customdata_names.first= envre->customdata_names.last= NULL;
envre->raytree= NULL;
envre->instancetable.first= envre->instancetable.last= NULL;
diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c
index dd5b96a50ca..375d8a23a2e 100644
--- a/source/blender/render/intern/source/rendercore.c
+++ b/source/blender/render/intern/source/rendercore.c
@@ -684,7 +684,7 @@ static void freeps(ListBase *lb)
lb->first= lb->last= NULL;
}
-void addps(ListBase *lb, long *rd, int obi, int facenr, int z, unsigned short mask)
+static void addps(ListBase *lb, long *rd, int obi, int facenr, int z, unsigned short mask)
{
PixStrMain *psm;
PixStr *ps, *last= NULL;
@@ -969,8 +969,8 @@ void zbufshadeDA_tile(RenderPart *pa)
halo_tile(pa, rl->rectf, rl->lay);
/* transp layer */
- if(R.flag & R_ZTRA) {
- if(rl->layflag & SCE_LAY_ZTRA) {
+ if(R.flag & R_ZTRA || R.totstrand) {
+ if(rl->layflag & (SCE_LAY_ZTRA|SCE_LAY_STRAND)) {
if(pa->fullresult.first) {
zbuffer_transp_shade(pa, rl, rl->rectf, &psmlist);
}
@@ -1015,51 +1015,6 @@ void zbufshadeDA_tile(RenderPart *pa)
}
}
- /* strand rendering */
- if((rl->layflag & SCE_LAY_STRAND) && R.totstrand) {
- if(pa->fullresult.first) {
- zbuffer_strands_shade(&R, pa, rl, rl->rectf);
- }
- else {
- float *fcol, *scol;
- unsigned short *strandmask, *solidmask= NULL; /* 16 bits, MAX_OSA */
- int x;
-
- /* allocate, but not free here, for asynchronous display of this rect in main thread */
- rl->scolrect= MEM_callocN(4*sizeof(float)*pa->rectx*pa->recty, "strand layer");
-
- /* swap for live updates, and it is used in zbuf.c!!! */
- SWAP(float*, rl->scolrect, rl->rectf);
- strandmask= zbuffer_strands_shade(&R, pa, rl, rl->rectf);
- SWAP(float*, rl->scolrect, rl->rectf);
-
- /* zbuffer strands only returns strandmask if there's solid rendered */
- if(strandmask)
- solidmask= make_solid_mask(pa);
-
- if(strandmask && solidmask) {
- unsigned short *sps= solidmask, *spz= strandmask;
- unsigned short fullmask= (1<<R.osa)-1;
-
- fcol= rl->rectf; scol= rl->scolrect;
- for(x=pa->rectx*pa->recty; x>0; x--, scol+=4, fcol+=4, sps++, spz++) {
- if(*sps == fullmask)
- addAlphaOverFloat(fcol, scol);
- else
- addAlphaOverFloatMask(fcol, scol, *sps, *spz);
- }
- }
- else {
- fcol= rl->rectf; scol= rl->scolrect;
- for(x=pa->rectx*pa->recty; x>0; x--, scol+=4, fcol+=4)
- addAlphaOverFloat(fcol, scol);
- }
-
- if(solidmask) MEM_freeN(solidmask);
- if(strandmask) MEM_freeN(strandmask);
- }
- }
-
/* sky before edge */
if(rl->layflag & SCE_LAY_SKY)
sky_tile(pa, rl);
@@ -1192,8 +1147,8 @@ void zbufshade_tile(RenderPart *pa)
if(rl->layflag & SCE_LAY_HALO)
halo_tile(pa, rl->rectf, rl->lay);
- if(R.flag & R_ZTRA) {
- if(rl->layflag & SCE_LAY_ZTRA) {
+ if(R.flag & R_ZTRA || R.totstrand) {
+ if(rl->layflag & (SCE_LAY_ZTRA|SCE_LAY_STRAND)) {
float *fcol, *acol;
int x;
@@ -1211,24 +1166,6 @@ void zbufshade_tile(RenderPart *pa)
}
}
}
-
- /* strand rendering */
- if((rl->layflag & SCE_LAY_STRAND) && R.totstrand) {
- float *fcol, *scol;
- int x;
-
- /* allocate, but not free here, for asynchronous display of this rect in main thread */
- rl->scolrect= MEM_callocN(4*sizeof(float)*pa->rectx*pa->recty, "strand layer");
-
- /* swap for live updates */
- SWAP(float*, rl->scolrect, rl->rectf);
- zbuffer_strands_shade(&R, pa, rl, rl->rectf);
- SWAP(float*, rl->scolrect, rl->rectf);
-
- fcol= rl->rectf; scol= rl->scolrect;
- for(x=pa->rectx*pa->recty; x>0; x--, scol+=4, fcol+=4)
- addAlphaOverFloat(fcol, scol);
- }
/* sky before edge */
if(rl->layflag & SCE_LAY_SKY)
diff --git a/source/blender/render/intern/source/renderdatabase.c b/source/blender/render/intern/source/renderdatabase.c
index 27daad9dc26..9495360f089 100644
--- a/source/blender/render/intern/source/renderdatabase.c
+++ b/source/blender/render/intern/source/renderdatabase.c
@@ -868,11 +868,6 @@ void free_renderdata_tables(Render *re)
re->sortedhalos= NULL;
}
- if(re->strandbuckets) {
- free_buckets(re->strandbuckets);
- re->strandbuckets= NULL;
- }
-
BLI_freelistN(&re->customdata_names);
BLI_freelistN(&re->objecttable);
BLI_freelistN(&re->instancetable);
@@ -1290,8 +1285,6 @@ void project_renderdata(Render *re, void (*projectfunc)(float *, float mat[][4],
}
}
-
- project_strands(re, projectfunc, do_pano, do_buckets);
}
/* ------------------------------------------------------------------------- */
@@ -1349,3 +1342,54 @@ void RE_makeRenderInstances(Render *re)
re->instancetable= newlist;
}
+#if 0
+int clip_render_object(ObjectInstanceRen *obi, float *bounds, float winmat[][4])
+{
+ float mat[4][4], vec[4], max, min, (*boundbox)[3];
+ int a, fl, flag= -1;
+
+ boundbox= obi->obr->boundbox;
+ Mat4CpyMat4(mat, winmat);
+
+ for(a=0; a<8; a++) {
+ vec[0]= (a & 1)? boundbox[0][0]: boundbox[1][0];
+ vec[1]= (a & 2)? boundbox[0][1]: boundbox[1][1];
+ vec[2]= (a & 4)? boundbox[0][2]: boundbox[1][2];
+ vec[3]= 1.0;
+ Mat4MulVec4fl(mat, vec);
+
+ fl= 0;
+ if(bounds) {
+ if(vec[0] > bounds[1]*vec[3]) fl |= 1;
+ if(vec[0]< bounds[0]*vec[3]) fl |= 2;
+ if(vec[1] > bounds[3]*vec[3]) fl |= 4;
+ if(vec[1]< bounds[2]*vec[3]) fl |= 8;
+ }
+ else {
+ if(vec[0] < -vec[3]) fl |= 1;
+ if(vec[0] > vec[3]) fl |= 2;
+ if(vec[1] < -vec[3]) fl |= 4;
+ if(vec[1] > vec[3]) fl |= 8;
+ }
+ if(vec[2] < -vec[3]) fl |= 16;
+ if(vec[2] > vec[3]) fl |= 32;
+
+#if 0
+ max= vec[3];
+ min= -vec[3];
+
+ wco= ho[3];
+ if(vec[0] < min) fl |= 1;
+ if(vec[0] > max) fl |= 2;
+ if(vec[1] < min) fl |= 4;
+ if(vec[1] > max) fl |= 8;
+#endif
+
+ flag &= fl;
+ if(flag==0) return 0;
+ }
+
+ return flag;
+}
+#endif
+
diff --git a/source/blender/render/intern/source/strand.c b/source/blender/render/intern/source/strand.c
index b1cba27ba9b..91b3dfbe621 100644
--- a/source/blender/render/intern/source/strand.c
+++ b/source/blender/render/intern/source/strand.c
@@ -57,248 +57,9 @@
#include "zbuf.h"
/* to be removed */
-void merge_transp_passes(RenderLayer *rl, ShadeResult *shr);
-void add_transp_passes(RenderLayer *rl, int offset, ShadeResult *shr, float alpha);
void hoco_to_zco(ZSpan *zspan, float *zco, float *hoco);
void zspan_scanconvert_strand(ZSpan *zspan, void *handle, float *v1, float *v2, float *v3, void (*func)(void *, int, int, float, float, float) );
void zbufsinglewire(ZSpan *zspan, int obi, int zvlnr, float *ho1, float *ho2);
-int addtosamp_shr(ShadeResult *samp_shr, ShadeSample *ssamp, int addpassflag);
-void add_transp_speed(RenderLayer *rl, int offset, float *speed, float alpha, long *rdrect);
-void reset_sky_speedvectors(RenderPart *pa, RenderLayer *rl, float *rectf);
-
-/* *************** */
-
-#define BUCKETPRIMS_SIZE 256
-
-typedef struct BucketPrims {
- struct BucketPrims *next, *prev;
- void *prim[BUCKETPRIMS_SIZE];
- int totprim;
-} BucketPrims;
-
-typedef struct RenderBuckets {
- ListBase all;
- ListBase *inside;
- ListBase *overlap;
- int x, y;
- float insize[2];
- float zmulx, zmuly, zofsx, zofsy;
-} RenderBuckets;
-
-static void add_bucket_prim(ListBase *lb, void *prim)
-{
- BucketPrims *bpr= lb->last;
-
- if(!bpr || bpr->totprim == BUCKETPRIMS_SIZE) {
- bpr= MEM_callocN(sizeof(BucketPrims), "BucketPrims");
- BLI_addtail(lb, bpr);
- }
-
- bpr->prim[bpr->totprim++]= prim;
-}
-
-RenderBuckets *init_buckets(Render *re)
-{
- RenderBuckets *buckets;
- RenderPart *pa;
- float scalex, scaley, cropx, cropy;
- int x, y, tempparts= 0;
-
- buckets= MEM_callocN(sizeof(RenderBuckets), "RenderBuckets");
-
- if(!re->parts.first) {
- initparts(re);
- tempparts= 1;
- }
-
- pa= re->parts.first;
- if(!pa)
- return buckets;
-
- x= re->xparts+1;
- y= re->yparts+1;
- buckets->x= x;
- buckets->y= y;
-
- scalex= (2.0f - re->xparts*re->partx/(float)re->winx);
- scaley= (2.0f - re->yparts*re->party/(float)re->winy);
-
- cropx= pa->crop/(float)re->partx;
- cropy= pa->crop/(float)re->party;
-
- buckets->insize[0]= 1.0f - 2.0f*cropx;
- buckets->insize[1]= 1.0f - 2.0f*cropy;
-
- buckets->zmulx= re->xparts*scalex;
- buckets->zmuly= re->yparts*scaley;
- buckets->zofsx= scalex*(1.0f - cropx);
- buckets->zofsy= scaley*(1.0f - cropy);
-
- buckets->inside= MEM_callocN(sizeof(ListBase)*x*y, "BucketPrimsInside");
- buckets->overlap= MEM_callocN(sizeof(ListBase)*x*y, "BucketPrimsOverlap");
-
- if(tempparts)
- freeparts(re);
-
- return buckets;
-}
-
-void add_buckets_primitive(RenderBuckets *buckets, float *min, float *max, void *prim)
-{
- float end[3];
- int x, y, a;
-
- x= (int)min[0];
- y= (int)min[1];
-
- if(x >= 0 && x < buckets->x && y >= 0 && y < buckets->y) {
- a= y*buckets->x + x;
-
- end[0]= x + buckets->insize[0];
- end[1]= y + buckets->insize[1];
-
- if(max[0] <= end[0] && max[1] <= end[1]) {
- add_bucket_prim(&buckets->inside[a], prim);
- return;
- }
- else {
- end[0]= x + 2;
- end[1]= y + 2;
-
- if(max[0] <= end[0] && max[1] <= end[1]) {
- add_bucket_prim(&buckets->overlap[a], prim);
- return;
- }
- }
- }
-
- add_bucket_prim(&buckets->all, prim);
-}
-
-void free_buckets(RenderBuckets *buckets)
-{
- int a, size;
-
- BLI_freelistN(&buckets->all);
-
- size= buckets->x*buckets->y;
- for(a=0; a<size; a++) {
- BLI_freelistN(&buckets->inside[a]);
- BLI_freelistN(&buckets->overlap[a]);
- }
-
- if(buckets->inside)
- MEM_freeN(buckets->inside);
- if(buckets->overlap)
- MEM_freeN(buckets->overlap);
-
- MEM_freeN(buckets);
-}
-
-void project_hoco_to_bucket(RenderBuckets *buckets, float *hoco, float *bucketco)
-{
- float div;
-
- div= 1.0f/hoco[3];
- bucketco[0]= buckets->zmulx*(0.5 + 0.5f*hoco[0]*div) + buckets->zofsx;
- bucketco[1]= buckets->zmuly*(0.5 + 0.5f*hoco[1]*div) + buckets->zofsy;
-}
-
-typedef struct RenderPrimitiveIterator {
- Render *re;
- RenderBuckets *buckets;
- ListBase *list[6];
- int listindex, totlist;
- BucketPrims *bpr;
- int bprindex;
-
- ObjectInstanceRen *obi;
- StrandRen *strand;
- int index, tot;
-} RenderPrimitiveIterator;
-
-RenderPrimitiveIterator *init_primitive_iterator(Render *re, RenderBuckets *buckets, RenderPart *pa)
-{
- RenderPrimitiveIterator *iter;
- int nr, x, y, width;
-
- iter= MEM_callocN(sizeof(RenderPrimitiveIterator), "RenderPrimitiveIterator");
- iter->re= re;
-
- if(buckets) {
- iter->buckets= buckets;
-
- nr= BLI_findindex(&re->parts, pa);
- width= buckets->x - 1;
- x= (nr % width) + 1;
- y= (nr / width) + 1;
-
- iter->list[iter->totlist++]= &buckets->all;
- iter->list[iter->totlist++]= &buckets->inside[y*buckets->x + x];
- iter->list[iter->totlist++]= &buckets->overlap[y*buckets->x + x];
- iter->list[iter->totlist++]= &buckets->overlap[y*buckets->x + (x-1)];
- iter->list[iter->totlist++]= &buckets->overlap[(y-1)*buckets->x + (x-1)];
- iter->list[iter->totlist++]= &buckets->overlap[(y-1)*buckets->x + x];
- }
- else {
- iter->index= 0;
- iter->obi= re->instancetable.first;
- if(iter->obi)
- iter->tot= iter->obi->obr->totstrand;
- }
-
- return iter;
-}
-
-void *next_primitive_iterator(RenderPrimitiveIterator *iter)
-{
- if(iter->buckets) {
- if(iter->bpr && iter->bprindex >= iter->bpr->totprim) {
- iter->bpr= iter->bpr->next;
- iter->bprindex= 0;
- }
-
- while(iter->bpr == NULL) {
- if(iter->listindex == iter->totlist)
- return NULL;
-
- iter->bpr= iter->list[iter->listindex++]->first;
- iter->bprindex= 0;
- }
-
- return iter->bpr->prim[iter->bprindex++];
- }
- else {
- if(!iter->obi)
- return NULL;
-
- if(iter->index >= iter->tot) {
- while((iter->obi=iter->obi->next) && !iter->obi->obr->totstrand)
- iter->obi= iter->obi->next;
-
- if(iter->obi)
- iter->tot= iter->obi->obr->totstrand;
- else
- return NULL;
- }
-
- if(iter->index < iter->tot) {
- if((iter->index & 255)==0)
- iter->strand= iter->obi->obr->strandnodes[iter->index>>8].strand;
- else
- iter->strand++;
-
- return iter->strand;
- }
- else
- return NULL;
- }
-}
-
-void free_primitive_iterator(RenderPrimitiveIterator *iter)
-{
- MEM_freeN(iter);
-}
/* *************** */
@@ -422,45 +183,6 @@ void strand_eval_point(StrandSegment *sseg, StrandPoint *spoint)
/* *************** */
-typedef struct StrandPart {
- Render *re;
- ZSpan *zspan;
-
- RenderLayer *rl;
- ShadeResult *result;
- float *pass;
- int *rectz, *outrectz;
- long *rectdaps;
- unsigned short *mask;
- int rectx, recty;
- int addpassflag, addzbuf, sample;
-
- StrandSegment *segment;
- GHash *hash;
- StrandPoint point1, point2;
- ShadeSample ssamp1, ssamp2, ssamp;
- float t[3], s[3];
-} StrandPart;
-
-typedef struct StrandSortSegment {
- struct StrandSortSegment *next;
- int obi, strand, segment;
- float z;
-} StrandSortSegment;
-
-static int compare_strand_segment(const void *poin1, const void *poin2)
-{
- const StrandSortSegment *seg1= (const StrandSortSegment*)poin1;
- const StrandSortSegment *seg2= (const StrandSortSegment*)poin2;
-
- if(seg1->z < seg2->z)
- return -1;
- else if(seg1->z == seg2->z)
- return 0;
- else
- return 1;
-}
-
static void interpolate_vec1(float *v1, float *v2, float t, float negt, float *v)
{
v[0]= negt*v1[0] + t*v2[0];
@@ -481,7 +203,7 @@ static void interpolate_vec4(float *v1, float *v2, float t, float negt, float *v
v[3]= negt*v1[3] + t*v2[3];
}
-static void interpolate_shade_result(ShadeResult *shr1, ShadeResult *shr2, float t, ShadeResult *shr, int addpassflag)
+void interpolate_shade_result(ShadeResult *shr1, ShadeResult *shr2, float t, ShadeResult *shr, int addpassflag)
{
float negt= 1.0f - t;
@@ -517,20 +239,7 @@ static void interpolate_shade_result(ShadeResult *shr1, ShadeResult *shr2, float
}
}
-static void add_strand_obindex(RenderLayer *rl, int offset, ObjectRen *obr)
-{
- RenderPass *rpass;
-
- for(rpass= rl->passes.first; rpass; rpass= rpass->next) {
- if(rpass->passtype == SCE_PASS_INDEXOB) {
- float *fp= rpass->rect + offset;
- *fp= (float)obr->ob->index;
- break;
- }
- }
-}
-
-static void strand_apply_shaderesult_alpha(ShadeResult *shr, float alpha)
+void strand_apply_shaderesult_alpha(ShadeResult *shr, float alpha)
{
if(alpha < 1.0f) {
shr->combined[0] *= alpha;
@@ -547,6 +256,191 @@ static void strand_apply_shaderesult_alpha(ShadeResult *shr, float alpha)
}
}
+void strand_shade_point(Render *re, ShadeSample *ssamp, StrandSegment *sseg, StrandPoint *spoint)
+{
+ ShadeInput *shi= ssamp->shi;
+ ShadeResult *shr= ssamp->shr;
+ VlakRen vlr;
+
+ memset(&vlr, 0, sizeof(vlr));
+ vlr.flag= R_SMOOTH;
+ if(sseg->buffer->ma->mode & MA_TANGENT_STR)
+ vlr.flag |= R_TANGENT;
+
+ shi->vlr= &vlr;
+ shi->strand= sseg->strand;
+ shi->obi= sseg->obi;
+ shi->obr= sseg->obi->obr;
+
+ /* cache for shadow */
+ shi->samplenr= ssamp->samplenr++;
+
+ shade_input_set_strand(shi, sseg->strand, spoint);
+ shade_input_set_strand_texco(shi, sseg->strand, sseg->v[1], spoint);
+
+ /* init material vars */
+ // note, keep this synced with render_types.h
+ memcpy(&shi->r, &shi->mat->r, 23*sizeof(float));
+ shi->har= shi->mat->har;
+
+ /* shade */
+ shade_samples_do_AO(ssamp);
+ shade_input_do_shade(shi, shr);
+
+ /* apply simplification */
+ strand_apply_shaderesult_alpha(shr, spoint->alpha);
+
+ /* include lamphalos for strand, since halo layer was added already */
+ if(re->flag & R_LAMPHALO)
+ if(shi->layflag & SCE_LAY_HALO)
+ renderspothalo(shi, shr->combined, shr->combined[3]);
+
+ shi->strand= NULL;
+}
+
+/* *************** */
+
+struct StrandShadeCache {
+ GHash *resulthash;
+ GHash *refcounthash;
+ MemArena *memarena;
+};
+
+StrandShadeCache *strand_shade_cache_create()
+{
+ StrandShadeCache *cache;
+
+ cache= MEM_callocN(sizeof(StrandShadeCache), "StrandShadeCache");
+ cache->resulthash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+ cache->refcounthash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+ cache->memarena= BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE);
+
+ return cache;
+}
+
+void strand_shade_cache_free(StrandShadeCache *cache)
+{
+ BLI_ghash_free(cache->refcounthash, NULL, NULL);
+ BLI_ghash_free(cache->resulthash, NULL, (GHashValFreeFP)MEM_freeN);
+ BLI_memarena_free(cache->memarena);
+ MEM_freeN(cache);
+}
+
+static void strand_shade_get(Render *re, StrandShadeCache *cache, ShadeSample *ssamp, StrandSegment *sseg, StrandVert *svert)
+{
+ ShadeResult *hashshr;
+ StrandPoint p;
+ int *refcount;
+
+ hashshr= BLI_ghash_lookup(cache->resulthash, svert);
+ refcount= BLI_ghash_lookup(cache->refcounthash, svert);
+
+ if(!hashshr) {
+ /* not shaded yet, shade and insert into hash */
+ p.t= (sseg->v[1] == svert)? 0.0f: 1.0f;
+ strand_eval_point(sseg, &p);
+ strand_shade_point(re, ssamp, sseg, &p);
+
+ hashshr= MEM_callocN(sizeof(ShadeResult), "HashShadeResult");
+ *hashshr= ssamp->shr[0];
+ BLI_ghash_insert(cache->resulthash, svert, hashshr);
+ }
+ else
+ /* already shaded, just copy previous result from hash */
+ ssamp->shr[0]= *hashshr;
+
+ /* lower reference count and remove if not needed anymore by any samples */
+ (*refcount)--;
+ if(*refcount == 0) {
+ BLI_ghash_remove(cache->resulthash, svert, NULL, (GHashValFreeFP)MEM_freeN);
+ BLI_ghash_remove(cache->refcounthash, svert, NULL, NULL);
+ }
+}
+
+void strand_shade_segment(Render *re, StrandShadeCache *cache, StrandSegment *sseg, ShadeSample *ssamp, float t, float s, int addpassflag)
+{
+ ShadeResult shr1, shr2;
+
+ /* get shading for two endpoints and interpolate */
+ strand_shade_get(re, cache, ssamp, sseg, sseg->v[1]);
+ shr1= ssamp->shr[0];
+ strand_shade_get(re, cache, ssamp, sseg, sseg->v[2]);
+ shr2= ssamp->shr[0];
+
+ interpolate_shade_result(&shr1, &shr2, t, ssamp->shr, addpassflag);
+
+ /* apply alpha along width */
+ if(sseg->buffer->widthfade != 0.0f) {
+ s = 1.0f - pow(fabs(s), sseg->buffer->widthfade);
+
+ strand_apply_shaderesult_alpha(ssamp->shr, s);
+ }
+}
+
+void strand_shade_unref(StrandShadeCache *cache, StrandVert *svert)
+{
+ int *refcount;
+
+ /* lower reference count and remove if not needed anymore by any samples */
+ refcount= BLI_ghash_lookup(cache->refcounthash, svert);
+
+ (*refcount)--;
+ if(*refcount == 0) {
+ BLI_ghash_remove(cache->resulthash, svert, NULL, (GHashValFreeFP)MEM_freeN);
+ BLI_ghash_remove(cache->refcounthash, svert, NULL, NULL);
+ }
+}
+
+static void strand_shade_refcount(StrandShadeCache *cache, StrandVert *svert)
+{
+ int *refcount= BLI_ghash_lookup(cache->refcounthash, svert);
+
+ if(!refcount) {
+ refcount= BLI_memarena_alloc(cache->memarena, sizeof(int));
+ *refcount= 1;
+ BLI_ghash_insert(cache->refcounthash, svert, refcount);
+ }
+ else
+ (*refcount)++;
+}
+
+/* *************** */
+
+typedef struct StrandPart {
+ Render *re;
+ ZSpan *zspan;
+
+ APixstrand *apixbuf;
+ int *rectz;
+ long *rectdaps;
+ int rectx, recty;
+ int sample;
+
+ StrandSegment *segment;
+ float t[3], s[3];
+
+ StrandShadeCache *cache;
+} StrandPart;
+
+typedef struct StrandSortSegment {
+ struct StrandSortSegment *next;
+ int obi, strand, segment;
+ float z;
+} StrandSortSegment;
+
+static int compare_strand_segment(const void *poin1, const void *poin2)
+{
+ const StrandSortSegment *seg1= (const StrandSortSegment*)poin1;
+ const StrandSortSegment *seg2= (const StrandSortSegment*)poin2;
+
+ if(seg1->z > seg2->z)
+ return -1;
+ else if(seg1->z == seg2->z)
+ return 0;
+ else
+ return 1;
+}
+
static void do_strand_point_project(float winmat[][4], ZSpan *zspan, float *co, float *hoco, float *zco)
{
projectvert(co, winmat, hoco);
@@ -564,69 +458,59 @@ static void strand_project_point(float winmat[][4], float winx, float winy, Stra
spoint->y= spoint->hoco[1]*div*winy*0.5f;
}
-static void strand_shade_point(Render *re, ShadeSample *ssamp, StrandSegment *sseg, StrandPoint *spoint);
-
-static void strand_shade_get(StrandPart *spart, int lookup, ShadeSample *ssamp, StrandPoint *spoint, StrandVert *svert, StrandSegment *sseg)
+static APixstrand *addpsmainAstrand(ListBase *lb)
{
- ShadeResult *hashshr;
+ APixstrMain *psm;
- if(lookup) {
- hashshr= BLI_ghash_lookup(spart->hash, svert);
+ psm= MEM_mallocN(sizeof(APixstrMain), "addpsmainA");
+ BLI_addtail(lb, psm);
+ psm->ps= MEM_callocN(4096*sizeof(APixstrand),"pixstr");
- if(!hashshr) {
- strand_shade_point(spart->re, ssamp, sseg, spoint);
-
- hashshr= MEM_callocN(sizeof(ShadeResult), "HashShadeResult");
- *hashshr= ssamp->shr[0];
- BLI_ghash_insert(spart->hash, svert, hashshr);
- }
- else {
- ssamp->shr[0]= *hashshr;
- BLI_ghash_remove(spart->hash, svert, NULL, (GHashValFreeFP)MEM_freeN);
- }
- }
- else
- strand_shade_point(spart->re, ssamp, sseg, spoint);
+ return psm->ps;
}
-static void strand_shade_segment(StrandPart *spart)
+static APixstrand *addpsAstrand(ZSpan *zspan)
{
- StrandSegment *sseg= spart->segment;
- int first, last;
-
- if(!sseg->shaded) {
- first= (sseg->v[1] == &sseg->strand->vert[0]);
- last= (sseg->v[2] == &sseg->strand->vert[sseg->strand->totvert-1]);
-
- strand_shade_get(spart, !first, &spart->ssamp1, &sseg->point1, sseg->v[1], sseg);
- strand_shade_get(spart, !last, &spart->ssamp2, &sseg->point2, sseg->v[2], sseg);
- sseg->shaded= 1;
+ /* make new PS */
+ if(zspan->apstrandmcounter==0) {
+ zspan->curpstrand= addpsmainAstrand(zspan->apsmbase);
+ zspan->apstrandmcounter= 4095;
+ }
+ else {
+ zspan->curpstrand++;
+ zspan->apstrandmcounter--;
}
+ return zspan->curpstrand;
}
-static void do_strand_blend(void *handle, int x, int y, float u, float v, float z)
+static void do_strand_fillac(void *handle, int x, int y, float u, float v, float z)
{
StrandPart *spart= (StrandPart*)handle;
- StrandBuffer *buffer= spart->segment->buffer;
- ShadeResult *shr;
- float /**pass,*/ t, s;
- int offset, zverg, bufferz;
+ StrandShadeCache *cache= spart->cache;
+ StrandSegment *sseg= spart->segment;
+ APixstrand *apn, *apnew;
+ float t, s;
+ int offset, mask, obi, strnr, seg, zverg, bufferz;
- /* check again solid z-buffer */
offset = y*spart->rectx + x;
+ obi= sseg->obi - spart->re->objectinstance;
+ strnr= sseg->strand->index + 1;
+ seg= sseg->v[1] - sseg->strand->vert;
+ mask= (1<<spart->sample);
+
+ /* check against solid z-buffer */
zverg= (int)z;
if(spart->rectdaps) {
/* find the z of the sample */
PixStr *ps;
long *rd= spart->rectdaps + offset;
- int sample= (1<<spart->sample);
bufferz= 0x7FFFFFFF;
if(*rd) {
for(ps= (PixStr *)(*rd); ps; ps= ps->next) {
- if(sample & ps->mask) {
+ if(mask & ps->mask) {
bufferz= ps->z;
break;
}
@@ -636,48 +520,37 @@ static void do_strand_blend(void *handle, int x, int y, float u, float v, float
else
bufferz= spart->rectz[offset];
- if(zverg < bufferz) {
- /* fill in output z-buffer if needed */
- if(spart->addzbuf)
- if(zverg < spart->outrectz[offset])
- spart->outrectz[offset]= zverg;
-
- /* check alpha limit */
- shr= spart->result + offset*(spart->re->osa? spart->re->osa: 1);
- if(shr[spart->sample].combined[3]>0.999f)
- return;
-
- /* shade points if not shaded yet */
- strand_shade_segment(spart);
+#define CHECK_ADD(n) \
+ if(apn->p[n]==strnr && apn->obi[n]==obi && apn->seg[n]==seg) \
+ { if(!(apn->mask[n] & mask)) { apn->mask[n] |= mask; apn->v[n] += t; apn->u[n] += s; } break; }
+#define CHECK_ASSIGN(n) \
+ if(apn->p[n]==0) \
+ {apn->obi[n]= obi; apn->p[n]= strnr; apn->z[n]= zverg; apn->mask[n]= mask; apn->v[n]= t; apn->u[n]= s; apn->seg[n]= seg; break; }
- /* interpolate shading from two control points */
+ /* add to pixel list */
+ if(zverg < bufferz) {
t = u*spart->t[0] + v*spart->t[1] + (1.0f-u-v)*spart->t[2];
- interpolate_shade_result(spart->ssamp1.shr, spart->ssamp2.shr, t,
- spart->ssamp.shr, spart->addpassflag);
-
- /* alpha along width */
- if(buffer->widthfade != 0.0f) {
- s = fabs(u*spart->s[0] + v*spart->s[1] + (1.0f-u-v)*spart->s[2]);
- s = 1.0f - pow(s, buffer->widthfade);
-
- strand_apply_shaderesult_alpha(spart->ssamp.shr, s);
- }
-
- /* add in shaderesult array for part */
- spart->ssamp.shi[0].mask= (1<<spart->sample);
- addtosamp_shr(shr, &spart->ssamp, spart->addpassflag);
- spart->mask[offset] |= (1<<spart->sample);
-
-#if 0
- /* fill in pass for preview */
- if(spart->sample == 0) {
- pass= spart->pass + offset*4;
- QUATCOPY(pass, shr->combined);
+ s = fabs(u*spart->s[0] + v*spart->s[1] + (1.0f-u-v)*spart->s[2]);
+
+ apn= spart->apixbuf + offset;
+ while(apn) {
+ CHECK_ADD(0);
+ CHECK_ADD(1);
+ CHECK_ADD(2);
+ CHECK_ADD(3);
+ CHECK_ASSIGN(0);
+ CHECK_ASSIGN(1);
+ CHECK_ASSIGN(2);
+ CHECK_ASSIGN(3);
+
+ apnew= addpsAstrand(spart->zspan);
+ SWAP(APixstrand, *apnew, *apn);
+ apn->next= apnew;
+ CHECK_ASSIGN(0);
}
-#endif
- if(spart->addpassflag & SCE_PASS_INDEXOB)
- add_strand_obindex(spart->rl, offset, buffer->obr);
+ strand_shade_refcount(cache, sseg->v[1]);
+ strand_shade_refcount(cache, sseg->v[2]);
}
}
@@ -701,46 +574,6 @@ static int strand_test_clip(float winmat[][4], ZSpan *zspan, float *bounds, floa
return clipflag;
}
-static void strand_shade_point(Render *re, ShadeSample *ssamp, StrandSegment *sseg, StrandPoint *spoint)
-{
- ShadeInput *shi= ssamp->shi;
- ShadeResult *shr= ssamp->shr;
- VlakRen vlr;
-
- memset(&vlr, 0, sizeof(vlr));
- vlr.flag= R_SMOOTH;
- if(sseg->buffer->ma->mode & MA_TANGENT_STR)
- vlr.flag |= R_TANGENT;
-
- shi->vlr= &vlr;
- shi->strand= sseg->strand;
- shi->obi= sseg->obi;
- shi->obr= sseg->obi->obr;
-
- /* cache for shadow */
- shi->samplenr++;
-
- shade_input_set_strand(shi, sseg->strand, spoint);
- shade_input_set_strand_texco(shi, sseg->strand, sseg->v[1], spoint);
-
- /* init material vars */
- // note, keep this synced with render_types.h
- memcpy(&shi->r, &shi->mat->r, 23*sizeof(float));
- shi->har= shi->mat->har;
-
- /* shade */
- shade_samples_do_AO(ssamp);
- shade_input_do_shade(shi, shr);
-
- /* apply simplification */
- strand_apply_shaderesult_alpha(shr, spoint->alpha);
-
- /* include lamphalos for strand, since halo layer was added already */
- if(re->flag & R_LAMPHALO)
- if(shi->layflag & SCE_LAY_HALO)
- renderspothalo(shi, shr->combined, shr->combined[3]);
-}
-
static void do_scanconvert_strand(Render *re, StrandPart *spart, ZSpan *zspan, float t, float dt, float *co1, float *co2, float *co3, float *co4, int sample)
{
float jco1[3], jco2[3], jco3[3], jco4[3], jx, jy;
@@ -777,14 +610,14 @@ static void do_scanconvert_strand(Render *re, StrandPart *spart, ZSpan *zspan, f
spart->s[1]= 1.0f;
spart->t[2]= t;
spart->s[2]= 1.0f;
- zspan_scanconvert_strand(zspan, spart, jco1, jco2, jco3, do_strand_blend);
+ zspan_scanconvert_strand(zspan, spart, jco1, jco2, jco3, do_strand_fillac);
spart->t[0]= t-dt;
spart->s[0]= -1.0f;
spart->t[1]= t;
spart->s[1]= 1.0f;
spart->t[2]= t;
spart->s[2]= -1.0f;
- zspan_scanconvert_strand(zspan, spart, jco1, jco3, jco4, do_strand_blend);
+ zspan_scanconvert_strand(zspan, spart, jco1, jco3, jco4, do_strand_fillac);
}
static void strand_render(Render *re, StrandSegment *sseg, float winmat[][4], StrandPart *spart, ZSpan *zspan, int totzspan, StrandPoint *p1, StrandPoint *p2)
@@ -909,110 +742,9 @@ void render_strand_segment(Render *re, float winmat[][4], StrandPart *spart, ZSp
strand_render(re, sseg, winmat, spart, zspan, totzspan, p1, p2);
}
-static void zbuffer_strands_filter(Render *re, RenderPart *pa, RenderLayer *rl, StrandPart *spart, float *pass)
-{
- RenderResult *rr= pa->result;
- ShadeResult *shr, *shrrect= spart->result;
- RenderLayer *rl_pp[RE_MAX_OSA];
- float *passrect= pass, alpha, sampalpha;
- long *rdrect;
- int osa, x, y, a, crop= 0, offs=0, od;
-
- osa= (re->osa? re->osa: 1);
- sampalpha= 1.0f/osa;
-
- /* only used for multisample buffers */
- get_sample_layers(pa, rl, rl_pp);
-
- /* filtered render, for now we assume only 1 filter size */
- if(pa->crop) {
- crop= 1;
- offs= pa->rectx + 1;
- passrect+= 4*offs;
- shrrect+= offs*osa;
- }
-
- rdrect= pa->rectdaps;
-
- /* zero alpha pixels get speed vector max again */
- if(spart->addpassflag & SCE_PASS_VECTOR)
- if(rl->layflag & SCE_LAY_SOLID)
- reset_sky_speedvectors(pa, rl, rl->scolrect?rl->scolrect:rl->rectf); /* scolrect==NULL for multisample */
-
- /* init scanline updates */
- rr->renrect.ymin= 0;
- rr->renrect.ymax= -pa->crop;
- rr->renlay= rl;
-
- /* filter the shade results */
- for(y=pa->disprect.ymin+crop; y<pa->disprect.ymax-crop; y++, rr->renrect.ymax++) {
- pass= passrect;
- shr= shrrect;
- od= offs;
-
- for(x=pa->disprect.xmin+crop; x<pa->disprect.xmax-crop; x++, shr+=osa, pass+=4, od++) {
- if(spart->mask[od] == 0) {
- if(spart->addpassflag & SCE_PASS_VECTOR)
- add_transp_speed(rl, od, NULL, 0.0f, rdrect);
- }
- else {
- alpha= 0.0f;
-
- if(pa->fullresult.first) {
- for(a=0; a<re->osa; a++) {
- alpha= shr[a].combined[3];
- if(alpha!=0.0f) {
- RenderLayer *rl= rl_pp[a];
-
- addAlphaOverFloat(rl->rectf + 4*od, shr[a].combined);
-
- add_transp_passes(rl, od, shr, alpha);
- if(spart->addpassflag & SCE_PASS_VECTOR)
- add_transp_speed(rl, od, shr[a].winspeed, alpha, rdrect);
- }
- }
-
- }
- else {
-
- if(re->osa == 0) {
- addAlphaUnderFloat(pass, shr->combined);
- }
- else {
- /* note; cannot use pass[3] for alpha due to filtermask */
- for(a=0; a<re->osa; a++) {
- add_filt_fmask(1<<a, shr[a].combined, pass, rr->rectx);
- alpha += shr[a].combined[3];
- }
- }
-
- if(spart->addpassflag) {
- alpha *= sampalpha;
-
- /* merge all in one, and then add */
- merge_transp_passes(rl, shr);
- add_transp_passes(rl, od, shr, alpha);
-
- if(spart->addpassflag & SCE_PASS_VECTOR)
- add_transp_speed(rl, od, shr->winspeed, alpha, rdrect);
- }
- }
- }
- }
-
- shrrect+= pa->rectx*osa;
- passrect+= 4*pa->rectx;
- offs+= pa->rectx;
- }
-
- /* disable scanline updating */
- rr->renlay= NULL;
-}
-
/* render call to fill in strands */
-unsigned short *zbuffer_strands_shade(Render *re, RenderPart *pa, RenderLayer *rl, float *pass)
+int zbuffer_strands_abuf(Render *re, RenderPart *pa, RenderLayer *rl, APixstrand *apixbuf, ListBase *apsmbase, StrandShadeCache *cache)
{
- //struct RenderPrimitiveIterator *iter;
ObjectRen *obr;
ObjectInstanceRen *obi;
ZSpan zspan;
@@ -1023,56 +755,24 @@ unsigned short *zbuffer_strands_shade(Render *re, RenderPart *pa, RenderLayer *r
StrandSortSegment *sortsegments = NULL, *sortseg, *firstseg;
MemArena *memarena;
float z[4], bounds[4], winmat[4][4];
- int a, b, i, resultsize, totsegment, clip[4];
+ int a, b, i, totsegment, clip[4];
if(re->test_break())
- return NULL;
+ return 0;
if(re->totstrand == 0)
- return NULL;
+ return 0;
/* setup StrandPart */
memset(&spart, 0, sizeof(spart));
spart.re= re;
- spart.rl= rl;
- spart.pass= pass;
spart.rectx= pa->rectx;
spart.recty= pa->recty;
- spart.rectz= pa->rectz;
+ spart.apixbuf= apixbuf;
+ spart.zspan= &zspan;
spart.rectdaps= pa->rectdaps;
- spart.addpassflag= rl->passflag & ~(SCE_PASS_Z|SCE_PASS_COMBINED);
- spart.addzbuf= rl->passflag & SCE_PASS_Z;
-
- if(re->osa) resultsize= pa->rectx*pa->recty*re->osa;
- else resultsize= pa->rectx*pa->recty;
- spart.result= MEM_callocN(sizeof(ShadeResult)*resultsize, "StrandPartResult");
- spart.mask= MEM_callocN(pa->rectx*pa->recty*sizeof(short), "StrandPartMask");
-
- if(spart.addpassflag & SCE_PASS_VECTOR) {
- /* initialize speed vectors */
- for(a=0; a<resultsize; a++) {
- spart.result[a].winspeed[0]= PASS_VECTOR_MAX;
- spart.result[a].winspeed[1]= PASS_VECTOR_MAX;
- spart.result[a].winspeed[2]= PASS_VECTOR_MAX;
- spart.result[a].winspeed[3]= PASS_VECTOR_MAX;
- }
- }
-
- if(spart.addzbuf) {
- /* duplicate rectz so we can read from the old buffer, while
- * writing new z values */
- spart.rectz= MEM_dupallocN(pa->rectz);
- spart.outrectz= pa->rectz;
- }
-
- shade_sample_initialize(&spart.ssamp1, pa, rl);
- shade_sample_initialize(&spart.ssamp2, pa, rl);
- shade_sample_initialize(&spart.ssamp, pa, rl);
- spart.ssamp1.shi[0].sample= 0;
- spart.ssamp2.shi[0].sample= 1;
- spart.ssamp1.tot= 1;
- spart.ssamp2.tot= 1;
- spart.ssamp.tot= 1;
+ spart.rectz= pa->rectz;
+ spart.cache= cache;
zbuf_alloc_span(&zspan, pa->rectx, pa->recty, re->clipcrop);
@@ -1087,21 +787,19 @@ unsigned short *zbuffer_strands_shade(Render *re, RenderPart *pa, RenderLayer *r
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;
- /* sort segments */
- //iter= init_primitive_iterator(re, re->strandbuckets, pa);
-
memarena= BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE);
firstseg= NULL;
sortseg= sortsegments;
totsegment= 0;
- //while((strand = next_primitive_iterator(iter))) {
for(obi=re->instancetable.first, i=0; obi; obi=obi->next, i++) {
obr= obi->obr;
@@ -1120,11 +818,6 @@ unsigned short *zbuffer_strands_shade(Render *re, RenderPart *pa, RenderLayer *r
if(!(strand->buffer->lay & rl->lay))
continue;
-#if 0
- if(strand->clip)
- continue;
-#endif
-
svert= strand->vert;
/* keep clipping and z depth for 4 control points */
@@ -1163,10 +856,6 @@ unsigned short *zbuffer_strands_shade(Render *re, RenderPart *pa, RenderLayer *r
}
}
-#if 0
- free_primitive_iterator(iter);
-#endif
-
if(!re->test_break()) {
/* convert list to array and sort */
sortsegments= MEM_mallocN(sizeof(StrandSortSegment)*totsegment, "StrandSortSegment");
@@ -1177,8 +866,6 @@ unsigned short *zbuffer_strands_shade(Render *re, RenderPart *pa, RenderLayer *r
BLI_memarena_free(memarena);
- spart.hash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
-
if(!re->test_break()) {
/* render segments in sorted order */
sortseg= sortsegments;
@@ -1209,133 +896,15 @@ unsigned short *zbuffer_strands_shade(Render *re, RenderPart *pa, RenderLayer *r
}
}
- // TODO printf(">>> %d\n", BLI_ghash_size(spart.hash));
- BLI_ghash_free(spart.hash, NULL, (GHashValFreeFP)MEM_freeN);
-
- zbuffer_strands_filter(re, pa, rl, &spart, pass);
-
- /* free */
- MEM_freeN(spart.result);
-
- if(spart.addzbuf)
- MEM_freeN(spart.rectz);
-
if(sortsegments)
MEM_freeN(sortsegments);
zbuf_free_span(&zspan);
- if( !(re->osa && (rl->layflag & SCE_LAY_SOLID)) || (pa->fullresult.first)) {
- MEM_freeN(spart.mask);
- spart.mask= NULL;
- }
-
- return spart.mask;
+ return totsegment;
}
-void project_strands(Render *re, void (*projectfunc)(float *, float mat[][4], float *), int do_pano, int do_buckets)
-{
-#if 0
- ObjectRen *obr;
- StrandRen *strand = NULL;
- StrandVert *svert;
- float hoco[4], min[2], max[2], bucketco[2], vec[3];
- int a, b;
- /* float bmin[3], bmax[3], bpad[3], padding[2]; */
-
- if(re->strandbuckets) {
- free_buckets(re->strandbuckets);
- re->strandbuckets= NULL;
- }
-
- if(re->totstrand == 0)
- return;
-
- if(do_buckets)
- re->strandbuckets= init_buckets(re);
-
- /* calculate view coordinates (and zbuffer value) */
- for(obr=re->objecttable.first; obr; obr=obr->next) {
- for(a=0; a<obr->totstrand; a++) {
- if((a & 255)==0) strand= obr->strandnodes[a>>8].strand;
- else strand++;
-
- strand->clip= ~0;
-
-#if 0
- if(!(strand->buffer->flag & R_STRAND_BSPLINE)) {
- INIT_MINMAX(bmin, bmax);
- svert= strand->vert;
- for(b=0; b<strand->totvert; b++, svert++)
- DO_MINMAX(svert->co, bmin, bmax)
-
- bpad[0]= (bmax[0]-bmin[0])*0.2f;
- bpad[1]= (bmax[1]-bmin[1])*0.2f;
- bpad[2]= (bmax[2]-bmin[2])*0.2f;
- }
- else
- bpad[0]= bpad[1]= bpad[2]= 0.0f;
-
- ma= strand->buffer->ma;
- width= MAX2(ma->strand_sta, ma->strand_end);
- if(strand->buffer->flag & R_STRAND_B_UNITS) {
- bpad[0] += 0.5f*width;
- bpad[1] += 0.5f*width;
- bpad[2] += 0.5f*width;
- }
-#endif
-
- INIT_MINMAX2(min, max);
- svert= strand->vert;
- for(b=0; b<strand->totvert; b++, svert++) {
- //VECADD(vec, svert->co, bpad);
-
- /* same as VertRen */
- if(do_pano) {
- vec[0]= re->panoco*svert->co[0] + re->panosi*svert->co[2];
- vec[1]= svert->co[1];
- vec[2]= -re->panosi*svert->co[0] + re->panoco*svert->co[2];
- }
- else
- VECCOPY(vec, svert->co)
-
- /* Go from wcs to hcs ... */
- projectfunc(vec, re->winmat, hoco);
- /* ... and clip in that system. */
- strand->clip &= testclip(hoco);
-
-#if 0
- if(do_buckets) {
- project_hoco_to_bucket(re->strandbuckets, hoco, bucketco);
- DO_MINMAX2(bucketco, min, max);
- }
-#endif
- }
-
-#if 0
- if(do_buckets) {
- if(strand->buffer->flag & R_STRAND_BSPLINE) {
- min[0] -= width;
- min[1] -= width;
- max[0] += width;
- max[1] += width;
- }
- else {
- /* catmull-rom stays within 1.2f bounds in object space,
- * is this still true after projection? */
- min[0] -= width + (max[0]-min[0])*0.2f;
- min[1] -= width + (max[1]-min[1])*0.2f;
- max[0] += width + (max[0]-min[0])*0.2f;
- max[1] += width + (max[1]-min[1])*0.2f;
- }
-
- add_buckets_primitive(re->strandbuckets, min, max, strand);
- }
-#endif
- }
- }
-#endif
-}
+/* *************** */
StrandSurface *cache_strand_surface(Render *re, ObjectRen *obr, DerivedMesh *dm, float mat[][4], int timeoffset)
{
diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c
index 8aa2e06714c..3acce279836 100644
--- a/source/blender/render/intern/source/zbuf.c
+++ b/source/blender/render/intern/source/zbuf.c
@@ -3438,12 +3438,11 @@ void add_transp_speed(RenderLayer *rl, int offset, float *speed, float alpha, lo
}
}
-static void add_transp_obindex(RenderLayer *rl, int offset, int obi, int facenr)
+static void add_transp_obindex(RenderLayer *rl, int offset, int obi)
{
ObjectRen *obr= R.objectinstance[obi].obr;
- VlakRen *vlr= RE_findOrAddVlak(obr, (facenr-1) & RE_QUAD_MASK);
- if(vlr && obr->ob) {
+ if(obr->ob) {
RenderPass *rpass;
for(rpass= rl->passes.first; rpass; rpass= rpass->next) {
@@ -3600,12 +3599,13 @@ void add_transp_passes(RenderLayer *rl, int offset, ShadeResult *shr, float alph
}
}
-
typedef struct ZTranspRow {
int obi;
int z;
int p;
int mask;
+ int segment;
+ float u, v;
} ZTranspRow;
static int vergzvlak(const void *a1, const void *a2)
@@ -3617,6 +3617,56 @@ static int vergzvlak(const void *a1, const void *a2)
return 0;
}
+static void shade_strand_samples(StrandShadeCache *cache, ShadeSample *ssamp, int x, int y, ZTranspRow *row, int addpassflag)
+{
+ StrandSegment sseg;
+ StrandVert *svert;
+ ObjectInstanceRen *obi;
+ ObjectRen *obr;
+
+ obi= R.objectinstance + row->obi;
+ obr= obi->obr;
+
+ sseg.obi= obi;
+ sseg.strand= RE_findOrAddStrand(obr, row->p-1);
+ sseg.buffer= sseg.strand->buffer;
+
+ svert= sseg.strand->vert + row->segment;
+ sseg.v[0]= (row->segment > 0)? (svert-1): svert;
+ sseg.v[1]= svert;
+ sseg.v[2]= svert+1;
+ sseg.v[3]= (row->segment < sseg.strand->totvert-2)? svert+2: svert+1;
+
+ strand_shade_segment(&R, cache, &sseg, ssamp, row->v, row->u, addpassflag);
+ ssamp->shi[0].mask= row->mask;
+ ssamp->tot= 1;
+}
+
+static void unref_strand_samples(StrandShadeCache *cache, ZTranspRow *row, int totface)
+{
+ StrandVert *svert;
+ ObjectInstanceRen *obi;
+ ObjectRen *obr;
+ StrandRen *strand;
+
+ /* remove references to samples that are not being rendered, but we still
+ * need to remove them so that the reference count of strand vertex shade
+ * samples correctly drops to zero */
+ while(totface > 0) {
+ totface--;
+
+ if(row[totface].segment != -1) {
+ obi= R.objectinstance + row[totface].obi;
+ obr= obi->obr;
+ strand= RE_findOrAddStrand(obr, row[totface].p-1);
+ svert= strand->vert + row[totface].segment;
+
+ strand_shade_unref(cache, svert);
+ strand_shade_unref(cache, svert+1);
+ }
+ }
+}
+
static void shade_tra_samples_fill(ShadeSample *ssamp, int x, int y, int z, int obi, int facenr, int curmask)
{
ShadeInput *shi= ssamp->shi;
@@ -3674,8 +3724,13 @@ static void shade_tra_samples_fill(ShadeSample *ssamp, int x, int y, int z, int
}
}
-static int shade_tra_samples(ShadeSample *ssamp, int x, int y, ZTranspRow *row)
+static int shade_tra_samples(ShadeSample *ssamp, StrandShadeCache *cache, int x, int y, ZTranspRow *row, int addpassflag)
{
+ if(row->segment != -1) {
+ shade_strand_samples(cache, ssamp, x, y, row, addpassflag);
+ return 1;
+ }
+
shade_tra_samples_fill(ssamp, x, y, row->z, row->obi, row->p, row->mask);
if(ssamp->tot) {
@@ -3800,16 +3855,19 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas
RenderResult *rr= pa->result;
ShadeSample ssamp;
APixstr *APixbuf; /* Zbuffer: linked list of face samples */
+ APixstrand *APixbufstrand = NULL;
APixstr *ap, *aprect, *apn;
+ APixstrand *apstrand, *aprectstrand, *apnstrand;
ListBase apsmbase={NULL, NULL};
ShadeResult samp_shr[16]; /* MAX_OSA */
ZTranspRow zrow[MAX_ZROW];
+ StrandShadeCache *sscache= NULL;
float sampalpha, *passrect= pass;
long *rdrect;
- int x, y, crop=0, a, totface;
+ int x, y, crop=0, a, b, totface, totsample, doztra;
int addpassflag, offs= 0, od, addzbuf;
unsigned short *ztramask= NULL;
-
+
/* looks nicer for calling code */
if(R.test_break())
return NULL;
@@ -3821,14 +3879,15 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas
}
APixbuf= MEM_callocN(pa->rectx*pa->recty*sizeof(APixstr), "APixbuf");
+ if(R.totstrand && (rl->layflag & SCE_LAY_STRAND)) {
+ APixbufstrand= MEM_callocN(pa->rectx*pa->recty*sizeof(APixstrand), "APixbufstrand");
+ sscache= strand_shade_cache_create();
+ }
/* general shader info, passes */
shade_sample_initialize(&ssamp, pa, rl);
addpassflag= rl->passflag & ~(SCE_PASS_Z|SCE_PASS_COMBINED);
- if((rl->layflag & SCE_LAY_STRAND) && R.totstrand)
- addzbuf= 1; /* strands layer needs the z-buffer */
- else
- addzbuf= rl->passflag & SCE_PASS_Z;
+ addzbuf= rl->passflag & SCE_PASS_Z;
if(R.osa)
sampalpha= 1.0f/(float)R.osa;
@@ -3836,14 +3895,25 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas
sampalpha= 1.0f;
/* fill the Apixbuf */
- if(0 == zbuffer_abuf(pa, APixbuf, &apsmbase, rl->lay)) {
+ doztra= 0;
+ if(rl->layflag & SCE_LAY_ZTRA)
+ doztra+= zbuffer_abuf(pa, APixbuf, &apsmbase, rl->lay);
+ if((rl->layflag & SCE_LAY_STRAND) && APixbufstrand)
+ doztra+= zbuffer_strands_abuf(&R, pa, rl, APixbufstrand, &apsmbase, sscache);
+
+ if(doztra == 0) {
/* nothing filled in */
MEM_freeN(APixbuf);
+ if(APixbufstrand)
+ MEM_freeN(APixbufstrand);
+ if(sscache)
+ strand_shade_cache_free(sscache);
freepsA(&apsmbase);
return NULL;
}
aprect= APixbuf;
+ aprectstrand= APixbufstrand;
rdrect= pa->rectdaps;
/* irregular shadowb buffer creation */
@@ -3865,6 +3935,7 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas
offs= pa->rectx + 1;
passrect+= 4*offs;
aprect+= offs;
+ aprectstrand+= offs;
}
/* init scanline updates */
@@ -3876,14 +3947,15 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas
for(y=pa->disprect.ymin+crop; y<pa->disprect.ymax-crop; y++, rr->renrect.ymax++) {
pass= passrect;
ap= aprect;
+ apstrand= aprectstrand;
od= offs;
if(R.test_break())
break;
- for(x=pa->disprect.xmin+crop; x<pa->disprect.xmax-crop; x++, ap++, pass+=4, od++) {
+ for(x=pa->disprect.xmin+crop; x<pa->disprect.xmax-crop; x++, ap++, apstrand++, pass+=4, od++) {
- if(ap->p[0]==0) {
+ if(ap->p[0]==0 && (!APixbufstrand || apstrand->p[0]==0)) {
if(addpassflag & SCE_PASS_VECTOR)
add_transp_speed(rl, od, NULL, 0.0f, rdrect);
}
@@ -3898,6 +3970,7 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas
zrow[totface].z= apn->z[a];
zrow[totface].p= apn->p[a];
zrow[totface].mask= apn->mask[a];
+ zrow[totface].segment= -1;
totface++;
if(totface>=MAX_ZROW) totface= MAX_ZROW-1;
}
@@ -3905,7 +3978,35 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas
}
apn= apn->next;
}
-
+
+ apnstrand= (APixbufstrand)? apstrand: NULL;
+ while(apnstrand) {
+ for(a=0; a<4; a++) {
+ if(apnstrand->p[a]) {
+ zrow[totface].obi= apnstrand->obi[a];
+ zrow[totface].z= apnstrand->z[a];
+ zrow[totface].p= apnstrand->p[a];
+ zrow[totface].mask= apnstrand->mask[a];
+ zrow[totface].segment= apnstrand->seg[a];
+
+ if(R.osa) {
+ totsample= 0;
+ for(b=0; b<R.osa; b++)
+ if(zrow[totface].mask & (1<<b))
+ totsample++;
+ }
+ else
+ totsample= 1;
+
+ zrow[totface].u= apnstrand->u[a]/totsample;
+ zrow[totface].v= apnstrand->v[a]/totsample;
+ totface++;
+ if(totface>=MAX_ZROW) totface= MAX_ZROW-1;
+ }
+ }
+ apnstrand= apnstrand->next;
+ }
+
if(totface==2) {
if(zrow[0].z < zrow[1].z) {
SWAP(ZTranspRow, zrow[0], zrow[1]);
@@ -3922,19 +4023,22 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas
pa->rectz[od]= zrow[totface-1].z;
if(addpassflag & SCE_PASS_INDEXOB)
- add_transp_obindex(rl, od, zrow[totface-1].obi, zrow[totface-1].p);
-
+ add_transp_obindex(rl, od, zrow[totface-1].obi);
if(R.osa==0) {
while(totface>0) {
totface--;
- if(shade_tra_samples(&ssamp, x, y, &zrow[totface])) {
+ if(shade_tra_samples(&ssamp, sscache, x, y, &zrow[totface], addpassflag)) {
if(addpassflag)
add_transp_passes(rl, od, ssamp.shr, (1.0f-pass[3])*ssamp.shr[0].combined[3]);
addAlphaUnderFloat(pass, ssamp.shr[0].combined);
- if(pass[3]>=0.999) break;
+ if(pass[3]>=0.999) {
+ if(sscache)
+ unref_strand_samples(sscache, zrow, totface);
+ break;
+ }
}
}
if(addpassflag & SCE_PASS_VECTOR)
@@ -3954,16 +4058,16 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas
while(totface>0) {
totface--;
- if(shade_tra_samples(&ssamp, x, y, &zrow[totface])) {
+ if(shade_tra_samples(&ssamp, sscache, x, y, &zrow[totface], addpassflag)) {
filled= addtosamp_shr(samp_shr, &ssamp, addpassflag);
if(ztramask)
*sp |= zrow[totface].mask;
- if(filled==0)
+ if(filled==0) {
+ if(sscache)
+ unref_strand_samples(sscache, zrow, totface);
break;
-
- if(R.totstrand)
- addps(psmlist, pa->rectdaps+od, zrow[totface].obi, zrow[totface].p, zrow[totface].z, zrow[totface].mask);
+ }
}
}
@@ -4006,6 +4110,7 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas
}
aprect+= pa->rectx;
+ aprectstrand+= pa->rectx;
passrect+= 4*pa->rectx;
offs+= pa->rectx;
}
@@ -4014,6 +4119,10 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas
rr->renlay= NULL;
MEM_freeN(APixbuf);
+ if(APixbufstrand)
+ MEM_freeN(APixbufstrand);
+ if(sscache)
+ strand_shade_cache_free(sscache);
freepsA(&apsmbase);
if(R.r.mode & R_SHADOW)