diff options
-rw-r--r-- | source/blender/blenkernel/intern/object.c | 2 | ||||
-rw-r--r-- | source/blender/blenloader/intern/readfile.c | 12 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_lamp_types.h | 9 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_material_types.h | 2 | ||||
-rw-r--r-- | source/blender/render/extern/include/RE_shader_ext.h | 1 | ||||
-rw-r--r-- | source/blender/render/intern/include/render_types.h | 14 | ||||
-rw-r--r-- | source/blender/render/intern/include/shadbuf.h | 44 | ||||
-rw-r--r-- | source/blender/render/intern/include/zbuf.h | 16 | ||||
-rw-r--r-- | source/blender/render/intern/source/convertblender.c | 8 | ||||
-rw-r--r-- | source/blender/render/intern/source/pipeline.c | 3 | ||||
-rw-r--r-- | source/blender/render/intern/source/rendercore.c | 33 | ||||
-rw-r--r-- | source/blender/render/intern/source/shadbuf.c | 1233 | ||||
-rw-r--r-- | source/blender/render/intern/source/zbuf.c | 37 | ||||
-rw-r--r-- | source/blender/src/buttons_shading.c | 54 | ||||
-rw-r--r-- | source/blender/src/drawobject.c | 4 |
15 files changed, 1381 insertions, 91 deletions
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index c36aadee586..47654dc15e4 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -569,7 +569,7 @@ void *add_lamp(void) la->spotsize= 45.0; la->spotblend= 0.15; la->att2= 1.0; - la->mode= LA_SHAD; + la->mode= LA_SHAD_BUF; la->bufsize= 512; la->clipsta= 0.5; la->clipend= 40.0; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index b5c5aa87bbe..82c723fa606 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -5589,6 +5589,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) Scene *sce; Object *ob; Curve *cu; + Material *ma; Nurb *nu; BezTriple *bezt; BPoint *bp; @@ -5617,9 +5618,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } - ob = main->object.first; - - while (ob) { + for(ob = main->object.first; ob; ob= ob->id.next) { ListBase *list; list = &ob->constraints; @@ -5660,8 +5659,11 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } } - - ob = ob->id.next; + } + + for(ma = main->mat.first; ma; ma= ma->id.next) { + if(ma->shad_alpha==0.0f) + ma->shad_alpha= 1.0f; } } diff --git a/source/blender/makesdna/DNA_lamp_types.h b/source/blender/makesdna/DNA_lamp_types.h index f42b9d7f03d..bc233b14fa4 100644 --- a/source/blender/makesdna/DNA_lamp_types.h +++ b/source/blender/makesdna/DNA_lamp_types.h @@ -58,7 +58,8 @@ typedef struct Lamp { float clipsta, clipend, shadspotsize; float bias, soft; - short bufsize, samp, buffers, filtertype, bufflag; + short bufsize, samp, buffers, filtertype; + char bufflag, buftype; short ray_samp, ray_sampy, ray_sampz, ray_samp_type; short area_shape; @@ -93,7 +94,7 @@ typedef struct Lamp { #define LA_YF_PHOTON 5 /* mode */ -#define LA_SHAD 1 +#define LA_SHAD_BUF 1 #define LA_HALO 2 #define LA_LAYER 4 #define LA_QUAD 8 @@ -111,6 +112,10 @@ typedef struct Lamp { /* Since it is used with LOCAL lamp, can't use LA_SHAD */ #define LA_YF_SOFT 16384 +/* buftype, no flag */ +#define LA_SHADBUF_REGULAR 0 +#define LA_SHADBUF_IRREGULAR 1 + /* bufflag, auto clipping */ #define LA_SHADBUF_AUTO_START 1 #define LA_SHADBUF_AUTO_END 2 diff --git a/source/blender/makesdna/DNA_material_types.h b/source/blender/makesdna/DNA_material_types.h index 77820a80aeb..b624f3b769e 100644 --- a/source/blender/makesdna/DNA_material_types.h +++ b/source/blender/makesdna/DNA_material_types.h @@ -77,7 +77,9 @@ typedef struct Material { short flarec, starc, linec, ringc; float hasize, flaresize, subsize, flareboost; float strand_sta, strand_end, strand_ease; + float sbias; /* shadow bias */ + float shad_alpha, padf; /* in use for irregular shadowbuffer */ /* for buttons and render*/ char rgbsel, texact, pr_type, use_nodes; diff --git a/source/blender/render/extern/include/RE_shader_ext.h b/source/blender/render/extern/include/RE_shader_ext.h index 9fdaf8f4e62..25110e4edfb 100644 --- a/source/blender/render/extern/include/RE_shader_ext.h +++ b/source/blender/render/extern/include/RE_shader_ext.h @@ -106,6 +106,7 @@ typedef struct ShadeInput short osatex, puno; int mask; int depth; /* 1 or larger on raytrace shading */ + int facenr; unsigned int lay; } ShadeInput; diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h index 5ff00e7a72c..a429e3027cd 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -49,7 +49,7 @@ struct GHash; #define TABLEINITSIZE 1024 #define LAMPINITSIZE 256 /* hardcoded maximum now, for optimize tables */ -#define MAX_THREADS 2 +#define RE_MAXTHREAD 2 typedef struct SampleTables { @@ -188,6 +188,8 @@ struct Render /* ------------------------------------------------------------------------- */ +struct ISBData; + typedef struct ShadSampleBuf { struct ShadSampleBuf *next, *prev; long *zbuf; @@ -195,6 +197,7 @@ typedef struct ShadSampleBuf { } ShadSampleBuf; typedef struct ShadBuf { + /* regular shadowbuffer */ short samp, shadhalostep, totbuf; float persmat[4][4]; float viewmat[4][4]; @@ -204,6 +207,9 @@ typedef struct ShadBuf { int co[3]; int size, bias; ListBase buffers; + + /* irregular shadowbufer, result stored per thread */ + struct ISBData *isb_result[RE_MAXTHREAD]; } ShadBuf; /* ------------------------------------------------------------------------- */ @@ -304,8 +310,10 @@ typedef struct LampRen short samp; /** Softness factor for shadow */ float soft; - /** amount of subsample buffers */ + /** amount of subsample buffers and type of filter for sampling */ short buffers, filtertype; + /** shadow buffer type (regular, irregular) */ + short buftype; /** autoclip */ short bufflag; /** shadow plus halo: detail level */ @@ -339,7 +347,7 @@ typedef struct LampRen short YF_glowtype; /* ray optim */ - VlakRen *vlr_last[MAX_THREADS]; + VlakRen *vlr_last[RE_MAXTHREAD]; struct MTex *mtex[MAX_MTEX]; } LampRen; diff --git a/source/blender/render/intern/include/shadbuf.h b/source/blender/render/intern/include/shadbuf.h index 8258dea466f..8b786c6e098 100644 --- a/source/blender/render/intern/include/shadbuf.h +++ b/source/blender/render/intern/include/shadbuf.h @@ -61,6 +61,50 @@ float testshadowbuf(struct ShadBuf *shb, float *rco, float *dxco, float *dyco, f */ float shadow_halo(LampRen *lar, float *p1, float *p2); +/** + * Irregular shadowbuffer + */ + +struct MemArena; +struct APixstr; + +void ISB_create(RenderPart *pa, struct APixstr *apixbuf); +void ISB_free(RenderPart *pa); +float ISB_getshadow(ShadeInput *shi, ShadBuf *shb); + +/* data structures have to be accessible both in camview(x, y) as in lampview(x, y) */ +/* since they're created per tile rendered, speed goes over memory requirements */ + + +/* buffer samples, allocated in camera buffer and pointed to in lampbuffer nodes */ +typedef struct ISBSample { + float zco[3]; /* coordinate in lampview projection */ + short *shadfac; /* initialized zero = full lighted */ + int facenr; /* index in faces list */ +} ISBSample; + +/* transparent version of buffer sample */ +typedef struct ISBSampleA { + float zco[3]; /* coordinate in lampview projection */ + short *shadfac; /* NULL = full lighted */ + int facenr; /* index in faces list */ + struct ISBSampleA *next; /* in end, we want the first items to align with ISBSample */ +} ISBSampleA; + +/* used for transparent storage only */ +typedef struct ISBShadfacA { + struct ISBShadfacA *next; + int facenr; + float shadfac; +} ISBShadfacA; + +/* What needs to be stored to evaluate shadow, for each thread in ShadBuf */ +typedef struct ISBData { + short *shadfacs; /* simple storage for solid only */ + ISBShadfacA **shadfaca; + struct MemArena *memarena; + int minx, miny, rectx, recty; /* copy from part disprect */ +} ISBData; #endif /* SHADBUF_EXT_H */ diff --git a/source/blender/render/intern/include/zbuf.h b/source/blender/render/intern/include/zbuf.h index 1ec682c2162..ebad8f241f7 100644 --- a/source/blender/render/intern/include/zbuf.h +++ b/source/blender/render/intern/include/zbuf.h @@ -54,8 +54,9 @@ void convert_zbuf_to_distbuf(struct RenderPart *pa, struct RenderLayer *rl); typedef struct APixstr { unsigned short mask[4]; /* jitter mask */ - int z[4]; /* distance */ - int p[4]; /* index */ + int z[4]; /* distance */ + int p[4]; /* index */ + short shadfac[4]; /* optimize storage for irregular shadow */ struct APixstr *next; } APixstr; @@ -81,6 +82,7 @@ typedef struct ZSpan { 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 */ void (*zbuffunc)(struct ZSpan *, int, float *, float *, float *, float *); @@ -88,10 +90,14 @@ typedef struct ZSpan { } ZSpan; -/* exported for evil edge render... */ +/* exported to shadbuf.c */ +void zbufclip4(struct ZSpan *zspan, int zvlnr, float *f1, float *f2, float *f3, float *f4, int c1, int c2, int c3, int c4); +void zbuf_free_span(struct ZSpan *zspan); + +/* exported to edge render... */ void zbufclip(struct ZSpan *zspan, int zvlnr, float *f1, float *f2, float *f3, int c1, int c2, int c3); -void zbuf_alloc_span(ZSpan *zspan, int rectx, int recty); -void zbufclipwire(ZSpan *zspan, int zvlnr, struct VlakRen *vlr); +void zbuf_alloc_span(struct ZSpan *zspan, int rectx, int recty); +void zbufclipwire(struct ZSpan *zspan, int zvlnr, struct VlakRen *vlr); #endif diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index 54ff0b90541..c1cc2627e4f 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -1242,7 +1242,7 @@ static void static_particle_strand(Render *re, Object *ob, Material *ma, float * flag= R_SMOOTH; /* only 1 pixel wide strands filled in as quads now, otherwise zbuf errors */ - if(width==1.0f) + if(ma->strand_sta==1.0f) flag |= R_STRAND; /* first two vertices */ @@ -2221,6 +2221,7 @@ static LampRen *add_render_lamp(Render *re, Object *ob) lar->samp = la->samp; lar->buffers= la->buffers; if(lar->buffers==0) lar->buffers= 1; + lar->buftype= la->buftype; lar->filtertype= la->filtertype; lar->soft = la->soft; lar->shadhalostep = la->shadhalostep; @@ -2327,7 +2328,7 @@ static LampRen *add_render_lamp(Render *re, Object *ob) lar->spottexfac= 1.0/(xn); if(lar->mode & LA_ONLYSHADOW) { - if((lar->mode & (LA_SHAD|LA_SHAD_RAY))==0) lar->mode -= LA_ONLYSHADOW; + if((lar->mode & (LA_SHAD_BUF|LA_SHAD_RAY))==0) lar->mode -= LA_ONLYSHADOW; } } @@ -2369,7 +2370,7 @@ static LampRen *add_render_lamp(Render *re, Object *ob) /* yafray: shadowbuffers and jitter only needed for internal render */ if (re->r.renderer==R_INTERN) { if(re->r.mode & R_SHADOW) { - if (la->type==LA_SPOT && (lar->mode & LA_SHAD) ) { + if (la->type==LA_SPOT && (lar->mode & LA_SHAD_BUF) ) { /* Per lamp, one shadow buffer is made. */ lar->bufflag= la->bufflag; Mat4CpyMat4(mat, ob->obmat); @@ -3383,6 +3384,7 @@ void RE_Database_FromScene(Render *re, Scene *scene, int use_camera_view) if(re->test_break()) break; if(lar->shb) { + /* if type is irregular, this only sets the perspective matrix and autoclips */ makeshadowbuf(re, lar); } } diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index f6c51753204..5bbc3174a3c 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -1120,7 +1120,8 @@ static void threaded_tile_processor(Render *re) IMB_exrtile_begin_write(rr->exrhandle, str, rr->rectx, rr->recty, rr->rectx/re->xparts, rr->recty/re->yparts); } - if(re->r.mode & R_THREADS) maxthreads= 2; + if(re->r.mode & R_THREADS) + maxthreads= RE_MAXTHREAD; /* should become button value too */ else maxthreads= 1; BLI_init_threads(&threads, do_part_thread, maxthreads); diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index 1cbba7aa144..7e7a790ebad 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -412,7 +412,7 @@ static void renderspothalo(ShadeInput *shi, float *col, float alpha) -/* also used in zbuf.c */ +/* also used in zbuf.c and shadbuf.c */ int count_mask(unsigned short mask) { if(R.samples) @@ -1453,7 +1453,10 @@ static void shade_one_light(LampRen *lar, ShadeInput *shi, ShadeResult *shr, int if(lar->type==LA_HEMI); // no shadow else { if(lar->shb) { - shadfac[3] = testshadowbuf(lar->shb, shi->co, shi->dxco, shi->dyco, inp); + if(lar->buftype==LA_SHADBUF_IRREGULAR) + shadfac[3]= ISB_getshadow(shi, lar->shb); + else + shadfac[3] = testshadowbuf(lar->shb, shi->co, shi->dxco, shi->dyco, inp); } else if(lar->mode & LA_SHAD_RAY) { ray_shadow(shi, lar, shadfac); @@ -2410,9 +2413,9 @@ void *shadepixel(ShadePixelInfo *shpi, float x, float y, int z, volatile int fac ShadeInput shi; VlakRen *vlr=NULL; - /* currently in use for dithering (soft shadow) node preview */ - shi.xs= (int)(x+0.5f); - shi.ys= (int)(y+0.5f); + /* currently in use for dithering (soft shadow), node preview, irregular shad */ + shi.xs= (int)(x); + shi.ys= (int)(y); shi.thread= shpi->thread; shi.do_preview= R.r.scemode & R_NODE_PREVIEW; @@ -2430,7 +2433,8 @@ void *shadepixel(ShadePixelInfo *shpi, float x, float y, int z, volatile int fac VertRen *v1; float alpha, fac, zcor; - vlr= RE_findOrAddVlak(&R, (facenr-1) & RE_QUAD_MASK); + shi.facenr= (facenr-1) & RE_QUAD_MASK; + vlr= RE_findOrAddVlak(&R, shi.facenr); shi.vlr= vlr; shi.mat= vlr->mat; @@ -2959,6 +2963,10 @@ static void shadeDA_tile(RenderPart *pa, RenderLayer *rl) if(R.test_break()) return; + /* irregular shadowb buffer creation */ + if(R.r.mode & R_SHADOW) + ISB_create(pa, NULL); + /* we set per pixel a fixed seed, for random AO and shadow samples */ seed= pa->rectx*pa->disprect.ymin; @@ -3081,6 +3089,9 @@ static void shadeDA_tile(RenderPart *pa, RenderLayer *rl) rectf[2] = invGammaCorrect(rectf[2]); } } + + if(R.r.mode & R_SHADOW) + ISB_free(pa); } /* ************* pixel struct ******** */ @@ -3319,7 +3330,8 @@ void zbufshade_tile(RenderPart *pa) zbuffer_solid(pa, rl->lay, rl->layflag); - if(!R.test_break()) { + if(!R.test_break()) { /* NOTE: this if() is not consistant */ + /* edges only for solid part, ztransp doesn't support it yet anti-aliased */ if(rl->layflag & SCE_LAY_EDGE) if(R.r.mode & R_EDGE) @@ -3333,6 +3345,10 @@ void zbufshade_tile(RenderPart *pa) float *fcol= rl->rectf; int x, y, *rp= pa->rectp, *rz= pa->rectz, offs=0; + /* irregular shadowb buffer creation */ + if(R.r.mode & R_SHADOW) + ISB_create(pa, NULL); + for(y=pa->disprect.ymin; y<pa->disprect.ymax; y++, rr->renrect.ymax++) { for(x=pa->disprect.xmin; x<pa->disprect.xmax; x++, rz++, rp++, fcol+=4, offs++) { shadepixel_sky(&shpi, (float)x, (float)y, *rz, *rp, 0); @@ -3345,6 +3361,9 @@ void zbufshade_tile(RenderPart *pa) if(y&1) if(R.test_break()) break; } + + if(R.r.mode & R_SHADOW) + ISB_free(pa); } else if(rl->layflag & SCE_LAY_SKY) { sky_tile(pa, rl->rectf); diff --git a/source/blender/render/intern/source/shadbuf.c b/source/blender/render/intern/source/shadbuf.c index b9e2562a6c0..fc6e34d0cbb 100644 --- a/source/blender/render/intern/source/shadbuf.c +++ b/source/blender/render/intern/source/shadbuf.c @@ -29,6 +29,7 @@ #include "MTC_matrixops.h" #include "MEM_guardedalloc.h" +#include "DNA_group_types.h" #include "DNA_lamp_types.h" #include "DNA_material_types.h" @@ -38,10 +39,13 @@ #include "BLI_arithb.h" #include "BLI_blenlib.h" #include "BLI_jitter.h" +#include "BLI_memarena.h" +#include "BLI_rand.h" #include "renderpipeline.h" #include "render_types.h" #include "renderdatabase.h" +#include "rendercore.h" #include "shadbuf.h" #include "zbuf.h" @@ -60,6 +64,12 @@ #define ACOMP 3 #endif +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ +/* defined in pipeline.c, is hardcopy of active dynamic allocated Render */ +/* only to be used here in this file, it's for speed */ +extern struct Render R; +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + /* ------------------------------------------------------------------------- */ /* initshadowbuf() in convertBlenderScene.c */ @@ -359,18 +369,13 @@ void makeshadowbuf(Render *re, LampRen *lar) float wsize, *jitbuf, twozero[2]= {0.0f, 0.0f}, angle, temp; int *rectz, samples; - /* jitter, weights */ - shb->jit= give_jitter_tab(shb->samp); - make_jitter_weight_tab(shb, lar->filtertype); - - 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; - if(lar->bufflag & (LA_SHADBUF_AUTO_START|LA_SHADBUF_AUTO_END)) shadowbuf_autoclip(re, lar); + /* just to enforce identical behaviour of all irregular buffers */ + if(lar->buftype==LA_SHADBUF_IRREGULAR) + shb->size= 1024; + /* matrices and window: in winmat the transformation is being put, transforming from observer view to lamp view, including lamp window matrix */ @@ -381,26 +386,38 @@ 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); - /* temp, will be restored */ - MTC_Mat4SwapMat4(shb->persmat, re->winmat); + + if(lar->buftype==LA_SHADBUF_REGULAR) { + /* jitter, weights */ + shb->jit= give_jitter_tab(shb->samp); + make_jitter_weight_tab(shb, lar->filtertype); + + 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; + + /* temp, will be restored */ + MTC_Mat4SwapMat4(shb->persmat, re->winmat); - /* zbuffering */ - rectz= MEM_mapallocN(sizeof(int)*shb->size*shb->size, "makeshadbuf"); + project_renderdata(re, projectvert, 0, 0); + + /* zbuffering */ + rectz= MEM_mapallocN(sizeof(int)*shb->size*shb->size, "makeshadbuf"); + + for(samples=0; samples<shb->totbuf; samples++) { + zbuffer_shadow(re, 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); + } + + MEM_freeN(rectz); + + /* old matrix back */ + MTC_Mat4SwapMat4(shb->persmat, re->winmat); - project_renderdata(re, projectvert, 0, 0); - - for(samples=0; samples<shb->totbuf; samples++) { - zbuffer_shadow(re, 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); + /* printf("lampbuf %d\n", sizeoflampbuf(shb)); */ } - - MEM_freeN(rectz); - - /* old matrix back */ - MTC_Mat4SwapMat4(shb->persmat, re->winmat); - - /* printf("lampbuf %d\n", sizeoflampbuf(shb)); */ } void freeshadowbuf(LampRen *lar) @@ -826,8 +843,1172 @@ float shadow_halo(LampRen *lar, float *p1, float *p2) } +/* ********************* Irregular Shadow Buffer (ISB) ************* */ +/* ********** storage of all view samples in a raster of lists ***** */ + +/* based on several articles describing this method, like: +The Irregular Z-Buffer and its Application to Shadow Mapping +Gregory S. Johnson - William R. Mark - Christopher A. Burns +and +Alias-Free Shadow Maps +Timo Aila and Samuli Laine +*/ + +/* bsp structure (actually kd tree) */ + +#define BSPMAX_SAMPLE 128 +#define BSPMAX_DEPTH 32 + +/* aligned with struct rctf */ +typedef struct Boxf { + float xmin, xmax; + float ymin, ymax; + float zmin, zmax; +} Boxf; + +typedef struct ISBBranch { + struct ISBBranch *left, *right; + float divider[2]; + Boxf box; + short totsamp, index, full, unused; + ISBSample **samples; +} ISBBranch; + +typedef struct BSPFace { + Boxf box; + float *v1, *v2, *v3, *v4; + int facenr; /* index to retrieve VlakRen */ + int type; /* only for strand now */ + short shad_alpha, is_full; + + /* strand caching data, optimize for point_behind_strand() */ + float radline, radline_end, len; + float vec1[3], vec2[3], rc[3]; +} BSPFace; + +/* boxes are in lamp projection */ +static void init_box(Boxf *box) +{ + box->xmin= 1000000.0f; + box->xmax= 0; + box->ymin= 1000000.0f; + box->ymax= 0; + box->zmin= 0x7FFFFFFF; + box->zmax= - 0x7FFFFFFF; +} + +/* use v1 to calculate boundbox */ +static void bound_boxf(Boxf *box, float *v1) +{ + if(v1[0] < box->xmin) box->xmin= v1[0]; + if(v1[0] > box->xmax) box->xmax= v1[0]; + if(v1[1] < box->ymin) box->ymin= v1[1]; + if(v1[1] > box->ymax) box->ymax= v1[1]; + if(v1[2] < box->zmin) box->zmin= v1[2]; + if(v1[2] > box->zmax) box->zmax= v1[2]; +} + +/* use v1 to calculate boundbox */ +static void bound_rectf(rctf *box, float *v1) +{ + if(v1[0] < box->xmin) box->xmin= v1[0]; + if(v1[0] > box->xmax) box->xmax= v1[0]; + if(v1[1] < box->ymin) box->ymin= v1[1]; + if(v1[1] > box->ymax) box->ymax= v1[1]; +} + + +/* halfway splitting, for initializing a more regular tree */ +static void isb_bsp_split_init(ISBBranch *root, MemArena *mem, int level) +{ + + /* if level > 0 we create new branches and go deeper*/ + if(level > 0) { + ISBBranch *left, *right; + int i; + + /* splitpoint */ + root->divider[0]= 0.5f*(root->box.xmin+root->box.xmax); + root->divider[1]= 0.5f*(root->box.ymin+root->box.ymax); + + /* find best splitpoint */ + if(root->box.xmax-root->box.xmin > root->box.ymax-root->box.ymin) + i= root->index= 0; + else + i= root->index= 1; + + left= root->left= BLI_memarena_alloc(mem, sizeof(ISBBranch)); + right= root->right= BLI_memarena_alloc(mem, sizeof(ISBBranch)); + + /* box info */ + left->box= root->box; + right->box= root->box; + if(i==0) { + left->box.xmax= root->divider[0]; + right->box.xmin= root->divider[0]; + } + else { + left->box.ymax= root->divider[1]; + right->box.ymin= root->divider[1]; + } + isb_bsp_split_init(left, mem, level-1); + isb_bsp_split_init(right, mem, level-1); + } + else { + /* we add sample array */ + root->samples= BLI_memarena_alloc(mem, BSPMAX_SAMPLE*sizeof(void *)); + } +} + +/* note; if all samples on same location we just spread them over 2 new branches */ +static void isb_bsp_split(ISBBranch *root, MemArena *mem) +{ + ISBBranch *left, *right; + ISBSample *samples[BSPMAX_SAMPLE]; + int a, i; + + /* splitpoint */ + root->divider[0]= root->divider[1]= 0.0f; + for(a=BSPMAX_SAMPLE-1; a>=0; a--) { + root->divider[0]+= root->samples[a]->zco[0]; + root->divider[1]+= root->samples[a]->zco[1]; + } + root->divider[0]/= BSPMAX_SAMPLE; + root->divider[1]/= BSPMAX_SAMPLE; + + /* find best splitpoint */ + if(root->box.xmax-root->box.xmin > root->box.ymax-root->box.ymin) + i= root->index= 0; + else + i= root->index= 1; + + /* new branches */ + left= root->left= BLI_memarena_alloc(mem, sizeof(ISBBranch)); + right= root->right= BLI_memarena_alloc(mem, sizeof(ISBBranch)); + + /* new sample array */ + left->samples= BLI_memarena_alloc(mem, BSPMAX_SAMPLE*sizeof(void *)); + right->samples= samples; // tmp + + /* split samples */ + for(a=BSPMAX_SAMPLE-1; a>=0; a--) { + int comp= 0; + /* this prevents adding samples all to 1 branch when divider is equal to samples */ + if(root->samples[a]->zco[i] == root->divider[i]) + comp= a & 1; + else if(root->samples[a]->zco[i] < root->divider[i]) + comp= 1; + + if(comp==1) { + left->samples[left->totsamp]= root->samples[a]; + left->totsamp++; + } + else { + right->samples[right->totsamp]= root->samples[a]; + right->totsamp++; + } + } + + /* copy samples from tmp */ + memcpy(root->samples, samples, right->totsamp*(sizeof(void *))); + right->samples= root->samples; + root->samples= NULL; + + /* box info */ + left->box= root->box; + right->box= root->box; + if(i==0) { + left->box.xmax= root->divider[0]; + right->box.xmin= root->divider[0]; + } + else { + left->box.ymax= root->divider[1]; + right->box.ymin= root->divider[1]; + } +} + +/* inserts sample in main tree, also splits on threshold */ +/* returns 1 if error */ +static int isb_bsp_insert(ISBBranch *root, MemArena *memarena, ISBSample *sample) +{ + ISBBranch *bspn= root; + float *zco= sample->zco; + int i= 0; + + /* debug counter, also used to check if something was filled in ever */ + root->totsamp++; + + /* going over branches until last one found */ + while(bspn->left) { + if(zco[bspn->index] <= bspn->divider[bspn->index]) + bspn= bspn->left; + else + bspn= bspn->right; + i++; + } + /* bspn now is the last branch */ + + if(bspn->totsamp==BSPMAX_SAMPLE) { + printf("error in bsp branch\n"); /* only for debug, cannot happen */ + return 1; + } + + /* insert */ + bspn->samples[bspn->totsamp]= sample; + bspn->totsamp++; + + /* split if allowed and needed */ + if(bspn->totsamp==BSPMAX_SAMPLE) { + if(i==BSPMAX_DEPTH) { + bspn->totsamp--; /* stop filling in... will give errors */ + return 1; + } + isb_bsp_split(bspn, memarena); + } + return 0; +} + +static float VecLen2f( float *v1, float *v2) +{ + float x= v1[0]-v2[0]; + float y= v1[1]-v2[1]; + return (float)sqrt(x*x+y*y); +} + +/* initialize vars in face, for optimal point-in-face test */ +static void bspface_init_strand(BSPFace *face) +{ + + face->radline= 0.5f*VecLen2f(face->v1, face->v2); + + VecMidf(face->vec1, face->v1, face->v2); + if(face->v4) + VecMidf(face->vec2, face->v3, face->v4); + else + VECCOPY(face->vec2, face->v3); + + face->rc[0]= face->vec2[0]-face->vec1[0]; + face->rc[1]= face->vec2[1]-face->vec1[1]; + face->rc[2]= face->vec2[2]-face->vec1[2]; + + face->len= face->rc[0]*face->rc[0]+ face->rc[1]*face->rc[1]; + + if(face->len!=0.0f) { + face->radline_end= face->radline/sqrt(face->len); + face->len= 1.0f/face->len; + } +} + +/* brought back to a simple 2d case */ +static int point_behind_strand(float *p, BSPFace *face) +{ + /* v1 - v2 is radius, v1 - v3 length */ + float dist, rc[2], pt[2]; + + /* using code from PdistVL2Dfl(), distance vec to line-piece */ + + if(face->len==0.0f) { + rc[0]= p[0]-face->vec1[0]; + rc[1]= p[1]-face->vec1[1]; + dist= (float)(sqrt(rc[0]*rc[0]+ rc[1]*rc[1])); + + if(dist < face->radline) + return 1; + } + else { + float labda= ( face->rc[0]*(p[0]-face->vec1[0]) + face->rc[1]*(p[1]-face->vec1[1]) )*face->len; + + if(labda > -face->radline_end && labda < 1.0f+face->radline_end) { + /* hesse for dist: */ + //dist= (float)(fabs( (p[0]-vec2[0])*rc[1] + (p[1]-vec2[1])*rc[0])/len); + + pt[0]= labda*face->rc[0]+face->vec1[0]; + pt[1]= labda*face->rc[1]+face->vec1[1]; + + rc[0]= pt[0]-p[0]; + rc[1]= pt[1]-p[1]; + dist= (float)sqrt(rc[0]*rc[0]+ rc[1]*rc[1]); + + if(dist < face->radline) { + float zval= face->vec1[2] + labda*face->rc[2]; + if(p[2] > zval) + return 1; + } + } + } + return 0; +} + + +/* return 1 if inside. code derived from src/parametrizer.c */ +static int point_behind_tria2d(float *p, float *v1, float *v2, float *v3) +{ + float a[2], c[2], h[2], div; + float u, v; + + a[0] = v2[0] - v1[0]; + a[1] = v2[1] - v1[1]; + c[0] = v3[0] - v1[0]; + c[1] = v3[1] - v1[1]; + + div = a[0]*c[1] - a[1]*c[0]; + if(div==0.0f) + return 0; + + h[0] = p[0] - v1[0]; + h[1] = p[1] - v1[1]; + + div = 1.0f/div; + + u = (h[0]*c[1] - h[1]*c[0])*div; + if(u >= 0.0f) { + v = (a[0]*h[1] - a[1]*h[0])*div; + if(v >= 0.0f) { + if( u + v <= 1.0f) { + /* inside, now check if point p is behind */ + float z= (1.0f-u-v)*v1[2] + u*v2[2] + v*v3[2]; + if(z <= p[2]) + return 1; + } + } + } + + return 0; +} + +#if 0 +/* tested these calls, but it gives inaccuracy, 'side' cannot be found reliably using v3 */ + +/* check if line v1-v2 has all rect points on other side of point v3 */ +static int rect_outside_line(rctf *rect, float *v1, float *v2, float *v3) +{ + float a, b, c; + int side; + + /* line formula for v1-v2 */ + a= v2[1]-v1[1]; + b= v1[0]-v2[0]; + c= -a*v1[0] - b*v1[1]; + side= a*v3[0] + b*v3[1] + c < 0.0f; + + /* the four quad points */ + if( side==(rect->xmin*a + rect->ymin*b + c >= 0.0f) ) + if( side==(rect->xmax*a + rect->ymin*b + c >= 0.0f) ) + if( side==(rect->xmax*a + rect->ymax*b + c >= 0.0f) ) + if( side==(rect->xmin*a + rect->ymax*b + c >= 0.0f) ) + return 1; + return 0; +} + +/* check if one of the triangle edges separates all rect points on 1 side */ +static int rect_isect_tria(rctf *rect, float *v1, float *v2, float *v3) +{ + if(rect_outside_line(rect, v1, v2, v3)) + return 0; + if(rect_outside_line(rect, v2, v3, v1)) + return 0; + if(rect_outside_line(rect, v3, v1, v2)) + return 0; + return 1; +} +#endif + +/* if face overlaps a branch, it executes func. recursive */ +static void isb_bsp_face_inside(ISBBranch *bspn, BSPFace *face) +{ + + /* are we descending? */ + if(bspn->left) { + /* hrmf, the box struct cannot be addressed with index */ + if(bspn->index==0) { + if(face->box.xmin <= bspn->divider[0]) + isb_bsp_face_inside(bspn->left, face); + if(face->box.xmax > bspn->divider[0]) + isb_bsp_face_inside(bspn->right, face); + } + else { + if(face->box.ymin <= bspn->divider[1]) + isb_bsp_face_inside(bspn->left, face); + if(face->box.ymax > bspn->divider[1]) + isb_bsp_face_inside(bspn->right, face); + } + } + else { + /* else: end branch reached */ + int a; + + if(bspn->totsamp==0) return; + + /* check for nodes entirely in shadow, can be skipped */ + if(bspn->totsamp==bspn->full) + return; + + /* if bsp node is entirely in front of face, give up */ + if(bspn->box.zmax < face->box.zmin) + return; + + /* if face boundbox is outside of branch rect, give up */ + if(0==BLI_isect_rctf((rctf *)&face->box, (rctf *)&bspn->box, NULL)) + return; + + /* test all points inside branch */ + for(a=bspn->totsamp-1; a>=0; a--) { + ISBSample *samp= bspn->samples[a]; + + if(samp->facenr!=face->facenr && samp->shadfac) { + if(face->box.zmax < samp->zco[2]) { + if(BLI_in_rctf((rctf *)&face->box, samp->zco[0], samp->zco[1])) { + int inshadow= 0; + + if(face->type) { + if(point_behind_strand(samp->zco, face)) + inshadow= 1; + } + else if( point_behind_tria2d(samp->zco, face->v1, face->v2, face->v3)) + inshadow= 1; + else if(face->v4 && point_behind_tria2d(samp->zco, face->v1, face->v3, face->v4)) + inshadow= 1; + + if(inshadow) { + *(samp->shadfac) += face->shad_alpha; + /* optimize; is_full means shad_alpha==4096 */ + if(*(samp->shadfac) >= 4096 || face->is_full) { + bspn->full++; + samp->shadfac= NULL; + } + } + } + } + } + } + } +} + +/* based on available samples, recalculate the bounding box for bsp nodes, recursive */ +static void isb_bsp_recalc_box(ISBBranch *root) +{ + if(root->left) { + isb_bsp_recalc_box(root->left); + isb_bsp_recalc_box(root->right); + } + else if(root->totsamp) { + int a; + + init_box(&root->box); + for(a=root->totsamp-1; a>=0; a--) + bound_boxf(&root->box, root->samples[a]->zco); + } +} + +/* callback function for zbuf clip */ +static void isb_bsp_test_strand(ZSpan *zspan, int zvlnr, float *v1, float *v2, float *v3, float *v4) +{ + BSPFace face; + + face.v1= v1; + face.v2= v2; + face.v3= v3; + face.v4= v4; + face.facenr= zvlnr & ~RE_QUAD_OFFS; + face.type= R_STRAND; + if(R.osa) + face.shad_alpha= (short)ceil(4096.0f*zspan->shad_alpha/(float)R.osa); + else + face.shad_alpha= (short)ceil(4096.0f*zspan->shad_alpha); + + face.is_full= (zspan->shad_alpha==1.0f); + + /* setup boundbox */ + init_box(&face.box); + bound_boxf(&face.box, v1); + bound_boxf(&face.box, v2); + bound_boxf(&face.box, v3); + if(v4) + bound_boxf(&face.box, v4); + + /* optimize values */ + bspface_init_strand(&face); + + isb_bsp_face_inside((ISBBranch *)zspan->rectz, &face); + +} +/* callback function for zbuf clip */ +static void isb_bsp_test_face(ZSpan *zspan, int zvlnr, float *v1, float *v2, float *v3, float *v4) +{ + BSPFace face; + + face.v1= v1; + face.v2= v2; + face.v3= v3; + face.v4= v4; + face.facenr= zvlnr & ~RE_QUAD_OFFS; + face.type= 0; + if(R.osa) + face.shad_alpha= (short)ceil(4096.0f*zspan->shad_alpha/(float)R.osa); + else + face.shad_alpha= (short)ceil(4096.0f*zspan->shad_alpha); + + face.is_full= (zspan->shad_alpha==1.0f); + + /* setup boundbox */ + init_box(&face.box); + bound_boxf(&face.box, v1); + bound_boxf(&face.box, v2); + bound_boxf(&face.box, v3); + if(v4) + bound_boxf(&face.box, v4); + + isb_bsp_face_inside((ISBBranch *)zspan->rectz, &face); +} +static int testclip_minmax(float *ho, float *minmax) +{ + float wco= ho[3]; + int flag= 0; + + if( ho[0] > minmax[1]*wco) flag = 1; + else if( ho[0]< minmax[0]*wco) flag = 2; + + if( ho[1] > minmax[3]*wco) flag |= 4; + else if( ho[1]< minmax[2]*wco) flag |= 8; + + return flag; +} + +/* main loop going over all faces and check in bsp overlaps, fill in shadfac values */ +static void isb_bsp_fillfaces(Render *re, LampRen *lar, ISBBranch *root) +{ + ShadBuf *shb= lar->shb; + ZSpan zspan, zspanstrand; + VlakRen *vlr= NULL; + Material *ma= NULL; + float minmaxf[4]; + int size= shb->size; + int a, ok=1, lay= -1; + + /* further optimize, also sets minz maxz */ + isb_bsp_recalc_box(root); + + /* extra clipping for minmax */ + minmaxf[0]= (2.0f*root->box.xmin - size-2.0f)/size; + minmaxf[1]= (2.0f*root->box.xmax - size+2.0f)/size; + minmaxf[2]= (2.0f*root->box.ymin - size-2.0f)/size; + minmaxf[3]= (2.0f*root->box.ymax - size+2.0f)/size; + + if(lar->mode & LA_LAYER) lay= lar->lay; + + /* (ab)use zspan, since we use zbuffer clipping code */ + zbuf_alloc_span(&zspan, size, size); + + zspan.zmulx= ((float)size)/2.0f; + zspan.zmuly= ((float)size)/2.0f; + zspan.zofsx= -0.5f; + zspan.zofsy= -0.5f; + + /* pass on bsp root to zspan */ + zspan.rectz= (int *)root; + + /* filling methods */ + zspanstrand= zspan; + // zspan.zbuflinefunc= zbufline_onlyZ; + zspan.zbuffunc= isb_bsp_test_face; + zspanstrand.zbuffunc= isb_bsp_test_strand; + + for(a=0; a<re->totvlak; a++) { + + if((a & 255)==0) vlr= re->blovl[a>>8]; + else vlr++; + + /* note, these conditions are copied in shadowbuf_autoclip() */ + if(vlr->mat!= ma) { + ma= vlr->mat; + ok= 1; + if((ma->mode & MA_SHADBUF)==0) ok= 0; + zspanstrand.shad_alpha= zspan.shad_alpha= ma->shad_alpha; + } + + if(ok && (vlr->lay & lay)) { + float hoco[4][4]; + int c1, c2, c3, c4=0; + int d1, d2, d3, d4=0; + int partclip; + + /* create hocos per face, it is while render */ + projectvert(vlr->v1->co, shb->persmat, hoco[0]); d1= testclip_minmax(hoco[0], minmaxf); + projectvert(vlr->v2->co, shb->persmat, hoco[1]); d2= testclip_minmax(hoco[1], minmaxf); + projectvert(vlr->v3->co, shb->persmat, hoco[2]); d3= testclip_minmax(hoco[2], minmaxf); + if(vlr->v4) { + projectvert(vlr->v4->co, shb->persmat, hoco[3]); d4= testclip_minmax(hoco[3], minmaxf); + } + + /* minmax clipping */ + if(vlr->v4) partclip= d1 & d2 & d3 & d4; + else partclip= d1 & d2 & d3; + + if(partclip==0) { + + /* window clipping */ + c1= testclip(hoco[0]); + c2= testclip(hoco[1]); + c3= testclip(hoco[2]); + if(vlr->v4) + c4= testclip(hoco[3]); + + /* ***** NO WIRE YET */ + if(ma->mode & MA_WIRE) + zbufclipwire(&zspan, a+1, vlr); + else if(vlr->v4) { + if(vlr->flag & R_STRAND) + zbufclip4(&zspanstrand, a+1, hoco[0], hoco[1], hoco[2], hoco[3], c1, c2, c3, c4); + else + zbufclip4(&zspan, a+1, hoco[0], hoco[1], hoco[2], hoco[3], c1, c2, c3, c4); + } + else + zbufclip(&zspan, a+1, hoco[0], hoco[1], hoco[2], c1, c2, c3); + + } + } + } + + zbuf_free_span(&zspan); + +} + + +/* returns 1 when the viewpixel is visible in lampbuffer */ +static int viewpixel_to_lampbuf(ShadBuf *shb, VlakRen *vlr, float x, float y, float *co) +{ + float hoco[4], *v1= vlr->v1->co, *nor= vlr->n; + float dface, fac, siz; + + /* from shadepixel() */ + dface= v1[0]*nor[0] + v1[1]*nor[1] + v1[2]*nor[2]; + hoco[3]= 1.0f; + + /* ortho viewplane cannot intersect using view vector originating in (0,0,0) */ + if(R.r.mode & R_ORTHO) { + /* x and y 3d coordinate can be derived from pixel coord and winmat */ + float fx= 2.0/(R.winx*R.winmat[0][0]); + float fy= 2.0/(R.winy*R.winmat[1][1]); + + hoco[0]= (x - 0.5*R.winx)*fx - R.winmat[3][0]/R.winmat[0][0]; + hoco[1]= (y - 0.5*R.winy)*fy - R.winmat[3][1]/R.winmat[1][1]; + + /* using a*x + b*y + c*z = d equation, (a b c) is normal */ + if(nor[2]!=0.0f) + hoco[2]= (dface - nor[0]*hoco[0] - nor[1]*hoco[1])/nor[2]; + else + hoco[2]= 0.0f; + } + else { + float div, view[3]; + + calc_view_vector(view, x, y); + + div= nor[0]*view[0] + nor[1]*view[1] + nor[2]*view[2]; + if (div==0.0f) + return 0; + + fac= dface/div; + + hoco[0]= fac*view[0]; + hoco[1]= fac*view[1]; + hoco[2]= fac*view[2]; + } + + /* move 3d vector to lampbuf */ + MTC_Mat4MulVec4fl(shb->persmat, hoco); /* rational hom co */ + + /* clip We can test for -1.0/1.0 because of the properties of the + * coordinate transformations. */ + if(hoco[0]<-hoco[3] || hoco[0]>hoco[3]) + return 0; + if(hoco[1]<-hoco[3] || hoco[1]>hoco[3]) + return 0; + + siz= 0.5f*(float)shb->size; + co[0]= siz*(1.0f+hoco[0]/hoco[3]) -0.5f; + co[1]= siz*(1.0f+hoco[1]/hoco[3]) -0.5f; + + /* Clip for z: clipsta and clipend clip values of the shadow buffer */ + fac= (hoco[2]/hoco[3]); + + if(fac >= 1.0f || fac <= -1.0f) + return 0; + else + co[2]= ((float)0x7FFFFFFF)*fac; + + /* XXXX bias, much less than normal shadbuf, or do we need a constant? */ + co[2] -= 0.05f*shb->bias; + + return 1; +} + + +/* adding samples, solid case */ +static int isb_add_samples(RenderPart *pa, ISBBranch *root, MemArena *memarena, ISBSample **samplebuf) +{ + int xi, yi, *xcos, *ycos; + int sample, bsp_err= 0; + + /* bsp split doesn't like to handle regular sequenes */ + xcos= MEM_mallocN( pa->rectx*sizeof(int), "xcos"); + ycos= MEM_mallocN( pa->recty*sizeof(int), "ycos"); + for(xi=0; xi<pa->rectx; xi++) + xcos[xi]= xi; + for(yi=0; yi<pa->recty; yi++) + ycos[yi]= yi; + BLI_array_randomize(xcos, sizeof(int), pa->rectx, 12345); + BLI_array_randomize(ycos, sizeof(int), pa->recty, 54321); + + for(sample=0; sample<(R.osa?R.osa:1); sample++) { + ISBSample *samp= samplebuf[sample], *samp1; + + for(yi=0; yi<pa->recty; yi++) { + int y= ycos[yi]; + for(xi=0; xi<pa->rectx; xi++) { + int x= xcos[xi]; + samp1= samp + y*pa->rectx + x; + if(samp1->facenr) + bsp_err |= isb_bsp_insert(root, memarena, samp1); + } + if(bsp_err) break; + } + } + + MEM_freeN(xcos); + MEM_freeN(ycos); + + return bsp_err; +} + +/* solid version */ +/* lar->shb, pa->rectz and pa->rectp should exist */ +static void isb_make_buffer(RenderPart *pa, LampRen *lar) +{ + ShadBuf *shb= lar->shb; + ISBData *isbdata; + ISBSample *samp, *samplebuf[16]; /* should be RE_MAX_OSA */ + ISBBranch root; + MemArena *memarena; + long *rd; + int *rectp, x, y, sindex, sample, bsp_err=0; + + /* storage for shadow, per thread */ + isbdata= shb->isb_result[pa->thread]; + + /* to map the shi->xs and ys coordinate */ + isbdata->minx= pa->disprect.xmin; + isbdata->miny= pa->disprect.ymin; + isbdata->rectx= pa->rectx; + isbdata->recty= pa->recty; + + /* branches are added using memarena (32k branches) */ + memarena = BLI_memarena_new(0x8000 * sizeof(ISBBranch)); + + /* samplebuf is in camera view space (pixels) */ + for(sample=0; sample<(R.osa?R.osa:1); sample++) + samplebuf[sample]= MEM_callocN(sizeof(ISBSample)*pa->rectx*pa->recty, "isb samplebuf"); + + /* end result, ISBSamples point to this */ + isbdata->shadfacs= MEM_callocN(pa->rectx*pa->recty*sizeof(short), "isb shadfacs"); + + /* setup bsp root */ + memset(&root, 0, sizeof(ISBBranch)); + root.box.xmin= (float)shb->size; + root.box.ymin= (float)shb->size; + + /* create the sample buffers */ + for(sindex=0, y=0; y<pa->recty; y++) { + for(x=0; x<pa->rectx; x++, sindex++) { + + /* this makes it a long function, but splitting it out would mean 10+ arguments */ + /* first check OSA case */ + if(R.osa) { + rd= pa->rectdaps + sindex; + if(*rd) { + float xs= (float)(x + pa->disprect.xmin); + float ys= (float)(y + pa->disprect.ymin); + + for(sample=0; sample<R.osa; sample++) { + PixStr *ps= (PixStr *)(*rd); + int mask= (1<<sample); + + while(ps) { + if(ps->mask & mask) + break; + ps= ps->next; + } + if(ps && ps->facenr>0) { + VlakRen *vlr= RE_findOrAddVlak(&R, (ps->facenr-1) & RE_QUAD_MASK); + + samp= samplebuf[sample] + sindex; + /* convert image plane pixel location to lamp buffer space */ + if(viewpixel_to_lampbuf(shb, vlr, xs + R.jit[sample][0], ys + R.jit[sample][1], samp->zco)) { + samp->facenr= ps->facenr & ~RE_QUAD_OFFS; + samp->shadfac= isbdata->shadfacs + sindex; + bound_rectf((rctf *)&root.box, samp->zco); + } + } + } + } + } + else { + rectp= pa->rectp + sindex; + if(*rectp>0) { + VlakRen *vlr= RE_findOrAddVlak(&R, (*rectp-1) & RE_QUAD_MASK); + float xs= (float)(x + pa->disprect.xmin); + float ys= (float)(y + pa->disprect.ymin); + + samp= samplebuf[0] + sindex; + /* convert image plane pixel location to lamp buffer space */ + if(viewpixel_to_lampbuf(shb, vlr, xs, ys, samp->zco)) { + samp->facenr= *rectp & ~RE_QUAD_OFFS; + samp->shadfac= isbdata->shadfacs + sindex; + bound_rectf((rctf *)&root.box, samp->zco); + } + } + } + } + } + + /* simple method to see if we have samples */ + if(root.box.xmin != (float)shb->size) { + /* now create a regular split, root.box has the initial bounding box of all pixels */ + /* split bsp 8 levels deep, in regular grid (16 x 16) */ + isb_bsp_split_init(&root, memarena, 8); + + /* insert all samples in BSP now */ + bsp_err= isb_add_samples(pa, &root, memarena, samplebuf); + + if(bsp_err==0) { + /* go over all faces and fill in shadow values */ + + isb_bsp_fillfaces(&R, lar, &root); /* shb->persmat should have been calculated */ + } + } + else { + MEM_freeN(isbdata->shadfacs); + isbdata->shadfacs= NULL; + } + + /* free BSP */ + BLI_memarena_free(memarena); + + /* free samples */ + for(x=0; x<(R.osa?R.osa:1); x++) + MEM_freeN(samplebuf[x]); + + if(bsp_err) printf("error in filling bsp\n"); +} + +/* add sample to buffer, isbsa is the root sample in a buffer */ +static ISBSampleA *isb_alloc_sample_transp(ISBSampleA **isbsa, MemArena *mem) +{ + ISBSampleA *new; + + new= BLI_memarena_alloc(mem, sizeof(ISBSampleA)); + if(*isbsa) + new->next= (*isbsa); + + *isbsa= new; + return new; +} + +/* adding samples in BSP, transparent case */ +static int isb_add_samples_transp(RenderPart *pa, ISBBranch *root, MemArena *memarena, ISBSampleA ***samplebuf) +{ + int xi, yi, *xcos, *ycos; + int sample, bsp_err= 0; + + /* bsp split doesn't like to handle regular sequenes */ + xcos= MEM_mallocN( pa->rectx*sizeof(int), "xcos"); + ycos= MEM_mallocN( pa->recty*sizeof(int), "ycos"); + for(xi=0; xi<pa->rectx; xi++) + xcos[xi]= xi; + for(yi=0; yi<pa->recty; yi++) + ycos[yi]= yi; + BLI_array_randomize(xcos, sizeof(int), pa->rectx, 12345); + BLI_array_randomize(ycos, sizeof(int), pa->recty, 54321); + + for(sample=0; sample<(R.osa?R.osa:1); sample++) { + ISBSampleA **samp= samplebuf[sample], *samp1; + + for(yi=0; yi<pa->recty; yi++) { + int y= ycos[yi]; + for(xi=0; xi<pa->rectx; xi++) { + int x= xcos[xi]; + + samp1= *(samp + y*pa->rectx + x); + while(samp1) { + bsp_err |= isb_bsp_insert(root, memarena, (ISBSample *)samp1); + samp1= samp1->next; + } + } + if(bsp_err) break; + } + } + + MEM_freeN(xcos); + MEM_freeN(ycos); + + return bsp_err; +} + +/* storage of shadow results, transparent case */ +static void isb_add_shadfac_transp(ISBShadfacA **isbsapp, MemArena *mem, int facenr, short shadfac, short samples) +{ + ISBShadfacA *new; + float shadfacf; + + /* in osa case, the samples were filled in with factor 1.0/R.osa. if fewer samples we have to correct */ + if(R.osa) + shadfacf= ((float)shadfac*R.osa)/(4096.0*samples); + else + shadfacf= ((float)shadfac)/(4096.0); + + new= BLI_memarena_alloc(mem, sizeof(ISBShadfacA)); + new->facenr= facenr & ~RE_QUAD_OFFS; + new->shadfac= shadfacf; + if(*isbsapp) + new->next= (*isbsapp); + + *isbsapp= new; +} + +/* Ztransp version */ +/* lar->shb, pa->rectz and pa->rectp should exist */ +static void isb_make_buffer_transp(RenderPart *pa, APixstr *apixbuf, LampRen *lar) +{ + ShadBuf *shb= lar->shb; + ISBData *isbdata; + ISBSampleA *samp, **samplebuf[16]; /* MAX_OSA */ + ISBBranch root; + MemArena *memarena; + APixstr *ap; + int x, y, sindex, sample, bsp_err=0; + + /* storage for shadow, per thread */ + isbdata= shb->isb_result[pa->thread]; + + /* to map the shi->xs and ys coordinate */ + isbdata->minx= pa->disprect.xmin; + isbdata->miny= pa->disprect.ymin; + isbdata->rectx= pa->rectx; + isbdata->recty= pa->recty; + + /* branches are added using memarena (32k branches) */ + memarena = BLI_memarena_new(0x8000 * sizeof(ISBBranch)); + + /* samplebuf is in camera view space (pixels) */ + for(sample=0; sample<(R.osa?R.osa:1); sample++) + samplebuf[sample]= MEM_callocN(sizeof(void *)*pa->rectx*pa->recty, "isb alpha samplebuf"); + + /* setup bsp root */ + memset(&root, 0, sizeof(ISBBranch)); + root.box.xmin= (float)shb->size; + root.box.ymin= (float)shb->size; + + /* create the sample buffers */ + for(ap= apixbuf, sindex=0, y=0; y<pa->recty; y++) { + for(x=0; x<pa->rectx; x++, sindex++, ap++) { + + if(ap->p[0]) { + APixstr *apn; + float xs= (float)(x + pa->disprect.xmin); + float ys= (float)(y + pa->disprect.ymin); + + for(apn=ap; apn; apn= apn->next) { + int a; + for(a=0; a<4; a++) { + if(apn->p[a]) { + VlakRen *vlr= RE_findOrAddVlak(&R, (apn->p[a]-1) & RE_QUAD_MASK); + float zco[3]; + + /* here we store shadfac, easier to create the end storage buffer. needs zero'ed, multiple shadowbufs use it */ + apn->shadfac[a]= 0; + + if(R.osa) { + for(sample=0; sample<R.osa; sample++) { + int mask= (1<<sample); + + if(apn->mask[a] & mask) { + + /* convert image plane pixel location to lamp buffer space */ + if(viewpixel_to_lampbuf(shb, vlr, xs + R.jit[sample][0], ys + R.jit[sample][1], zco)) { + samp= isb_alloc_sample_transp(samplebuf[sample] + sindex, memarena); + samp->facenr= apn->p[a] & ~RE_QUAD_OFFS; + samp->shadfac= &apn->shadfac[a]; + + VECCOPY(samp->zco, zco); + bound_rectf((rctf *)&root.box, samp->zco); + } + } + } + } + else { + + /* convert image plane pixel location to lamp buffer space */ + if(viewpixel_to_lampbuf(shb, vlr, xs, ys, zco)) { + + samp= isb_alloc_sample_transp(samplebuf[0] + sindex, memarena); + samp->facenr= apn->p[a] & ~RE_QUAD_OFFS; + samp->shadfac= &apn->shadfac[a]; + + VECCOPY(samp->zco, zco); + bound_rectf((rctf *)&root.box, samp->zco); + } + } + } + } + } + } + } + } + + /* simple method to see if we have samples */ + if(root.box.xmin != (float)shb->size) { + /* now create a regular split, root.box has the initial bounding box of all pixels */ + /* split bsp 8 levels deep, in regular grid (16 x 16) */ + isb_bsp_split_init(&root, memarena, 8); + + /* insert all samples in BSP now */ + bsp_err= isb_add_samples_transp(pa, &root, memarena, samplebuf); + + if(bsp_err==0) { + ISBShadfacA **isbsa; + + /* go over all faces and fill in shadow values */ + isb_bsp_fillfaces(&R, lar, &root); /* shb->persmat should have been calculated */ + + /* copy shadow samples to persistant buffer, reduce memory overhead */ + isbsa= isbdata->shadfaca= MEM_callocN(pa->rectx*pa->recty*sizeof(void *), "isb shadfacs"); + + isbdata->memarena = BLI_memarena_new(0x8000 * sizeof(ISBSampleA)); + + for(ap= apixbuf, x=pa->rectx*pa->recty; x>0; x--, ap++, isbsa++) { + + if(ap->p[0]) { + APixstr *apn; + for(apn=ap; apn; apn= apn->next) { + int a; + for(a=0; a<4; a++) { + if(apn->p[a] && apn->shadfac[a]) { + if(R.osa) + isb_add_shadfac_transp(isbsa, isbdata->memarena, apn->p[a], apn->shadfac[a], count_mask(apn->mask[a])); + else + isb_add_shadfac_transp(isbsa, isbdata->memarena, apn->p[a], apn->shadfac[a], 0); + } + } + } + } + } + } + } + + /* free BSP */ + BLI_memarena_free(memarena); + + /* free samples */ + for(x=0; x<(R.osa?R.osa:1); x++) + MEM_freeN(samplebuf[x]); + + if(bsp_err) printf("error in filling bsp\n"); +} + + + +/* exported */ + +/* returns amount of light (1.0 = no shadow) */ +/* note, shadepixel() rounds the coordinate, not the real sample info */ +float ISB_getshadow(ShadeInput *shi, ShadBuf *shb) +{ + /* if raytracing, we can't accept irregular shadow */ + if(shi->depth==0) { + ISBData *isbdata= shb->isb_result[shi->thread]; + + if(isbdata) { + if(isbdata->shadfacs || isbdata->shadfaca) { + int x= shi->xs - isbdata->minx; + + if(x >= 0 && x < isbdata->rectx) { + int y= shi->ys - isbdata->miny; + + if(y >= 0 && y < isbdata->recty) { + if(isbdata->shadfacs) { + short *sp= isbdata->shadfacs + y*isbdata->rectx + x; + return *sp>=4096?0.0f:1.0f - ((float)*sp)/4096.0f; + } + else { + int sindex= y*isbdata->rectx + x; + ISBShadfacA *isbsa= *(isbdata->shadfaca + sindex); + + while(isbsa) { + if(isbsa->facenr==shi->facenr+1) + return isbsa->shadfac>=1.0f?0.0f:1.0f - isbsa->shadfac; + isbsa= isbsa->next; + } + } + } + } + } + } + } + return 1.0f; +} + +/* part is supposed to be solid zbuffered (apixbuf==NULL) or transparent zbuffered */ +void ISB_create(RenderPart *pa, APixstr *apixbuf) +{ + GroupObject *go; + + /* go over all lamps, and make the irregular buffers */ + for(go=R.lights.first; go; go= go->next) { + LampRen *lar= go->lampren; + + if(lar->type==LA_SPOT && lar->shb && lar->buftype==LA_SHADBUF_IRREGULAR) { + + /* create storage for shadow, per thread */ + lar->shb->isb_result[pa->thread]= MEM_callocN(sizeof(ISBData), "isb data"); + + if(apixbuf) + isb_make_buffer_transp(pa, apixbuf, lar); + else + isb_make_buffer(pa, lar); + } + } +} + + +/* end of part rendering, free stored shadow data for this thread from all lamps */ +void ISB_free(RenderPart *pa) +{ + GroupObject *go; + + /* go over all lamps, and free the irregular buffers */ + for(go=R.lights.first; go; go= go->next) { + LampRen *lar= go->lampren; + + if(lar->type==LA_SPOT && lar->shb && lar->buftype==LA_SHADBUF_IRREGULAR) { + ISBData *isbdata= lar->shb->isb_result[pa->thread]; + + if(isbdata) { + if(isbdata->shadfacs) + MEM_freeN(isbdata->shadfacs); + if(isbdata->shadfaca) + MEM_freeN(isbdata->shadfaca); + + if(isbdata->memarena) + BLI_memarena_free(isbdata->memarena); + + MEM_freeN(isbdata); + lar->shb->isb_result[pa->thread]= NULL; + } + } + } +} diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c index c46be0eec28..deb5031ebf3 100644 --- a/source/blender/render/intern/source/zbuf.c +++ b/source/blender/render/intern/source/zbuf.c @@ -37,6 +37,7 @@ #include <limits.h> #include <string.h> +#include "BLI_arithb.h" #include "BLI_blenlib.h" #include "BLI_threads.h" #include "BLI_jitter.h" @@ -59,11 +60,12 @@ /* local includes */ #include "gammaCorrectionTables.h" +#include "pixelblending.h" #include "render_types.h" #include "renderpipeline.h" #include "renderdatabase.h" #include "rendercore.h" -#include "pixelblending.h" +#include "shadbuf.h" /* own includes */ #include "zbuf.h" @@ -89,7 +91,7 @@ void zbuf_alloc_span(ZSpan *zspan, int rectx, int recty) zspan->span2= MEM_mallocN(recty*sizeof(float), "zspan"); } -static void zbuf_free_span(ZSpan *zspan) +void zbuf_free_span(ZSpan *zspan) { if(zspan) { if(zspan->span1) MEM_freeN(zspan->span1); @@ -292,7 +294,7 @@ static APixstr *addpsA(ZSpan *zspan) return zspan->curpstr; } -static void zbufinvulAc4(ZSpan *zspan, int zvlnr, float *v1, float *v2, float *v3, float *v4) +static void zbuffillAc4(ZSpan *zspan, int zvlnr, float *v1, float *v2, float *v3, float *v4) { APixstr *ap, *apofs, *apn; double zxd, zyd, zy0, zverg; @@ -966,7 +968,7 @@ void zbufclipwire(ZSpan *zspan, int zvlnr, VlakRen *vlr) * @param v2 [4 floats, world coordinates] second vertex * @param v3 [4 floats, world coordinates] third vertex */ -static void zbufinvulGLinv4(ZSpan *zspan, int zvlnr, float *v1, float *v2, float *v3, float *v4) +static void zbuffillGLinv4(ZSpan *zspan, int zvlnr, float *v1, float *v2, float *v3, float *v4) { double zxd, zyd, zy0, zverg; float x0,y0,z0; @@ -1069,7 +1071,7 @@ static void zbufinvulGLinv4(ZSpan *zspan, int zvlnr, float *v1, float *v2, float /* uses spanbuffers */ -static void zbufinvulGL4(ZSpan *zspan, int zvlnr, float *v1, float *v2, float *v3, float *v4) +static void zbuffillGL4(ZSpan *zspan, int zvlnr, float *v1, float *v2, float *v3, float *v4) { double zxd, zyd, zy0, zverg; float x0,y0,z0; @@ -1181,7 +1183,7 @@ static void zbufinvulGL4(ZSpan *zspan, int zvlnr, float *v1, float *v2, float *v * @param v3 [4 floats, world coordinates] third vertex */ -static void zbufinvulGL_onlyZ(ZSpan *zspan, int zvlnr, float *v1, float *v2, float *v3, float *v4) +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; @@ -1530,7 +1532,7 @@ void zbufclip(ZSpan *zspan, int zvlnr, float *f1, float *f2, float *f3, int c1, zspan->zbuffunc(zspan, zvlnr, vez,vez+4,vez+8, NULL); } -static void zbufclip4(ZSpan *zspan, int zvlnr, float *f1, float *f2, float *f3, float *f4, int c1, int c2, int c3, int c4) +void zbufclip4(ZSpan *zspan, int zvlnr, float *f1, float *f2, float *f3, float *f4, int c1, int c2, int c3, int c4) { float vez[16]; @@ -1651,7 +1653,7 @@ void zbuffer_solid(RenderPart *pa, unsigned int lay, short layflag) fillrect(pa->rectz, pa->rectx, pa->recty, 0x7FFFFFFF); /* filling methods */ - zspan.zbuffunc= zbufinvulGL4; + zspan.zbuffunc= zbuffillGL4; zspan.zbuflinefunc= zbufline; /* part clipflag, threaded */ @@ -1671,8 +1673,8 @@ void zbuffer_solid(RenderPart *pa, unsigned int lay, short layflag) env= (ma->mode & MA_ENV); wire= (ma->mode & MA_WIRE); - if(ma->mode & MA_ZINV) zspan.zbuffunc= zbufinvulGLinv4; - else zspan.zbuffunc= zbufinvulGL4; + if(ma->mode & MA_ZINV) zspan.zbuffunc= zbuffillGLinv4; + else zspan.zbuffunc= zbuffillGL4; } } else if(all_z) { @@ -1774,7 +1776,7 @@ void RE_zbufferall_radio(struct RadView *vw, RNode **rg_elem, int rg_totelem, Re fillrect(zspan.rectp, vw->rectx, vw->recty, 0xFFFFFF); /* filling methods */ - zspan.zbuffunc= zbufinvulGL4; + zspan.zbuffunc= zbuffillGL4; if(rg_elem) { /* radio tool */ RNode **re, *rn; @@ -1862,7 +1864,7 @@ void zbuffer_shadow(Render *re, LampRen *lar, int *rectz, int size, float jitx, /* filling methods */ zspan.zbuflinefunc= zbufline_onlyZ; - zspan.zbuffunc= zbufinvulGL_onlyZ; + zspan.zbuffunc= zbuffillGL_onlyZ; for(a=0; a<re->totvlak; a++) { @@ -2429,7 +2431,7 @@ static void zbuffer_abuf(RenderPart *pa, APixstr *APixbuf, ListBase *apsmbase, u zspan.apsmbase= apsmbase; /* filling methods */ - zspan.zbuffunc= zbufinvulAc4; + zspan.zbuffunc= zbuffillAc4; zspan.zbuflinefunc= zbuflineAc; /* part clipflag, 4 threads */ @@ -2732,6 +2734,10 @@ void zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pass) aprect= APixbuf; rdrect= pa->rectdaps; + /* irregular shadowb buffer creation */ + if(R.r.mode & R_SHADOW) + ISB_create(pa, APixbuf); + /* filtered render, for now we assume only 1 filter size */ if(pa->crop) { crop= 1; @@ -2756,7 +2762,7 @@ void zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pass) for(x=pa->disprect.xmin+crop; x<pa->disprect.xmax-crop; x++, ap++, pass+=4, od++) { - if(ap->p[0]==NULL) { + if(ap->p[0]==0) { if(addpassflag & SCE_PASS_VECTOR) add_transp_speed(rl, od, NULL, 0.0f, rdrect); } @@ -2873,6 +2879,9 @@ void zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pass) MEM_freeN(APixbuf); freepsA(&apsmbase); + if(R.r.mode & R_SHADOW) + ISB_free(pa); + } /* *************** */ diff --git a/source/blender/src/buttons_shading.c b/source/blender/src/buttons_shading.c index af98d947e71..7798d50a663 100644 --- a/source/blender/src/buttons_shading.c +++ b/source/blender/src/buttons_shading.c @@ -1960,7 +1960,7 @@ void do_lampbuts(unsigned short event) break; case B_SHADRAY: la= G.buts->lockpoin; - la->mode &= ~LA_SHAD; + la->mode &= ~LA_SHAD_BUF; /* yafray: 'softlight' uses it's own shadbuf. flag. Must be cleared here too when switching from ray shadow */ la->mode &= ~LA_YF_SOFT; @@ -2146,8 +2146,11 @@ static void lamp_panel_spot(Object *ob, Lamp *la) uiBlockSetCol(block, TH_BUT_SETTING1); uiBlockBeginAlign(block); 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, B_SHADBUF, "Buf.Shadow",10,160,80,19,&la->mode, 0, 0, 0, 0, "Lets spotlight produce shadows using shadow buffer"); + 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"); + } uiBlockEndAlign(block); uiDefButBitS(block, TOG, LA_ONLYSHADOW, B_NOP,"OnlyShadow", 10,110,80,19,&la->mode, 0, 0, 0, 0, "Causes light to cast shadows only without illuminating objects"); @@ -2165,30 +2168,35 @@ 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) { - 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"); + if(la->mode & LA_SHAD_BUF) { + if(la->buftype==LA_SHADBUF_REGULAR) { + 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,"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"); + // uiDefButS(block, ROW,B_NOP,"9", 270,90,30,19, &la->buffers, 1.0, 9.0, 0, 0, "Amount of lampbuffer subsamples, this halves the shadowbuffer size"); -// 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"); -// uiDefButS(block, ROW,B_NOP,"9", 270,90,30,19, &la->buffers, 1.0, 9.0, 0, 0, "Amount of lampbuffer subsamples, this halves the shadowbuffer size"); - - 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,"Soft:", 200,40,100,19, &la->soft,1.0,100.0, 100, 0, "Sets the size of the shadow sample area"); + 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,"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 */ + uiDefButF(block, NUM,B_LAMPREDRAW,"Bias:", 100,40,100,19, &la->bias, 0.01, 5.0, 1, 0, "Sets the shadow map sampling bias"); + } uiBlockBeginAlign(block); - uiDefIconButBitS(block, TOG, LA_SHADBUF_AUTO_START, B_REDR, ICON_AUTO, 10, 10, 25, 19, &la->bufflag, 0.0, 0.0, 0, 0, "Automatic calculation of clipping-start, based on visible vertices"); + uiDefIconButBitC(block, TOG, LA_SHADBUF_AUTO_START, B_REDR, ICON_AUTO, 10, 10, 25, 19, &la->bufflag, 0.0, 0.0, 0, 0, "Automatic calculation of clipping-start, based on visible vertices"); if(la->bufflag & LA_SHADBUF_AUTO_START) uiDefBut(block, LABEL, B_NOP, "ClipSta: Auto", 35,10,115,19, NULL, 0, 0, 0, 0, ""); else uiDefButF(block, NUM,REDRAWVIEW3D,"ClipSta:", 35,10,115,19, &la->clipsta, 0.1*grid,1000.0*grid, 10, 0, "Sets the shadow map clip start: objects closer will not generate shadows"); - uiDefIconButBitS(block, TOG, LA_SHADBUF_AUTO_END, B_REDR, ICON_AUTO, 160, 10, 25, 19, &la->bufflag, 0.0, 0.0, 0, 0, "Automatic calculation of clipping-end, based on visible vertices"); + uiDefIconButBitC(block, TOG, LA_SHADBUF_AUTO_END, B_REDR, ICON_AUTO, 160, 10, 25, 19, &la->bufflag, 0.0, 0.0, 0, 0, "Automatic calculation of clipping-end, based on visible vertices"); if(la->bufflag & LA_SHADBUF_AUTO_END) uiDefBut(block, LABEL,B_NOP, "ClipEnd: Auto", 185,10,115,19, NULL, 0, 0, 0, 0, ""); else @@ -3140,8 +3148,10 @@ static void material_panel_material(Material *ma) uiDefButBitI(block, TOG, MA_VERTEXCOLP, B_MAT_VCOL_PAINT, "VCol Paint", 82,166,74,20, &(ma->mode), 0, 0, 0, 0, "Replaces material's colours with vertex colours"); uiDefButBitI(block, TOG, MA_FACETEXTURE, B_REDR, "TexFace", 156,166,74,20, &(ma->mode), 0, 0, 0, 0, "Sets UV-Editor assigned texture as color and texture info for faces"); uiDefButBitI(block, TOG, MA_SHLESS, B_MATPRV, "Shadeless", 230,166,73,20, &(ma->mode), 0, 0, 0, 0, "Makes material insensitive to light or shadow"); - uiDefButBitI(block, TOG, MA_NOMIST, B_NOP, "No Mist", 8,146,146,20, &(ma->mode), 0, 0, 0, 0, "Sets the material to ignore mist values"); - uiDefButBitI(block, TOG, MA_ENV, B_MATPRV, "Env", 158,146,145,20, &(ma->mode), 0, 0, 0, 0, "Causes faces to render with alpha zero: allows sky/backdrop to show through (only for solid faces)"); + + uiDefButBitI(block, TOG, MA_NOMIST, B_NOP, "No Mist", 8,146,74,20, &(ma->mode), 0, 0, 0, 0, "Sets the material to ignore mist values"); + uiDefButBitI(block, TOG, MA_ENV, B_MATPRV, "Env", 82,146,74,20, &(ma->mode), 0, 0, 0, 0, "Causes faces to render with alpha zero: allows sky/backdrop to show through (only for solid faces)"); + uiDefButF(block, NUM, B_NOP, "Shad A ", 156,146,147,19, &ma->shad_alpha, 0.001, 1.0f, 100, 0, "Shadow casting alpha, only in use for Irregular Shadowbuffer"); } uiBlockSetCol(block, TH_AUTO); uiBlockBeginAlign(block); diff --git a/source/blender/src/drawobject.c b/source/blender/src/drawobject.c index 2df2e771696..d0332e5c2d3 100644 --- a/source/blender/src/drawobject.c +++ b/source/blender/src/drawobject.c @@ -647,7 +647,7 @@ static void drawlamp(Object *ob) /* draw dashed outer circle if shadow is on. remember some lamps can't have certain shadows! */ if (la->type!=LA_HEMI) { if ((la->mode & LA_SHAD_RAY) || - ((la->mode & LA_SHAD) && (la->type==LA_SPOT)) ) + ((la->mode & LA_SHAD_BUF) && (la->type==LA_SPOT)) ) { drawcircball(GL_LINE_LOOP, vec, circrad + 3.0f*pixsize, imat); } @@ -821,7 +821,7 @@ static void drawlamp(Object *ob) setlinestyle(0); - if(la->type==LA_SPOT && (la->mode & LA_SHAD) ) { + if(la->type==LA_SPOT && (la->mode & LA_SHAD_BUF) ) { drawshadbuflimits(la, ob->obmat); } |