diff options
author | Ton Roosendaal <ton@blender.org> | 2006-02-01 00:49:05 +0300 |
---|---|---|
committer | Ton Roosendaal <ton@blender.org> | 2006-02-01 00:49:05 +0300 |
commit | 5e3170fafd0a64d562c5c9e94af42136e8e98af6 (patch) | |
tree | ec721bb3fbeeb9c30dd377b8098f744146ddc18c | |
parent | 397ee6768dca9e4696c608c7731f050ce4440802 (diff) |
Three features;
- Live scanline updates while rendering
Using a timer system, each second now the tiles that are being processed
are checked if they could use display.
To make this work pretty, I had to use the threaded 'tile processor' for
a single thread too, but that's now proven to be stable.
Also note that these updates draw per layer, including ztransp progress
separately from solid render.
- Recode of ztransp OSA
Until now (since blender 1.0) the ztransp part was fully rendered and
added on top of the solid part with alpha-over. This adding was done before
the solid part applied sub-pixel sample filtering, causing the ztransp
layer to be always too blurry.
Now the ztransp layer uses same sub=pixel filter, resulting in the same
AA level (and filter results) as the solid part. Quite noticable with hair
renders.
- Vector buffer support & preliminary vector-blur Node
Using the "Render Layer" panel "Vector" pass button, the motion vectors
per pixel are calculated and stored. Accessible via the Compositor.
The vector-blur node is horrible btw! It just uses the length of the
vector to apply a filter like with current (z)blur. I'm committing it anyway,
I'll experiment with it further, and who knows some surprise code shows up!
19 files changed, 912 insertions, 483 deletions
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index d6ebdbef083..353389fde38 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -200,6 +200,7 @@ void set_node_shader_lamp_loop(void (*lamp_loop_func)(struct ShadeInput *, str #define CMP_NODE_FILTER 212 #define CMP_NODE_MAP_VALUE 213 #define CMP_NODE_TIME 214 +#define CMP_NODE_VECBLUR 215 #define CMP_NODE_IMAGE 220 #define CMP_NODE_R_RESULT 221 diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index b95c401808d..adeac4e6dc3 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -584,7 +584,7 @@ static void do_init_render_material(Material *ma, int osa, float *amb) } if(ma->texco & (TEXCO_ORCO|TEXCO_REFL|TEXCO_NORM|TEXCO_STRAND|TEXCO_STRESS)) needuv= 1; - else if(ma->texco & (TEXCO_GLOB|TEXCO_UV|TEXCO_OBJECT)) needuv= 1; + else if(ma->texco & (TEXCO_GLOB|TEXCO_UV|TEXCO_OBJECT|TEXCO_SPEED)) needuv= 1; else if(ma->texco & (TEXCO_LAVECTOR|TEXCO_VIEW|TEXCO_STICKY)) needuv= 1; } } diff --git a/source/blender/blenkernel/intern/node_composite.c b/source/blender/blenkernel/intern/node_composite.c index e7bfcd722b9..89fe2da98cd 100644 --- a/source/blender/blenkernel/intern/node_composite.c +++ b/source/blender/blenkernel/intern/node_composite.c @@ -70,6 +70,8 @@ typedef struct CompBuf { /* defines also used for pixel size */ #define CB_RGBA 4 +#define CB_VEC3 3 +#define CB_VEC2 2 #define CB_VAL 1 static CompBuf *alloc_compbuf(int sizex, int sizey, int type, int alloc) @@ -82,6 +84,10 @@ static CompBuf *alloc_compbuf(int sizex, int sizey, int type, int alloc) if(alloc) { if(cbuf->type==CB_RGBA) cbuf->rect= MEM_mallocT(4*sizeof(float)*sizex*sizey, "compbuf RGBA rect"); + else if(cbuf->type==CB_VEC3) + cbuf->rect= MEM_mallocT(4*sizeof(float)*sizex*sizey, "compbuf Vector3 rect"); + else if(cbuf->type==CB_VEC2) + cbuf->rect= MEM_mallocT(4*sizeof(float)*sizex*sizey, "compbuf Vector2 rect"); else cbuf->rect= MEM_mallocT(sizeof(float)*sizex*sizey, "compbuf Fac rect"); cbuf->malloc= 1; @@ -735,6 +741,7 @@ static bNodeSocketType cmp_node_rresult_out[]= { { SOCK_RGBA, 0, "Image", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, { SOCK_VALUE, 0, "Alpha", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_VALUE, 0, "Z", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_VECTOR, 0, "Vec", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { -1, 0, "" } }; @@ -761,6 +768,11 @@ static void node_composit_exec_rresult(void *data, bNode *node, bNodeStack **in, zbuf->rect= rl->rectz; out[2]->data= zbuf; } + if(out[3]->hasoutput && rl->rectvec) { + CompBuf *vecbuf= alloc_compbuf(rr->rectx, rr->recty, CB_VEC2, 0); + vecbuf->rect= rl->rectvec; + out[3]->data= vecbuf; + } generate_preview(node, stackbuf); } @@ -1080,34 +1092,33 @@ static void do_filter3(CompBuf *out, CompBuf *in, float *filter, float fac) float *row1, *row2, *row3; float *fp, mfac= 1.0f-fac; int rowlen, x, y, c; + int pixlen= in->type; rowlen= in->x; - if(in->type==CB_RGBA) { + for(y=2; y<in->y; y++) { + /* setup rows */ + row1= in->rect + pixlen*(y-2)*rowlen; + row2= row1 + pixlen*rowlen; + row3= row2 + pixlen*rowlen; - for(y=2; y<in->y; y++) { - /* setup rows */ - row1= in->rect + 4*(y-2)*rowlen; - row2= row1 + 4*rowlen; - row3= row2 + 4*rowlen; - - fp= out->rect + 4*(y-1)*rowlen; - QUATCOPY(fp, row2); - fp+= 4; - - for(x=2; x<rowlen; x++) { - for(c=0; c<4; c++) { - fp[0]= mfac*row2[4] + fac*(filter[0]*row1[0] + filter[1]*row1[4] + filter[2]*row1[8] + filter[3]*row2[0] + filter[4]*row2[4] + filter[5]*row2[8] + filter[6]*row3[0] + filter[7]*row3[4] + filter[8]*row3[8]); - fp++; row1++; row2++; row3++; - } + fp= out->rect + pixlen*(y-1)*rowlen; + QUATCOPY(fp, row2); + fp+= pixlen; + + for(x=2; x<rowlen; x++) { + for(c=0; c<pixlen; c++) { + fp[0]= mfac*row2[4] + fac*(filter[0]*row1[0] + filter[1]*row1[4] + filter[2]*row1[8] + filter[3]*row2[0] + filter[4]*row2[4] + filter[5]*row2[8] + filter[6]*row3[0] + filter[7]*row3[4] + filter[8]*row3[8]); + fp++; row1++; row2++; row3++; } } - } + } } +static float soft[9]= {1/16.0f, 2/16.0f, 1/16.0f, 2/16.0f, 4/16.0f, 2/16.0f, 1/16.0f, 2/16.0f, 1/16.0f}; + static void node_composit_exec_filter(void *data, bNode *node, bNodeStack **in, bNodeStack **out) { - float soft[9]= {1/16.0f, 2/16.0f, 1/16.0f, 2/16.0f, 4/16.0f, 2/16.0f, 1/16.0f, 2/16.0f, 1/16.0f}; float sharp[9]= {-1,-1,-1,-1,9,-1,-1,-1,-1}; float laplace[9]= {1/8.0f, -1/8.0f, 1/8.0f, -1/8.0f, 1.0f, -1/8.0f, 1/8.0f, -1/8.0f, 1/8.0f}; float sobel[9]= {1,2,1,0,0,0,-1,-2,-1}; @@ -1821,6 +1832,81 @@ static bNodeType cmp_node_blur= { }; +/* **************** VECTOR BLUR ******************** */ +static bNodeSocketType cmp_node_vecblur_in[]= { + { SOCK_RGBA, 1, "Image", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, + { SOCK_VECTOR, 1, "Vec", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { -1, 0, "" } +}; +static bNodeSocketType cmp_node_vecblur_out[]= { + { SOCK_RGBA, 0, "Image", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, + { -1, 0, "" } +}; + +static void fill_rct_in_image(rcti poly, float *rect, int xsize, int ysize, float *col) +{ + float *dest; + int x, y; + + for(y=poly.ymin; y<poly.ymax; y++) { + for(x=poly.xmin; x<poly.xmax; x++) { + dest= rect + 4*(xsize*y + x); + QUATCOPY(dest, col); + } + } + +} + + +static void node_composit_exec_vecblur(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +{ + CompBuf *new, *img= in[0]->data, *vecbuf= in[1]->data, *wbuf; + float *vect, *dest; + int x, y; + + if(img==NULL || vecbuf==NULL || out[0]->hasoutput==0) + return; + if(vecbuf->x!=img->x || vecbuf->y!=img->y) { + printf("cannot do different sized vecbuf yet\n"); + return; + } + if(vecbuf->type!=CB_VEC2) { + printf("input should be vecbuf\n"); + return; + } + + /* make weights version of vectors */ + wbuf= alloc_compbuf(img->x, img->y, CB_VAL, 1); // allocs + dest= wbuf->rect; + vect= vecbuf->rect; + for(y=0; y<img->y; y++) { + for(x=0; x<img->x; x++, dest++, vect+=2) { + *dest= 0.02f*sqrt(vect[0]*vect[0] + vect[1]*vect[1]); + if(*dest>1.0f) *dest= 1.0f; + } + } + + /* make output size of input image */ + new= alloc_compbuf(img->x, img->y, CB_RGBA, 1); // allocs + + blur_with_reference(new, img, wbuf, 100.0f, 100.0f); + + free_compbuf(wbuf); + out[0]->data= new; +} + +static bNodeType cmp_node_vecblur= { + /* type code */ CMP_NODE_VECBLUR, + /* name */ "Vector Blur", + /* width+range */ 120, 80, 200, + /* class+opts */ NODE_CLASS_OPERATOR, NODE_OPTIONS, + /* input sock */ cmp_node_vecblur_in, + /* output sock */ cmp_node_vecblur_out, + /* storage */ "", + /* execfunc */ node_composit_exec_vecblur + +}; + /* ****************** types array for all shaders ****************** */ @@ -1842,6 +1928,7 @@ bNodeType *node_all_composit[]= { &cmp_node_rresult, &cmp_node_alphaover, &cmp_node_blur, + &cmp_node_vecblur, &cmp_node_map_value, NULL }; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index df36fafcab1..6342578115e 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -4910,7 +4910,6 @@ static void do_versions(FileData *fd, Library *lib, Main *main) bScreen *sc; while(sce) { - sce->r.mode &= ~R_ZBLUR; // disabled for release if(sce->r.postsat==0.0) sce->r.postsat= 1.0f; diff --git a/source/blender/makesdna/DNA_material_types.h b/source/blender/makesdna/DNA_material_types.h index 04cd1c29a71..b9b4eaa0c29 100644 --- a/source/blender/makesdna/DNA_material_types.h +++ b/source/blender/makesdna/DNA_material_types.h @@ -216,6 +216,7 @@ typedef struct Material { /* still stored in vertex->accum, 1 D */ #define TEXCO_STRAND 8192 #define TEXCO_STRESS 16384 +#define TEXCO_SPEED 32768 /* mapto */ #define MAP_COL 1 diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 01776a2e981..a59e6e06427 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -387,9 +387,10 @@ typedef struct Scene { #define R_RAYTRACE 0x10000 /* R_GAUSS is obsolete, but used to retrieve setting from old files */ #define R_GAUSS 0x20000 + /* fbuf obsolete... */ #define R_FBUF 0x40000 #define R_THREADS 0x80000 -#define R_ZBLUR 0x100000 +#define R_SPEED 0x100000 /* filtertype */ #define R_FILTER_BOX 0 diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h index d34fc968e77..a9b75184e36 100644 --- a/source/blender/render/extern/include/RE_pipeline.h +++ b/source/blender/render/extern/include/RE_pipeline.h @@ -65,8 +65,9 @@ typedef struct RenderLayer { unsigned int lay; int layflag, passflag; - float *rectf; /* standard rgba buffer */ - float *rectz; /* standard camera coordinate zbuffer */ + float *rectf; /* 4 float, standard rgba buffer */ + float *rectz; /* 1 float, standard camera coordinate zbuffer */ + float *rectvec; /* 2 float, screen aligned speed vectors */ ListBase passes; @@ -90,7 +91,10 @@ typedef struct RenderResult { /* the main buffers */ ListBase layers; - int actlay; /* copy of renderdata..., so display callbacks can find out */ + + /* allowing live updates: */ + rcti renrect; + RenderLayer *renlay; /* optional saved endresult on disk */ char exrfile[FILE_MAXDIR]; diff --git a/source/blender/render/extern/include/RE_shader_ext.h b/source/blender/render/extern/include/RE_shader_ext.h index 3524523f9bc..b8bd46d784e 100644 --- a/source/blender/render/extern/include/RE_shader_ext.h +++ b/source/blender/render/extern/include/RE_shader_ext.h @@ -45,9 +45,12 @@ typedef struct TexResult { /* localized shade result data */ typedef struct ShadeResult { + float combined[4]; float diff[3]; float spec[3]; float alpha; + float nor[3]; + float winspeed[2]; } ShadeResult; @@ -76,7 +79,8 @@ typedef struct ShadeInput /* texture coordinates */ float lo[3], gl[3], uv[3], ref[3], orn[3], winco[3], sticky[3], vcol[3], rad[3]; - float vn[3], vno[3], facenor[3], view[3], refcol[4], displace[3], strand, tang[3], stress; + float vn[3], vno[3], facenor[3], view[3], refcol[4], displace[3]; + float strand, tang[3], stress, winspeed[3]; /* dx/dy OSA coordinates */ float dxco[3], dyco[3]; diff --git a/source/blender/render/intern/include/rendercore.h b/source/blender/render/intern/include/rendercore.h index cfdf34c205b..793480458c6 100644 --- a/source/blender/render/intern/include/rendercore.h +++ b/source/blender/render/intern/include/rendercore.h @@ -45,6 +45,7 @@ struct HaloRen; struct ShadeInput; +struct ShadeResult; /* ------------------------------------------------------------------------- */ @@ -84,7 +85,7 @@ void shade_material_loop(struct ShadeInput *shi, struct ShadeResult *shr); void zbufshade(void); void zbufshadeDA(void); /* Delta Accum Pixel Struct */ -void *shadepixel(RenderPart *pa, float x, float y, int z, int facenr, int mask, float *col, float *rco); +void *shadepixel(RenderPart *pa, float x, float y, int z, int facenr, int mask, struct ShadeResult *shr, float *rco); int count_mask(unsigned short mask); diff --git a/source/blender/render/intern/include/renderdatabase.h b/source/blender/render/intern/include/renderdatabase.h index 6996bca7a5c..a820800fae1 100644 --- a/source/blender/render/intern/include/renderdatabase.h +++ b/source/blender/render/intern/include/renderdatabase.h @@ -36,8 +36,21 @@ struct HaloRen; struct Material; struct Render; +/* render allocates totvert/256 of these nodes, for lookup and quick alloc */ +typedef struct VertTableNode { + struct VertRen *vert; + float *rad; + float *sticky; + float *strand; + float *tangent; + float *stress; + float *winspeed; +} VertTableNode; + /* renderdatabase.c */ void free_renderdata_tables(struct Render *re); +void free_renderdata_vertnodes(struct VertTableNode *vertnodes); + void set_normalflags(Render *re); void project_renderdata(struct Render *re, void (*projectfunc)(float *, float mat[][4], float *), int do_pano, int part); @@ -54,6 +67,7 @@ float *RE_vertren_get_stress(struct Render *re, struct VertRen *ver, int verify) float *RE_vertren_get_rad(struct Render *re, struct VertRen *ver, int verify); float *RE_vertren_get_strand(struct Render *re, struct VertRen *ver, int verify); float *RE_vertren_get_tangent(struct Render *re, struct VertRen *ver, int verify); +float *RE_vertren_get_winspeed(struct Render *re, struct VertRen *ver, int verify); /* haloren->type: flags */ #define HA_ONLYSKY 1 @@ -61,8 +75,9 @@ float *RE_vertren_get_tangent(struct Render *re, struct VertRen *ver, int verify #define HA_XALPHA 4 #define HA_FLARECIRC 8 - +/* convertblender.c */ void init_render_world(Render *re); +void RE_Database_FromScene_Vectors(Render *re, struct Scene *sce); #endif /* RENDERDATABASE_H */ diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index 9fbc071f0aa..beac431ce9d 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -708,6 +708,8 @@ static Material *give_render_material(Render *re, Object *ob, int nr) if(ma->mode & MA_ZTRA) re->flag |= R_ZTRA; + if(re->r.mode & R_SPEED) ma->texco |= NEED_UV; + return ma; } @@ -1404,7 +1406,7 @@ static void use_mesh_edge_lookup(Render *re, Mesh *me, DispListMesh *dlm, MEdge } } -static void init_render_mesh(Render *re, Object *ob) +static void init_render_mesh(Render *re, Object *ob, int only_verts) { Mesh *me; MVert *mvert = NULL; @@ -1493,190 +1495,196 @@ static void init_render_mesh(Render *re, Object *ob) ms++; } } - /* still to do for keys: the correct local texture coordinate */ - - /* faces in order of color blocks */ - vertofs= re->totvert - totvert; - for(a1=0; (a1<ob->totcol || (a1==0 && ob->totcol==0)); a1++) { - - ma= give_render_material(re, ob, a1+1); - - /* test for 100% transparant */ - ok= 1; - if(ma->alpha==0.0 && ma->spectra==0.0) { - ok= 0; - /* texture on transparency? */ - for(a=0; a<MAX_MTEX; a++) { - if(ma->mtex[a] && ma->mtex[a]->tex) { - if(ma->mtex[a]->mapto & MAP_ALPHA) ok= 1; - } - } - } + + if(!only_verts) { - /* if wire material, and we got edges, don't do the faces */ - if(ma->mode & MA_WIRE) { - end= dlm?dlm->totedge:me->totedge; - if(end) ok= 0; - } + /* still to do for keys: the correct local texture coordinate */ - if(ok) { - TFace *tface= NULL; + /* faces in order of color blocks */ + vertofs= re->totvert - totvert; + for(a1=0; (a1<ob->totcol || (a1==0 && ob->totcol==0)); a1++) { - /* radio faces need autosmooth, to separate shared vertices in corners */ - if(re->r.mode & R_RADIO) - if(ma->mode & MA_RADIO) - do_autosmooth= 1; + ma= give_render_material(re, ob, a1+1); - end= dlm?dlm->totface:me->totface; - if (dlm) { - mface= dlm->mface; - if (dlm->tface) { - tface= dlm->tface; - vertcol= NULL; - } else if (dlm->mcol) { - vertcol= (unsigned int *)dlm->mcol; - } else { - vertcol= NULL; - } - } else { - mface= me->mface; - if (me->tface) { - tface= me->tface; - vertcol= NULL; - } else if (me->mcol) { - vertcol= (unsigned int *)me->mcol; - } else { - vertcol= NULL; + /* test for 100% transparant */ + ok= 1; + if(ma->alpha==0.0 && ma->spectra==0.0) { + ok= 0; + /* texture on transparency? */ + for(a=0; a<MAX_MTEX; a++) { + if(ma->mtex[a] && ma->mtex[a]->tex) { + if(ma->mtex[a]->mapto & MAP_ALPHA) ok= 1; + } } } + + /* if wire material, and we got edges, don't do the faces */ + if(ma->mode & MA_WIRE) { + end= dlm?dlm->totedge:me->totedge; + if(end) ok= 0; + } - for(a=0; a<end; a++) { - int v1, v2, v3, v4, flag; - - if( mface->mat_nr==a1 ) { - float len; - - v1= mface->v1; - v2= mface->v2; - v3= mface->v3; - v4= mface->v4; - flag= mface->flag & ME_SMOOTH; - - vlr= RE_findOrAddVlak(re, re->totvlak++); - vlr->ob= ob; - vlr->v1= RE_findOrAddVert(re, vertofs+v1); - vlr->v2= RE_findOrAddVert(re, vertofs+v2); - vlr->v3= RE_findOrAddVert(re, vertofs+v3); - if(v4) vlr->v4= RE_findOrAddVert(re, vertofs+v4); - else vlr->v4= 0; - - /* render normals are inverted in render */ - if(vlr->v4) len= CalcNormFloat4(vlr->v4->co, vlr->v3->co, vlr->v2->co, - vlr->v1->co, vlr->n); - else len= CalcNormFloat(vlr->v3->co, vlr->v2->co, vlr->v1->co, - vlr->n); + if(ok) { + TFace *tface= NULL; - vlr->mat= ma; - vlr->flag= flag; - if((me->flag & ME_NOPUNOFLIP) ) { - vlr->flag |= R_NOPUNOFLIP; + /* radio faces need autosmooth, to separate shared vertices in corners */ + if(re->r.mode & R_RADIO) + if(ma->mode & MA_RADIO) + do_autosmooth= 1; + + end= dlm?dlm->totface:me->totface; + if (dlm) { + mface= dlm->mface; + if (dlm->tface) { + tface= dlm->tface; + vertcol= NULL; + } else if (dlm->mcol) { + vertcol= (unsigned int *)dlm->mcol; + } else { + vertcol= NULL; } - vlr->ec= 0; /* mesh edges rendered separately */ - vlr->lay= ob->lay; + } else { + mface= me->mface; + if (me->tface) { + tface= me->tface; + vertcol= NULL; + } else if (me->mcol) { + vertcol= (unsigned int *)me->mcol; + } else { + vertcol= NULL; + } + } - if(len==0) re->totvlak--; - else { - if(dlm) { - if(tface) { - vlr->tface= BLI_memarena_alloc(re->memArena, sizeof(TFace)); - vlr->vcol= vlr->tface->col; - memcpy(vlr->tface, tface, sizeof(TFace)); - } - else if (vertcol) { - vlr->vcol= BLI_memarena_alloc(re->memArena, sizeof(int)*4); - memcpy(vlr->vcol, vertcol+4*a, sizeof(int)*4); - } - } else { - if(tface) { - vlr->vcol= tface->col; - vlr->tface= tface; - } - else if (vertcol) { - vlr->vcol= vertcol+4*a; + for(a=0; a<end; a++) { + int v1, v2, v3, v4, flag; + + if( mface->mat_nr==a1 ) { + float len; + + v1= mface->v1; + v2= mface->v2; + v3= mface->v3; + v4= mface->v4; + flag= mface->flag & ME_SMOOTH; + + vlr= RE_findOrAddVlak(re, re->totvlak++); + vlr->ob= ob; + vlr->v1= RE_findOrAddVert(re, vertofs+v1); + vlr->v2= RE_findOrAddVert(re, vertofs+v2); + vlr->v3= RE_findOrAddVert(re, vertofs+v3); + if(v4) vlr->v4= RE_findOrAddVert(re, vertofs+v4); + else vlr->v4= 0; + + /* render normals are inverted in render */ + if(vlr->v4) len= CalcNormFloat4(vlr->v4->co, vlr->v3->co, vlr->v2->co, + vlr->v1->co, vlr->n); + else len= CalcNormFloat(vlr->v3->co, vlr->v2->co, vlr->v1->co, + vlr->n); + + vlr->mat= ma; + vlr->flag= flag; + if((me->flag & ME_NOPUNOFLIP) ) { + vlr->flag |= R_NOPUNOFLIP; + } + vlr->ec= 0; /* mesh edges rendered separately */ + vlr->lay= ob->lay; + + if(len==0) re->totvlak--; + else { + if(dlm) { + if(tface) { + vlr->tface= BLI_memarena_alloc(re->memArena, sizeof(TFace)); + vlr->vcol= vlr->tface->col; + memcpy(vlr->tface, tface, sizeof(TFace)); + } + else if (vertcol) { + vlr->vcol= BLI_memarena_alloc(re->memArena, sizeof(int)*4); + memcpy(vlr->vcol, vertcol+4*a, sizeof(int)*4); + } + } else { + if(tface) { + vlr->vcol= tface->col; + vlr->tface= tface; + } + else if (vertcol) { + vlr->vcol= vertcol+4*a; + } } } } - } - mface++; - if(tface) tface++; + mface++; + if(tface) tface++; + } } } - } - - /* exception... we do edges for wire mode. potential conflict when faces exist... */ - end= dlm?dlm->totedge:me->totedge; - mvert= dlm?dlm->mvert:me->mvert; - ma= give_render_material(re, ob, 1); - if(end && (ma->mode & MA_WIRE)) { - MEdge *medge; - struct edgesort *edgetable; - int totedge; - - medge= dlm?dlm->medge:me->medge; - /* we want edges to have UV and vcol too... */ - edgetable= make_mesh_edge_lookup(me, dlm, &totedge); - - for(a1=0; a1<end; a1++, medge++) { - if (medge->flag&ME_EDGERENDER) { - MVert *v0 = &mvert[medge->v1]; - MVert *v1 = &mvert[medge->v2]; + /* exception... we do edges for wire mode. potential conflict when faces exist... */ + end= dlm?dlm->totedge:me->totedge; + mvert= dlm?dlm->mvert:me->mvert; + ma= give_render_material(re, ob, 1); + if(end && (ma->mode & MA_WIRE)) { + MEdge *medge; + struct edgesort *edgetable; + int totedge; + + medge= dlm?dlm->medge:me->medge; + + /* we want edges to have UV and vcol too... */ + edgetable= make_mesh_edge_lookup(me, dlm, &totedge); + + for(a1=0; a1<end; a1++, medge++) { + if (medge->flag&ME_EDGERENDER) { + MVert *v0 = &mvert[medge->v1]; + MVert *v1 = &mvert[medge->v2]; - vlr= RE_findOrAddVlak(re, re->totvlak++); - vlr->ob= ob; - vlr->v1= RE_findOrAddVert(re, vertofs+medge->v1); - vlr->v2= RE_findOrAddVert(re, vertofs+medge->v2); - vlr->v3= vlr->v2; - vlr->v4= NULL; - - if(edgetable) { - use_mesh_edge_lookup(re, me, dlm, medge, vlr, edgetable, totedge); + vlr= RE_findOrAddVlak(re, re->totvlak++); + vlr->ob= ob; + vlr->v1= RE_findOrAddVert(re, vertofs+medge->v1); + vlr->v2= RE_findOrAddVert(re, vertofs+medge->v2); + vlr->v3= vlr->v2; + vlr->v4= NULL; + + if(edgetable) { + use_mesh_edge_lookup(re, me, dlm, medge, vlr, edgetable, totedge); + } + + xn= (v0->no[0]+v1->no[0]); + yn= (v0->no[1]+v1->no[1]); + zn= (v0->no[2]+v1->no[2]); + /* transpose ! */ + vlr->n[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn; + vlr->n[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn; + vlr->n[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn; + Normalise(vlr->n); + + vlr->mat= ma; + vlr->flag= 0; + vlr->ec= ME_V1V2; + vlr->lay= ob->lay; } - - xn= (v0->no[0]+v1->no[0]); - yn= (v0->no[1]+v1->no[1]); - zn= (v0->no[2]+v1->no[2]); - /* transpose ! */ - vlr->n[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn; - vlr->n[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn; - vlr->n[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn; - Normalise(vlr->n); - - vlr->mat= ma; - vlr->flag= 0; - vlr->ec= ME_V1V2; - vlr->lay= ob->lay; } + if(edgetable) + MEM_freeN(edgetable); } - if(edgetable) - MEM_freeN(edgetable); } } - if (test_for_displace(re, ob ) ) { - calc_vertexnormals(re, totverto, totvlako, 0); - do_displacement(re, ob, totvlako, re->totvlak-totvlako, totverto, re->totvert-totverto); - } + if(!only_verts) { + if (test_for_displace(re, ob ) ) { + calc_vertexnormals(re, totverto, totvlako, 0); + do_displacement(re, ob, totvlako, re->totvlak-totvlako, totverto, re->totvert-totverto); + } - if(do_autosmooth || (me->flag & ME_AUTOSMOOTH)) { - autosmooth(re, totverto, totvlako, me->smoothresh); - } + if(do_autosmooth || (me->flag & ME_AUTOSMOOTH)) { + autosmooth(re, totverto, totvlako, me->smoothresh); + } - calc_vertexnormals(re, totverto, totvlako, need_tangent); + calc_vertexnormals(re, totverto, totvlako, need_tangent); - if(need_stress) - calc_edge_stress(re, me, totverto, totvlako); + if(need_stress) + calc_edge_stress(re, me, totverto, totvlako); + } if(dlm) displistmesh_free(dlm); if(dm_needsfree) dm->release(dm); @@ -2422,7 +2430,7 @@ static void set_phong_threshold(Render *re, Object *ob, int startface, int numfa } } -static void init_render_object(Render *re, Object *ob) +static void init_render_object(Render *re, Object *ob, int only_verts) { float mat[4][4]; int startface, startvert; @@ -2439,7 +2447,7 @@ static void init_render_object(Render *re, Object *ob) else if(ob->type==OB_SURF) init_render_surf(re, ob); else if(ob->type==OB_MESH) - init_render_mesh(re, ob); + init_render_mesh(re, ob, only_verts); else if(ob->type==OB_MBALL) init_render_mball(re, ob); else { @@ -2735,8 +2743,8 @@ void RE_Database_FromScene(Render *re, Scene *scene, int use_camera_view) Base *base; Object *ob; Scene *sce; - unsigned int lay; float mat[4][4]; + unsigned int lay; re->scene= scene; @@ -2799,7 +2807,7 @@ void RE_Database_FromScene(Render *re, Scene *scene, int use_camera_view) if (re->r.renderer==R_YAFRAY) { if ((ob->type!=OB_MBALL) && ((ob->transflag & OB_DUPLIFRAMES)!=0)) { printf("Object %s has OB_DUPLIFRAMES set, adding to renderlist\n", ob->id.name); - init_render_object(re, ob); + init_render_object(re, ob, 0); } } /* before make duplis, update particle for current frame */ @@ -2811,7 +2819,7 @@ void RE_Database_FromScene(Render *re, Scene *scene, int use_camera_view) } if(ob->type==OB_MBALL) { - init_render_object(re, ob); + init_render_object(re, ob, 0); } else { DupliObject *dob; @@ -2833,7 +2841,7 @@ void RE_Database_FromScene(Render *re, Scene *scene, int use_camera_view) printf("Adding dupli matrix for object %s\n", obd->id.name); YAF_addDupliMtx(obd); } - else init_render_object(re, obd); + else init_render_object(re, obd, 0); } Mat4CpyMat4(obd->obmat, dob->omat); } @@ -2853,14 +2861,14 @@ void RE_Database_FromScene(Render *re, Scene *scene, int use_camera_view) (ob->parent->type!=OB_LATTICE) && YAF_objectKnownData(ob)) printf("From parent: Added dupli matrix for linked data object %s\n", ob->id.name); else - init_render_object(re, ob); + init_render_object(re, ob, 0); } else if ((ob->type!=OB_EMPTY) && (ob->type!=OB_LAMP) && (ob->type!=OB_ARMATURE) && YAF_objectKnownData(ob)) printf("Added dupli matrix for linked data object %s\n", ob->id.name); else - init_render_object(re, ob); + init_render_object(re, ob, 0); } - else init_render_object(re, ob); + else init_render_object(re, ob, 0); } } @@ -2895,6 +2903,7 @@ void RE_Database_FromScene(Render *re, Scene *scene, int use_camera_view) if(lar->shb) { makeshadowbuf(re, lar); } + re->stats_draw(&re->i); } /* yafray: 'direct' radiosity, environment maps and octree init not needed for yafray render */ @@ -2924,6 +2933,158 @@ void RE_Database_FromScene(Render *re, Scene *scene, int use_camera_view) } +static void database_fromscene_vectors(Render *re, Scene *scene) +{ + extern int slurph_opt; /* key.c */ + Base *base; + Object *ob; + Scene *sce; + float mat[4][4]; + unsigned int lay; + + re->scene= scene; + + /* XXX add test if dbase was filled already? */ + + re->memArena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE); + re->totvlak=re->totvert=re->totlamp=re->tothalo= 0; + re->lights.first= re->lights.last= NULL; + + slurph_opt= 0; + + /* in localview, lamps are using normal layers, objects only local bits */ + if(re->scene->lay & 0xFF000000) lay= re->scene->lay & 0xFF000000; + else lay= re->scene->lay; + + /* applies changes fully, still using G.scene for timing... */ + G.scene->r.cfra--; + scene_update_for_newframe(re->scene, lay); + G.scene->r.cfra++; + + /* if no camera, viewmat should have been set! */ + if(re->scene->camera) { + Mat4Ortho(re->scene->camera->obmat); + Mat4Invert(mat, re->scene->camera->obmat); + RE_SetView(re, mat); + } + + for(SETLOOPER(re->scene, base)) { + ob= base->object; + /* imat objects has to be done here, since displace can have texture using Object map-input */ + MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat); + MTC_Mat4Invert(ob->imat, mat); + /* each object should only be rendered once */ + ob->flag &= ~OB_DONE; + } + + /* MAKE RENDER DATA */ + + for(SETLOOPER(re->scene, base)) { + ob= base->object; + + /* OB_DONE means the object itself got duplicated, so was already converted */ + if(ob->flag & OB_DONE); + else if( (base->lay & lay) || (ob->type==OB_LAMP && (base->lay & re->scene->lay)) ) { + if(ob->transflag & OB_DUPLI) { + + /* before make duplis, update particle for current frame */ + if(ob->transflag & OB_DUPLIVERTS) { + PartEff *paf= give_parteff(ob); + if(paf) { + if(paf->flag & PAF_ANIMATED) build_particle_system(ob); + } + } + + if(ob->type==OB_MBALL) { + init_render_object(re, ob, 1); + } + else { + DupliObject *dob; + ListBase *lb= object_duplilist(sce, ob); + + for(dob= lb->first; dob; dob= dob->next) { + Object *obd= dob->ob; + Mat4CpyMat4(obd->obmat, dob->mat); + + if(obd->type!=OB_MBALL) { + init_render_object(re, obd, 1); + } + Mat4CpyMat4(obd->obmat, dob->omat); + } + BLI_freelistN(lb); + } + } + else { + init_render_object(re, ob, 1); + } + + } + } + + project_renderdata(re, projectverto, re->r.mode & R_PANORAMA, 0); +} + +void RE_Database_FromScene_Vectors(Render *re, Scene *sce) +{ + struct VertTableNode *vertnodes; + int vertnodeslen= 0; + printf("creating speed vectors \n"); + re->r.mode |= R_SPEED; + + /* creates entire dbase */ + database_fromscene_vectors(re, sce); + + /* copy away vertex info */ + vertnodes= re->vertnodes; + vertnodeslen= re->vertnodeslen; + re->vertnodes= NULL; + re->vertnodeslen= 0; + + /* free dbase and make the real one */ + RE_Database_Free(re); + + RE_Database_FromScene(re, sce, 1); + + if(re->vertnodeslen!=vertnodeslen) { + printf("ERROR: vertex tables different in size %d %d\n", re->vertnodeslen, vertnodeslen); + } + else { + VertRen *ver= NULL, *oldver= NULL; + float *speed, div, zco[2], oldzco[2]; + float zmulx= re->winx/2, zmuly= re->winy/2; + int a; + + for(a=0; a< re->totvert;a++) { + if((a & 255)==0) { + ver= re->vertnodes[a>>8].vert; + oldver= vertnodes[a>>8].vert; + } + else { + ver++; + oldver++; + } + + /* now map both hocos to screenspace */ + div= 1.0f/ver->ho[3]; + zco[0]= zmulx*(1.0+ver->ho[0]*div); + zco[1]= zmuly*(1.0+ver->ho[1]*div); + + div= 1.0f/oldver->ho[3]; + oldzco[0]= zmulx*(1.0+oldver->ho[0]*div); + oldzco[1]= zmuly*(1.0+oldver->ho[1]*div); + + speed= RE_vertren_get_winspeed(re, ver, 1); + speed[0]= oldzco[0] - zco[0]; + speed[1]= oldzco[1] - zco[1]; + //printf("speed %d %f %f\n", a, speed[0], speed[1]); + } + } + + free_renderdata_vertnodes(vertnodes); + +} + + /* exported call to recalculate hoco for vertices, when winmat changed */ void RE_DataBase_ApplyWindow(Render *re) { diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 375cb5f3a0c..e4268735e8a 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -150,6 +150,7 @@ static void free_render_result(RenderResult *res) RenderLayer *rl= res->layers.first; if(rl->rectf) RE_freeN(rl->rectf); if(rl->rectz) RE_freeN(rl->rectz); + if(rl->rectvec) RE_freeN(rl->rectvec); BLI_remlink(&res->layers, rl); RE_freeN(rl); } @@ -193,9 +194,6 @@ static RenderResult *new_render_result(Render *re, rcti *partrct, int crop) rr->tilerect.ymin= partrct->ymin - re->disprect.ymin; rr->tilerect.ymax= partrct->ymax - re->disprect.ymax; - /* copy, so display callbacks can find out too */ - rr->actlay= re->r.actlay; - /* check renderdata for amount of layers */ for(srl= re->r.layers.first; srl; srl= srl->next) { rl= RE_callocN(sizeof(RenderLayer), "new render layer"); @@ -209,6 +207,8 @@ static RenderResult *new_render_result(Render *re, rcti *partrct, int crop) rl->rectf= RE_callocN(rectx*recty*sizeof(float)*4, "layer float rgba"); if(srl->passflag & SCE_PASS_Z) rl->rectz= RE_callocN(rectx*recty*sizeof(float), "layer float Z"); + if(srl->passflag & SCE_PASS_VECTOR) + rl->rectvec= RE_callocN(rectx*recty*sizeof(float)*2, "layer float Vector"); } /* previewrender and envmap don't do layers, so we make a default one */ @@ -229,6 +229,47 @@ static RenderResult *new_render_result(Render *re, rcti *partrct, int crop) return rr; } +static int render_result_needs_vector(RenderResult *rr) +{ + RenderLayer *rl; + + for(rl= rr->layers.first; rl; rl= rl->next) + if(rl->passflag & SCE_PASS_VECTOR) + return 1; + return 0; +} + +static void do_merge_tile(RenderResult *rr, RenderResult *rrpart, float *target, float *tile, int pixsize) +{ + int y, ofs, copylen, tilex, tiley; + + copylen= tilex= rrpart->rectx; + tiley= rrpart->recty; + + if(rrpart->crop) { /* filters add pixel extra */ + tile+= pixsize*(rrpart->crop + rrpart->crop*tilex); + + copylen= tilex - 2*rrpart->crop; + tiley -= 2*rrpart->crop; + + ofs= (rrpart->tilerect.ymin + rrpart->crop)*rr->rectx + (rrpart->tilerect.xmin+rrpart->crop); + target+= pixsize*ofs; + } + else { + ofs= (rrpart->tilerect.ymin*rr->rectx + rrpart->tilerect.xmin); + target+= pixsize*ofs; + } + + copylen *= sizeof(float)*pixsize; + tilex *= pixsize; + ofs= pixsize*rr->rectx; + + for(y=0; y<tiley; y++) { + memcpy(target, tile, copylen); + target+= ofs; + tile+= tilex; + } +} /* used when rendering to a full buffer, or when reading the exr part-layer-pass file */ /* no test happens here if it fits... we also assume layers are in sync */ @@ -236,53 +277,18 @@ static RenderResult *new_render_result(Render *re, rcti *partrct, int crop) static void merge_render_result(RenderResult *rr, RenderResult *rrpart) { RenderLayer *rl, *rlp; - float *rf, *rfp; - float *rz, *rzp; - int y, height, len, copylen; for(rl= rr->layers.first, rlp= rrpart->layers.first; rl && rlp; rl= rl->next, rlp= rlp->next) { - /* first combined and z pass */ - if(rl->rectf && rlp->rectf) { - int ofs; - - rzp= rlp->rectz; - rfp= rlp->rectf; - - copylen=len= rrpart->rectx; - height= rrpart->recty; - - if(rrpart->crop) { /* filters add pixel extra */ - - if(rzp) rzp+= rrpart->crop + rrpart->crop*len; - if(rfp) rfp+= 4*(rrpart->crop + rrpart->crop*len); - - copylen= len-2*rrpart->crop; - height -= 2*rrpart->crop; - - ofs= (rrpart->tilerect.ymin + rrpart->crop)*rr->rectx + (rrpart->tilerect.xmin+rrpart->crop); - rz= rl->rectz+ ofs; - rf= rl->rectf+ 4*ofs; - } - else { - ofs= (rrpart->tilerect.ymin*rr->rectx + rrpart->tilerect.xmin); - rz= rl->rectz+ ofs; - rf= rl->rectf+ 4*ofs; - } - - for(y=0; y<height; y++) { - if(rzp) { - memcpy(rz, rzp, 4*copylen); - rz+= rr->rectx; - rzp+= len; - } - if(rfp) { - memcpy(rf, rfp, 16*copylen); - rf+= 4*rr->rectx; - rfp+= 4*len; - } - } - } + /* combined */ + if(rl->rectf && rlp->rectf) + do_merge_tile(rr, rrpart, rl->rectf, rlp->rectf, 4); + /* z */ + if(rl->rectz && rlp->rectz) + do_merge_tile(rr, rrpart, rl->rectz, rlp->rectz, 1); + /* vector */ + if(rl->rectvec && rlp->rectvec) + do_merge_tile(rr, rrpart, rl->rectvec, rlp->rectvec, 2); } } @@ -313,7 +319,7 @@ RenderResult *RE_GetResult(Render *re) /* fill provided result struct with what's currently active or done */ void RE_GetResultImage(Render *re, RenderResult *rr) { - memset(rr, sizeof(RenderResult), 0); + memset(rr, 0, sizeof(RenderResult)); if(re && re->result) { RenderLayer *rl; @@ -359,7 +365,7 @@ void RE_ResultGet32(Render *re, unsigned int *rect) } else /* else fill with black */ - memset(rect, sizeof(int)*re->rectx*re->recty, 0); + memset(rect, 0, sizeof(int)*re->rectx*re->recty); } @@ -573,9 +579,9 @@ static int do_part_thread(void *pa_v) zbufshadeDA_tile(pa); else zbufshade_tile(pa); - - if(!R.test_break()) - merge_render_result(R.result, pa->result); + + /* merge too on break! */ + merge_render_result(R.result, pa->result); } pa->ready= 1; @@ -661,13 +667,16 @@ static void threaded_tile_processor(Render *re) { ListBase threads; RenderPart *pa; - int maxthreads=2, rendering=1, counter= 1; + int maxthreads, rendering=1, counter= 1, hasdrawn, drawtimer=0; if(re->result==NULL) return; if(re->test_break()) return; + if(re->r.mode & R_THREADS) maxthreads= 2; + else maxthreads= 1; + initparts(re); BLI_init_threads(&threads, do_part_thread, maxthreads); @@ -687,10 +696,13 @@ static void threaded_tile_processor(Render *re) BLI_insert_thread(&threads, pa); } } - else + else { PIL_sleep_ms(50); + drawtimer++; + } /* check for ready ones to display, and if we need to continue */ + hasdrawn= 0; rendering= 0; for(pa= re->parts.first; pa; pa= pa->next) { if(pa->ready) { @@ -700,11 +712,21 @@ static void threaded_tile_processor(Render *re) free_render_result(pa->result); pa->result= NULL; re->i.partsdone++; + hasdrawn= 1; + } + } + else { + rendering= 1; + if(pa->nr && pa->result && drawtimer>20) { + re->display_draw(pa->result, &pa->result->renrect); + hasdrawn= 1; } } - else rendering= 1; } + if(hasdrawn) + drawtimer= 0; + /* on break, wait for all slots to get freed */ if(re->test_break() && BLI_available_threads(&threads)==maxthreads) rendering= 0; @@ -719,7 +741,7 @@ static void threaded_tile_processor(Render *re) void RE_TileProcessor(Render *re) { - if(re->r.mode & R_THREADS) + if(1) threaded_tile_processor(re); else render_tile_processor(re); @@ -734,8 +756,11 @@ void render_one_frame(Render *re) // re->cfra= cfra; /* <- unused! */ /* make render verts/faces/halos/lamps */ - RE_Database_FromScene(re, re->scene, 1); - + if(render_result_needs_vector(re->result)) + RE_Database_FromScene_Vectors(re, re->scene); + else + RE_Database_FromScene(re, re->scene, 1); + RE_TileProcessor(re); /* free all render verts etc */ diff --git a/source/blender/render/intern/source/pixelblending.c b/source/blender/render/intern/source/pixelblending.c index 860aeed29d7..ece9970e885 100644 --- a/source/blender/render/intern/source/pixelblending.c +++ b/source/blender/render/intern/source/pixelblending.c @@ -74,22 +74,14 @@ extern struct Render R; void addAlphaOverFloat(float *dest, float *source) { /* d = s + (1-alpha_s)d*/ - float c; float mul; mul= 1.0 - source[3]; - c= (mul*dest[0]) + source[0]; - dest[0]= c; - - c= (mul*dest[1]) + source[1]; - dest[1]= c; - - c= (mul*dest[2]) + source[2]; - dest[2]= c; - - c= (mul*dest[3]) + source[3]; - dest[3]= c; + dest[0]= (mul*dest[0]) + source[0]; + dest[1]= (mul*dest[1]) + source[1]; + dest[2]= (mul*dest[2]) + source[2]; + dest[3]= (mul*dest[3]) + source[3]; } @@ -98,7 +90,6 @@ void addAlphaOverFloat(float *dest, float *source) void addAlphaUnderFloat(float *dest, float *source) { - float c; float mul; if( (-RE_EMPTY_COLOUR_FLOAT < dest[3]) @@ -112,18 +103,10 @@ void addAlphaUnderFloat(float *dest, float *source) mul= 1.0 - dest[3]; - c= (mul*source[0]) + dest[0]; - dest[0]= c; - - c= (mul*source[1]) + dest[1]; - dest[1]= c; - - c= (mul*source[2]) + dest[2]; - dest[2]= c; - - c= (mul*source[3]) + dest[3]; - dest[3]= c; - + dest[0]+= (mul*source[0]); + dest[1]+= (mul*source[1]); + dest[2]+= (mul*source[2]); + dest[3]+= (mul*source[3]); } @@ -229,6 +212,68 @@ void add_filt_fmask(unsigned int mask, float *col, float *rowbuf, int row_w) } } +/* filtered adding to scanlines */ +void add_filt_fmask_alphaunder(unsigned int mask, float *col, float *rowbuf, int row_w) +{ + /* calc the value of mask */ + float **fmask1= R.samples->fmask1, **fmask2=R.samples->fmask2; + float *rb1, *rb2, *rb3; + float val, r, g, b, al, acol[4]; + unsigned int a, maskand, maskshift; + int j; + + r= col[0]; + g= col[1]; + b= col[2]; + al= col[3]; + + rb2= rowbuf-4; + rb3= rb2-4*row_w; + rb1= rb2+4*row_w; + + maskand= (mask & 255); + maskshift= (mask >>8); + + for(j=2; j>=0; j--) { + + a= j; + + val= *(fmask1[a] +maskand) + *(fmask2[a] +maskshift); + if(val!=0.0) { + acol[0]= val*r; + acol[1]= val*g; + acol[2]= val*b; + acol[3]= val*al; + addAlphaUnderFloat(rb1, acol); + } + a+=3; + + val= *(fmask1[a] +maskand) + *(fmask2[a] +maskshift); + if(val!=0.0) { + acol[0]= val*r; + acol[1]= val*g; + acol[2]= val*b; + acol[3]= val*al; + addAlphaUnderFloat(rb2, acol); + } + a+=3; + + val= *(fmask1[a] +maskand) + *(fmask2[a] +maskshift); + if(val!=0.0) { + acol[0]= val*r; + acol[1]= val*g; + acol[2]= val*b; + acol[3]= val*al; + addAlphaUnderFloat(rb3, acol); + } + + rb1+= 4; + rb2+= 4; + rb3+= 4; + } +} + + /* ------------------------------------------------------------------------- */ void addalphaAddFloat(float *dest, float *source) { diff --git a/source/blender/render/intern/source/ray.c b/source/blender/render/intern/source/ray.c index 19ec1dd546d..d5d0a951604 100644 --- a/source/blender/render/intern/source/ray.c +++ b/source/blender/render/intern/source/ray.c @@ -628,6 +628,8 @@ void makeoctree(Render *re) } MEM_freeN(ocface); + re->stats_draw(&re->i); + } /* ************ raytracer **************** */ diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index 87c1330d5ef..ba45953eefc 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -27,6 +27,7 @@ */ /* system includes */ +#include <stdio.h> #include <math.h> #include <string.h> #include <stdlib.h> @@ -1854,7 +1855,20 @@ void shade_input_set_coords(ShadeInput *shi, float u, float v, int i1, int i2, i if(mode & MA_TANGENT_V) shi->tang[0]= shi->tang[1]= shi->tang[2]= 0.0f; } - + + if(R.r.mode & R_SPEED) { + float *s1, *s2, *s3; + + s1= RE_vertren_get_winspeed(&R, v1, 0); + s2= RE_vertren_get_winspeed(&R, v2, 0); + s3= RE_vertren_get_winspeed(&R, v3, 0); + if(s1 && s2 && s3) { + shi->winspeed[0]= (l*s3[0] - u*s1[0] - v*s2[0]); + shi->winspeed[1]= (l*s3[1] - u*s1[1] - v*s2[1]); + shi->winspeed[2]= 0.0f; + } + } + /* texture coordinates. shi->dxuv shi->dyuv have been set */ if(texco & NEED_UV) { if(texco & TEXCO_ORCO) { @@ -2111,9 +2125,8 @@ void shade_material_loop(ShadeInput *shi, ShadeResult *shr) /* note, facenr declared volatile due to over-eager -O2 optimizations * on cygwin (particularly -frerun-cse-after-loop) */ -void *shadepixel(RenderPart *pa, float x, float y, int z, volatile int facenr, int mask, float *col, float *rco) +void *shadepixel(RenderPart *pa, float x, float y, int z, volatile int facenr, int mask, ShadeResult *shr, float *rco) { - ShadeResult shr; ShadeInput shi; VlakRen *vlr=NULL; @@ -2131,8 +2144,8 @@ void *shadepixel(RenderPart *pa, float x, float y, int z, volatile int facenr, i shi.depth= 0; // means first hit, not raytracing if(facenr==0) { /* sky */ - col[0]= 0.0; col[1]= 0.0; col[2]= 0.0; col[3]= 0.0; - VECCOPY(rco, col); + memset(shr, 0, sizeof(ShadeResult)); + rco[0]= rco[1]= rco[2]= 0.0f; } else if( (facenr & 0x7FFFFF) <= R.totvlak) { VertRen *v1; @@ -2327,34 +2340,38 @@ void *shadepixel(RenderPart *pa, float x, float y, int z, volatile int facenr, i VECCOPY(shi.vno, shi.vn); if(shi.mat->nodetree && shi.mat->use_nodes) { - ntreeShaderExecTree(shi.mat->nodetree, &shi, &shr); + ntreeShaderExecTree(shi.mat->nodetree, &shi, shr); } else { /* copy all relevant 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_material_loop(&shi, &shr); + shade_material_loop(&shi, shr); } /* after shading and composit layers */ - if(shr.spec[0]<0.0f) shr.spec[0]= 0.0f; - if(shr.spec[1]<0.0f) shr.spec[1]= 0.0f; - if(shr.spec[2]<0.0f) shr.spec[2]= 0.0f; + if(shr->spec[0]<0.0f) shr->spec[0]= 0.0f; + if(shr->spec[1]<0.0f) shr->spec[1]= 0.0f; + if(shr->spec[2]<0.0f) shr->spec[2]= 0.0f; - if(shr.diff[0]<0.0f) shr.diff[0]= 0.0f; - if(shr.diff[1]<0.0f) shr.diff[1]= 0.0f; - if(shr.diff[2]<0.0f) shr.diff[2]= 0.0f; + if(shr->diff[0]<0.0f) shr->diff[0]= 0.0f; + if(shr->diff[1]<0.0f) shr->diff[1]= 0.0f; + if(shr->diff[2]<0.0f) shr->diff[2]= 0.0f; - VECADD(col, shr.diff, shr.spec); + VECADD(shr->combined, shr->diff, shr->spec); + + /* additional passes */ + shr->winspeed[0]= shi.winspeed[0]; shr->winspeed[1]= shi.winspeed[1]; + VECCOPY(shr->nor, shi.vn); /* NOTE: this is not correct here, sky from raytrace gets corrected... */ /* exposure correction */ if(R.wrld.exp!=0.0 || R.wrld.range!=1.0) { if((shi.mat->mode & MA_SHLESS)==0) { - col[0]= R.wrld.linfac*(1.0-exp( col[0]*R.wrld.logfac) ); - col[1]= R.wrld.linfac*(1.0-exp( col[1]*R.wrld.logfac) ); - col[2]= R.wrld.linfac*(1.0-exp( col[2]*R.wrld.logfac) ); + shr->combined[0]= R.wrld.linfac*(1.0-exp( shr->combined[0]*R.wrld.logfac) ); + shr->combined[1]= R.wrld.linfac*(1.0-exp( shr->combined[1]*R.wrld.logfac) ); + shr->combined[2]= R.wrld.linfac*(1.0-exp( shr->combined[2]*R.wrld.logfac) ); } } @@ -2367,26 +2384,20 @@ void *shadepixel(RenderPart *pa, float x, float y, int z, volatile int facenr, i } else alpha= 1.0; - if(shr.alpha!=1.0 || alpha!=1.0) { + if(shr->alpha!=1.0 || alpha!=1.0) { if(shi.mat->mode & MA_RAYTRANSP) { fac= alpha; - if(R.r.mode & R_UNIFIED) - /* unified alpha overs everything... */ - col[3]= 1.0f; - else { - /* sky was applied allready for ray transp, only do mist */ - col[3]= shr.alpha; - } + shr->combined[3]= shr->alpha; } else { - fac= alpha*(shr.alpha); - col[3]= fac; + fac= alpha*(shr->alpha); + shr->combined[3]= fac; } - col[0]*= fac; - col[1]*= fac; - col[2]*= fac; + shr->combined[0]*= fac; + shr->combined[1]*= fac; + shr->combined[2]*= fac; } - else col[3]= 1.0; + else shr->combined[3]= 1.0; } if(R.flag & R_LAMPHALO) { @@ -2403,29 +2414,30 @@ void *shadepixel(RenderPart *pa, float x, float y, int z, volatile int facenr, i calc_view_vector(shi.view, x, y); shi.co[2]= 0.0; - renderspothalo(&shi, col, 1.0); + renderspothalo(&shi, shr->combined, 1.0); } else - renderspothalo(&shi, col, col[3]); + renderspothalo(&shi, shr->combined, shr->combined[3]); } return vlr; } -static void shadepixel_sky(RenderPart *pa, float x, float y, int z, int facenr, int mask, float *colf) +static void shadepixel_sky(RenderPart *pa, float x, float y, int z, int facenr, int mask, ShadeResult *shr) { VlakRen *vlr; float collector[4], rco[3]; - vlr= shadepixel(pa, x, y, z, facenr, mask, colf, rco); - if(colf[3] != 1.0) { + vlr= shadepixel(pa, x, y, z, facenr, mask, shr, rco); + if(shr->combined[3] != 1.0) { + /* bail out when raytrace transparency (sky included already) */ if(vlr && (R.r.mode & R_RAYTRACE)) if(vlr->mat->mode & MA_RAYTRANSP) return; renderSkyPixelFloat(collector, x, y, vlr?rco:NULL); - addAlphaOverFloat(collector, colf); - QUATCOPY(colf, collector); + addAlphaOverFloat(collector, shr->combined); + QUATCOPY(shr->combined, collector); } } @@ -2503,14 +2515,16 @@ static void edge_enhance_add(RenderPart *pa, float *rectf, float *arect) /* ********************* MAINLOOPS ******************** */ -static void shadeDA_tile(RenderPart *pa, float *rectf, float *recta) +static void shadeDA_tile(RenderPart *pa, RenderLayer *rl) { + RenderResult *rr= pa->result; + ShadeResult shr; PixStr *ps; float xs, ys; - float fcol[4], *rf, *grf, *acol= NULL; + float *fcol= shr.combined, *rf, *rectf= rl->rectf; long *rd, *rectdaps= pa->rectdaps; int zbuf, samp, curmask, face, mask, fullmask; - int b, x, y, full_osa, seed, crop=0; + int b, x, y, full_osa, seed, crop=0, offs=0, od; if(R.test_break()) return; @@ -2519,23 +2533,24 @@ static void shadeDA_tile(RenderPart *pa, float *rectf, float *recta) fullmask= (1<<R.osa)-1; - /* might need it for gamma, in end of this function */ - grf= rectf; - /* filtered render, for now we assume only 1 filter size */ if(pa->crop) { crop= 1; rectf+= 4*(pa->rectx + 1); rectdaps+= pa->rectx + 1; - if(recta) recta+= 4*(pa->rectx + 1); + offs= pa->rectx + 1; } - for(y=pa->disprect.ymin+crop; y<pa->disprect.ymax-crop; y++) { + /* scanline updates have to be 2 lines behind */ + rr->renrect.ymin= 0; + rr->renrect.ymax= -2*crop; + + for(y=pa->disprect.ymin+crop; y<pa->disprect.ymax-crop; y++, rr->renrect.ymax++) { rf= rectf; rd= rectdaps; - if(recta) acol= recta; - - for(x=pa->disprect.xmin+crop; x<pa->disprect.xmax-crop; x++, rd++, rf+=4) { + od= offs; + + for(x=pa->disprect.xmin+crop; x<pa->disprect.xmax-crop; x++, rd++, rf+=4, od++) { BLI_thread_srandom(pa->thread, seed+x); ps= (PixStr *)(*rd); @@ -2567,9 +2582,8 @@ static void shadeDA_tile(RenderPart *pa, float *rectf, float *recta) if(curmask & (1<<samp)) { xs= (float)x + R.jit[samp][0]; ys= (float)y + R.jit[samp][1]; - shadepixel_sky(pa, xs, ys, zbuf, face, (1<<samp), fcol); + shadepixel_sky(pa, xs, ys, zbuf, face, (1<<samp), &shr); - if(acol && acol[3]!=0.0) addAlphaOverFloat(fcol, acol); if(R.do_gamma) { fcol[0]= gammaCorrect(fcol[0]); fcol[1]= gammaCorrect(fcol[1]); @@ -2579,14 +2593,12 @@ static void shadeDA_tile(RenderPart *pa, float *rectf, float *recta) } } } - else { + else if(curmask) { b= R.samples->centmask[curmask]; xs= (float)x+R.samples->centLut[b & 15]; ys= (float)y+R.samples->centLut[b>>4]; - shadepixel_sky(pa, xs, ys, zbuf, face, curmask, fcol); - - if(acol && acol[3]!=0.0) addAlphaOverFloat(fcol, acol); - + shadepixel_sky(pa, xs, ys, zbuf, face, curmask, &shr); + if(R.do_gamma) { fcol[0]= gammaCorrect(fcol[0]); fcol[1]= gammaCorrect(fcol[1]); @@ -2600,22 +2612,29 @@ static void shadeDA_tile(RenderPart *pa, float *rectf, float *recta) if(ps==NULL) break; else ps= ps->next; } - if(acol) acol+=4; + + /* passes */ + if(rl->passflag & SCE_PASS_VECTOR) { + float *fp= rl->rectvec+2*od; + fp[0]= shr.winspeed[0]; + fp[1]= shr.winspeed[1]; + } } rectf+= 4*pa->rectx; rectdaps+= pa->rectx; - if(recta) recta+= 4*pa->rectx; + offs+= pa->rectx; seed+= pa->rectx; if(y&1) if(R.test_break()) break; } if(R.do_gamma) { - for(y= pa->rectx*pa->recty; y>0; y--, grf+=4) { - grf[0] = invGammaCorrect(grf[0]); - grf[1] = invGammaCorrect(grf[1]); - grf[2] = invGammaCorrect(grf[2]); + rectf= rl->rectf; + for(y= pa->rectx*pa->recty; y>0; y--, rectf+=4) { + rectf[0] = invGammaCorrect(rectf[0]); + rectf[1] = invGammaCorrect(rectf[1]); + rectf[2] = invGammaCorrect(rectf[2]); } } @@ -2706,9 +2725,10 @@ static void make_pixelstructs(RenderPart *pa, ListBase *lb) /* supposed to be fully threadable! */ void zbufshadeDA_tile(RenderPart *pa) { + RenderResult *rr= pa->result; RenderLayer *rl; ListBase psmlist= {NULL, NULL}; - float *acolrect= NULL, *edgerect= NULL; + float *edgerect= NULL; set_part_zbuf_clipflag(pa); @@ -2718,7 +2738,9 @@ void zbufshadeDA_tile(RenderPart *pa) pa->rectz= RE_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectz"); if(R.r.mode & R_EDGE) edgerect= RE_callocN(sizeof(float)*pa->rectx*pa->recty, "rectedge"); - for(rl= pa->result->layers.first; rl; rl= rl->next) { + for(rl= rr->layers.first; rl; rl= rl->next) { + /* indication for scanline updates */ + rr->renlay= rl; /* initialize pixelstructs */ addpsmain(&psmlist); @@ -2737,20 +2759,28 @@ void zbufshadeDA_tile(RenderPart *pa) fillrect(pa->rectz, pa->rectx, pa->recty, 0x7FFFFFFF); - /* we do transp layer first, so its get added with filter in main buffer... still incorrect though */ + /* shades solid */ + if(rl->layflag & SCE_LAY_SOLID) + shadeDA_tile(pa, rl); + + /* transp layer */ if(R.flag & R_ZTRA) { if(rl->layflag & SCE_LAY_ZTRA) { - acolrect= RE_callocN(4*sizeof(float)*pa->rectx*pa->recty, "alpha layer"); - zbuffer_transp_shade(pa, acolrect, rl->lay, rl->layflag); + float *acolrect= RE_callocN(4*sizeof(float)*pa->rectx*pa->recty, "alpha layer"); + float *fcol= rl->rectf, *acol= acolrect; + int x; + + /* swap for live updates */ + SWAP(float *, acolrect, rl->rectf); + zbuffer_transp_shade(pa, rl->rectf, rl->lay, rl->layflag); + SWAP(float *, acolrect, rl->rectf); + + for(x=pa->rectx*pa->recty; x>0; x--, acol+=4, fcol+=4) { + addAlphaOverFloat(fcol, acol); + } + RE_freeN(acolrect); } } - - /* shades solid and adds transparent layer */ - if(rl->layflag & SCE_LAY_SOLID) - shadeDA_tile(pa, rl->rectf, acolrect); - else if(acolrect) { - SWAP(float *, acolrect, rl->rectf); - } /* extra layers */ if(R.r.mode & R_EDGE) @@ -2763,10 +2793,6 @@ void zbufshadeDA_tile(RenderPart *pa) convert_zbuf_to_distbuf(pa, rl); /* free stuff within loop! */ - if(acolrect) { - RE_freeN(acolrect); - acolrect= NULL; - } RE_freeN(pa->rectdaps); pa->rectdaps= NULL; freeps(&psmlist); } @@ -2786,35 +2812,67 @@ void zbufshadeDA_tile(RenderPart *pa) /* supposed to be fully threadable! */ void zbufshade_tile(RenderPart *pa) { + ShadeResult shr; + RenderResult *rr= pa->result; RenderLayer *rl; - + set_part_zbuf_clipflag(pa); /* zbuffer code clears/inits rects */ pa->rectp= RE_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectp"); pa->rectz= RE_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectz"); - for(rl= pa->result->layers.first; rl; rl= rl->next) { + for(rl= rr->layers.first; rl; rl= rl->next) { + /* indication for scanline updates */ + rr->renlay= rl; + zbuffer_solid(pa, rl->lay, rl->layflag); if(!R.test_break()) { if(rl->layflag & SCE_LAY_SOLID) { float *fcol= rl->rectf; - int x, y, *rp= pa->rectp, *rz= pa->rectz; - - for(y=pa->disprect.ymin; y<pa->disprect.ymax; y++) { - for(x=pa->disprect.xmin; x<pa->disprect.xmax; x++, rz++, rp++, fcol+=4) { - shadepixel_sky(pa, (float)x, (float)y, *rz, *rp, 0, fcol); + int x, y, *rp= pa->rectp, *rz= pa->rectz, offs=0; + + /* init scanline updates */ + rr->renrect.ymin=rr->renrect.ymax= 0; + + 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(pa, (float)x, (float)y, *rz, *rp, 0, &shr); + QUATCOPY(fcol, shr.combined); + + /* passes */ + if(*rp && (rl->passflag & SCE_PASS_VECTOR)) { + float *fp= rl->rectvec+2*(offs); + fp[0]= shr.winspeed[0]; + fp[1]= shr.winspeed[1]; + } } - if(y&1) if(R.test_break()) break; + if(y&1) + if(R.test_break()) break; } } } - if(!R.test_break()) - if(R.flag & R_ZTRA) - if(rl->layflag & SCE_LAY_ZTRA) + if(!R.test_break()) { + if(R.flag & R_ZTRA) { + if(rl->layflag & SCE_LAY_ZTRA) { + float *acolrect= RE_callocN(4*sizeof(float)*pa->rectx*pa->recty, "alpha layer"); + float *fcol= rl->rectf, *acol= acolrect; + int x; + + /* swap for live updates */ + SWAP(float *, acolrect, rl->rectf); zbuffer_transp_shade(pa, rl->rectf, rl->lay, rl->layflag); + SWAP(float *, acolrect, rl->rectf); + + for(x=pa->rectx*pa->recty; x>0; x--, acol+=4, fcol+=4) { + addAlphaOverFloat(fcol, acol); + } + RE_freeN(acolrect); + } + } + } if(!R.test_break()) { if(R.r.mode & R_EDGE) { diff --git a/source/blender/render/intern/source/renderdatabase.c b/source/blender/render/intern/source/renderdatabase.c index 098d4491060..d43a2bea8b8 100644 --- a/source/blender/render/intern/source/renderdatabase.c +++ b/source/blender/render/intern/source/renderdatabase.c @@ -91,16 +91,7 @@ #define RE_STRAND_ELEMS 1 #define RE_TANGENT_ELEMS 3 #define RE_STRESS_ELEMS 1 - -/* render allocates totvert/256 of these nodes, for lookup and quick alloc */ -typedef struct VertTableNode { - struct VertRen *vert; - float *rad; - float *sticky; - float *strand; - float *tangent; - float *stress; -} VertTableNode; +#define RE_WINSPEED_ELEMS 2 float *RE_vertren_get_sticky(Render *re, VertRen *ver, int verify) { @@ -179,6 +170,21 @@ float *RE_vertren_get_tangent(Render *re, VertRen *ver, int verify) return tangent + (ver->index & 255)*RE_TANGENT_ELEMS; } +/* needs malloc */ +float *RE_vertren_get_winspeed(Render *re, VertRen *ver, int verify) +{ + float *winspeed; + int nr= ver->index>>8; + + winspeed= re->vertnodes[nr].winspeed; + if(winspeed==NULL) { + if(verify) + winspeed= re->vertnodes[nr].winspeed= MEM_mallocN(256*RE_WINSPEED_ELEMS*sizeof(float), "winspeed table"); + else + return NULL; + } + return winspeed + (ver->index & 255)*RE_WINSPEED_ELEMS; +} VertRen *RE_findOrAddVert(Render *re, int nr) { @@ -218,6 +224,31 @@ VertRen *RE_findOrAddVert(Render *re, int nr) return v; } +void free_renderdata_vertnodes(VertTableNode *vertnodes) +{ + int a; + + for(a=0; vertnodes[a].vert; a++) { + MEM_freeN(vertnodes[a].vert); + + if(vertnodes[a].rad) + MEM_freeN(vertnodes[a].rad); + if(vertnodes[a].sticky) + MEM_freeN(vertnodes[a].sticky); + if(vertnodes[a].strand) + MEM_freeN(vertnodes[a].strand); + if(vertnodes[a].tangent) + MEM_freeN(vertnodes[a].tangent); + if(vertnodes[a].stress) + MEM_freeN(vertnodes[a].stress); + if(vertnodes[a].winspeed) + MEM_freeN(vertnodes[a].winspeed); + } + + MEM_freeN(vertnodes); + +} + void free_renderdata_tables(Render *re) { int a=0; @@ -241,22 +272,7 @@ void free_renderdata_tables(Render *re) } if(re->vertnodes) { - for(a=0; re->vertnodes[a].vert; a++) { - MEM_freeN(re->vertnodes[a].vert); - - if(re->vertnodes[a].rad) - MEM_freeN(re->vertnodes[a].rad); - if(re->vertnodes[a].sticky) - MEM_freeN(re->vertnodes[a].sticky); - if(re->vertnodes[a].strand) - MEM_freeN(re->vertnodes[a].strand); - if(re->vertnodes[a].tangent) - MEM_freeN(re->vertnodes[a].tangent); - if(re->vertnodes[a].stress) - MEM_freeN(re->vertnodes[a].stress); - } - - MEM_freeN(re->vertnodes); + free_renderdata_vertnodes(re->vertnodes); re->vertnodes= NULL; re->vertnodeslen= 0; } diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c index 7fac9f59944..4830db352d7 100644 --- a/source/blender/render/intern/source/zbuf.c +++ b/source/blender/render/intern/source/zbuf.c @@ -56,6 +56,7 @@ #include "RE_render_ext.h" /* local includes */ +#include "gammaCorrectionTables.h" #include "render_types.h" #include "renderpipeline.h" #include "renderdatabase.h" @@ -1879,7 +1880,7 @@ static void copyto_abufz(RenderPart *pa, int *arectz, int sample) long *rd; /* now, in OSA the pixstructs contain all faces filled in */ - if(R.r.mode & R_OSA) fillrect(arectz, pa->rectx, pa->recty, 0x7FFFFFFF); + if(R.osa) fillrect(arectz, pa->rectx, pa->recty, 0x7FFFFFFF); else { memcpy(arectz, pa->rectz, 4*pa->rectx*pa->recty); return; @@ -1952,7 +1953,7 @@ static void zbuffer_abuf(RenderPart *pa, APixstr *APixbuf, ListBase *apsmbase, u copyto_abufz(pa, zspan.arectz, zsample); /* init zbuffer */ zspan.mask= 1<<zsample; - if(R.r.mode & R_OSA) { + if(R.osa) { zspan.zofsx= -pa->disprect.xmin-R.jit[zsample][0]; zspan.zofsy= -pa->disprect.ymin-R.jit[zsample][1]; } @@ -2010,7 +2011,7 @@ static void zbuffer_abuf(RenderPart *pa, APixstr *APixbuf, ListBase *apsmbase, u } } - if((R.r.mode & R_OSA)==0) break; + if(R.osa==0) break; if(R.test_break()) break; } @@ -2033,13 +2034,14 @@ static int vergzvlak(const void *a1, const void *a2) */ static void shadetrapixel(RenderPart *pa, float x, float y, int z, int facenr, int mask, float *fcol) { + ShadeResult shr; float rco[3]; if( (facenr & 0x7FFFFF) > R.totvlak) { printf("error in shadetrapixel nr: %d\n", (facenr & 0x7FFFFF)); return; } - if(R.r.mode & R_OSA) { + if(R.osa) { VlakRen *vlr= RE_findOrAddVlak(&R, (facenr-1) & 0x7FFFFF); float accumcol[4]={0,0,0,0}, tot=0.0; int a; @@ -2047,11 +2049,11 @@ static void shadetrapixel(RenderPart *pa, float x, float y, int z, int facenr, i if(vlr->flag & R_FULL_OSA) { for(a=0; a<R.osa; a++) { if(mask & (1<<a)) { - shadepixel(pa, x+R.jit[a][0], y+R.jit[a][1], z, facenr, 1<<a, fcol, rco); - accumcol[0]+= fcol[0]; - accumcol[1]+= fcol[1]; - accumcol[2]+= fcol[2]; - accumcol[3]+= fcol[3]; + shadepixel(pa, x+R.jit[a][0], y+R.jit[a][1], z, facenr, 1<<a, &shr, rco); + accumcol[0]+= shr.combined[0]; + accumcol[1]+= shr.combined[1]; + accumcol[2]+= shr.combined[2]; + accumcol[3]+= shr.combined[3]; tot+= 1.0; } } @@ -2065,11 +2067,14 @@ static void shadetrapixel(RenderPart *pa, float x, float y, int z, int facenr, i int b= R.samples->centmask[mask]; x= x+R.samples->centLut[b & 15]; y= y+R.samples->centLut[b>>4]; - shadepixel(pa, x, y, z, facenr, mask, fcol, rco); - + shadepixel(pa, x, y, z, facenr, mask, &shr, rco); + QUATCOPY(fcol, shr.combined); } } - else shadepixel(pa, x, y, z, facenr, mask, fcol, rco); + else { + shadepixel(pa, x, y, z, facenr, mask, &shr, rco); + QUATCOPY(fcol, shr.combined); + } } static int addtosampcol(float *sampcol, float *fcol, int mask) @@ -2089,14 +2094,15 @@ static int addtosampcol(float *sampcol, float *fcol, int mask) void zbuffer_transp_shade(RenderPart *pa, float *pass, unsigned int lay, short layflag) { + RenderResult *rr= pa->result; APixstr *APixbuf; /* Zbuffer: linked list of face samples */ - APixstr *ap, *apn; + APixstr *ap, *aprect, *apn; ListBase apsmbase={NULL, NULL}; - float col[4], fcol[4], tempcol[4], sampcol[16*4], *scol, accumcol[4]; - float fac, alpha[32]; - int x, y, a, zrow[MAX_ZROW][3], totface, nr; + float fcol[4], sampcol[16*4]; + float fac, alpha[32], *passrect= pass; + int x, y, crop=0, a, zrow[MAX_ZROW][3], totface; int sval; - + /* looks nicer for calling code */ if(R.test_break()) return; @@ -2110,7 +2116,7 @@ void zbuffer_transp_shade(RenderPart *pa, float *pass, unsigned int lay, short l } /* alpha LUT */ - if(R.r.mode & R_OSA ) { + if(R.osa) { fac= (1.0/(float)R.osa); for(a=0; a<=R.osa; a++) { alpha[a]= (float)a*fac; @@ -2119,12 +2125,26 @@ void zbuffer_transp_shade(RenderPart *pa, float *pass, unsigned int lay, short l /* fill the Apixbuf */ zbuffer_abuf(pa, APixbuf, &apsmbase, lay, layflag); + aprect= APixbuf; - /* render tile */ - ap= APixbuf; + /* filtered render, for now we assume only 1 filter size */ + if(pa->crop) { + crop= 1; + passrect+= 4*(pa->rectx + 1); + aprect+= pa->rectx + 1; + } - for(y=pa->disprect.ymin; y<pa->disprect.ymax; y++) { - for(x=pa->disprect.xmin; x<pa->disprect.xmax; x++, ap++, pass+=4) { + /* init scanline updates */ + rr->renrect.ymin= 0; + rr->renrect.ymax= -pa->crop; + + /* render the tile */ + + for(y=pa->disprect.ymin+crop; y<pa->disprect.ymax-crop; y++, rr->renrect.ymax++) { + pass= passrect; + ap= aprect; + + for(x=pa->disprect.xmin+crop; x<pa->disprect.xmax-crop; x++, ap++, pass+=4) { if(ap->p[0]) { /* sort in z */ @@ -2148,23 +2168,14 @@ void zbuffer_transp_shade(RenderPart *pa, float *pass, unsigned int lay, short l shadetrapixel(pa, (float)x, (float)y, zrow[0][0], zrow[0][1], zrow[0][2], fcol); - nr= count_mask(zrow[0][2]); - if( (R.r.mode & R_OSA) && nr<R.osa) { - fac= alpha[ nr ]; - col[0]= (fcol[0]*fac); - col[1]= (fcol[1]*fac); - col[2]= (fcol[2]*fac); - col[3]= (fcol[3]*fac); + if(R.osa) { + add_filt_fmask(zrow[0][2], fcol, pass, rr->rectx); } else { - col[0]= fcol[0]; - col[1]= fcol[1]; - col[2]= fcol[2]; - col[3]= fcol[3]; + QUATCOPY(pass, fcol); } } else { - col[0]= col[1]= col[2]= col[3]= 0.0f; if(totface==2) { if(zrow[0][0] < zrow[1][0]) { @@ -2178,62 +2189,43 @@ void zbuffer_transp_shade(RenderPart *pa, float *pass, unsigned int lay, short l qsort(zrow, totface, sizeof(int)*3, vergzvlak); } - /* join when pixels are adjacent */ - - while(totface>0) { - totface--; - - shadetrapixel(pa, (float)x, (float)y, zrow[totface][0], zrow[totface][1], zrow[totface][2], fcol); - - a= count_mask(zrow[totface][2]); - if( (R.r.mode & R_OSA ) && a<R.osa) { - if(totface>0) { - memset(sampcol, 0, 4*sizeof(float)*R.osa); - sval= addtosampcol(sampcol, fcol, zrow[totface][2]); - - /* sval==0: alpha completely full */ - while( (sval != 0) && (totface>0) ) { - a= count_mask(zrow[totface-1][2]); - if(a==R.osa) break; - totface--; - - shadetrapixel(pa, (float)x, (float)y, zrow[totface][0], zrow[totface][1], zrow[totface][2], fcol); - sval= addtosampcol(sampcol, fcol, zrow[totface][2]); - } - - scol= sampcol; - accumcol[0]= scol[0]; accumcol[1]= scol[1]; - accumcol[2]= scol[2]; accumcol[3]= scol[3]; - scol+= 4; - for(a=1; a<R.osa; a++, scol+=4) { - accumcol[0]+= scol[0]; accumcol[1]+= scol[1]; - accumcol[2]+= scol[2]; accumcol[3]+= scol[3]; - } - tempcol[0]= accumcol[0]/R.osa; - tempcol[1]= accumcol[1]/R.osa; - tempcol[2]= accumcol[2]/R.osa; - tempcol[3]= accumcol[3]/R.osa; - - addAlphaUnderFloat(col, tempcol); - - } - else { - fac= alpha[a]; - fcol[0]= (fcol[0]*fac); - fcol[1]= (fcol[1]*fac); - fcol[2]= (fcol[2]*fac); - fcol[3]= (fcol[3]*fac); - addAlphaUnderFloat(col, fcol); - } - } - else addAlphaUnderFloat(col, fcol); /* no osa or full pixel with same face? */ + if(R.osa==0) { + while(totface>0) { + totface--; + + shadetrapixel(pa, (float)x, (float)y, zrow[totface][0], zrow[totface][1], zrow[totface][2], fcol); + addAlphaUnderFloat(pass, fcol); + + if(pass[3]>=0.999) break; + } + } + else { + /* for each mask-sample we alpha-under colors. then in end it's added using filter */ + memset(sampcol, 0, 4*sizeof(float)*R.osa); + + while(totface>0) { + totface--; + + shadetrapixel(pa, (float)x, (float)y, zrow[totface][0], zrow[totface][1], zrow[totface][2], fcol); + sval= addtosampcol(sampcol, fcol, zrow[totface][2]); + + if(sval==0) break; + } - if(col[3]>=0.999) break; + for(a=0; a<R.osa; a++) + add_filt_fmask(1<<a, sampcol+4*a, pass, rr->rectx); } } - if(col[3]!=0.0) addAlphaOverFloat(pass, col); + //if(R.osa && R.do_gamma) { + // pass[0]= invGammaCorrect(pass[0]); + // pass[1]= invGammaCorrect(pass[1]); + // pass[2]= invGammaCorrect(pass[2]); + //} } } + + aprect+= pa->rectx; + passrect+= 4*pa->rectx; } RE_freeN(APixbuf); diff --git a/source/blender/src/editnode.c b/source/blender/src/editnode.c index 84354859067..c192d801b65 100644 --- a/source/blender/src/editnode.c +++ b/source/blender/src/editnode.c @@ -1178,7 +1178,7 @@ static void node_add_menu(SpaceNode *snode) } else if(snode->treetype==NTREE_COMPOSIT) { /* compo menu, still hardcoded defines... solve */ - event= pupmenu("Add Node%t|Render Result %x221|Composite %x222|Viewer%x201|Image %x220|RGB Curves%x209|AlphaOver %x210|Blur %x211|Filter %x212|Value %x203|Color %x202|Mix %x204|ColorRamp %x205|Color to BW %x206|Map Value %x213|Normal %x207"); + event= pupmenu("Add Node%t|Render Result %x221|Composite %x222|Viewer%x201|Image %x220|RGB Curves%x209|AlphaOver %x210|Blur %x211|Vector Blur %x215|Filter %x212|Value %x203|Color %x202|Mix %x204|ColorRamp %x205|Color to BW %x206|Map Value %x213|Normal %x207"); if(event<1) return; } else return; diff --git a/source/blender/src/renderwin.c b/source/blender/src/renderwin.c index 579dc8b892a..8b2c0093b3e 100644 --- a/source/blender/src/renderwin.c +++ b/source/blender/src/renderwin.c @@ -721,10 +721,23 @@ static void renderwin_clear_display_cb(RenderResult *rr) */ /* can get as well the full picture, as the parts while rendering */ -static void renderwin_progress(RenderWin *rw, RenderResult *rr, rcti *unused) +static void renderwin_progress(RenderWin *rw, RenderResult *rr, rcti *renrect) { rcti win_rct; float *rectf, fullrect[2][2]; + int ymin, ymax; + + /* if renrect argument, we only display scanlines */ + if(renrect) { + ymin= renrect->ymin; + ymax= renrect->ymax-ymin; + if(ymax<2) return; + renrect->ymin= renrect->ymax; + } + else { + ymin= 0; + ymax= rr->recty-2*rr->crop; + } /* renderwindow cruft */ win_rct.xmin= win_rct.ymin= 0; @@ -736,9 +749,13 @@ static void renderwin_progress(RenderWin *rw, RenderResult *rr, rcti *unused) if(rr->rectf) rectf= rr->rectf; else { - RenderLayer *rl= BLI_findlink(&rr->layers, rr->actlay); + RenderLayer *rl= rr->renlay; + if(rl==NULL) return; rectf= rl->rectf; - } + } + /* if scanline updates... */ + rectf+= 4*rr->rectx*ymin; + /* when rendering more pixels than needed, we crop away cruft */ if(rr->crop) rectf+= 4*(rr->crop*rr->rectx + rr->crop); @@ -746,14 +763,14 @@ static void renderwin_progress(RenderWin *rw, RenderResult *rr, rcti *unused) /* tilerect defines drawing offset from (0,0) */ /* however, tilerect (xmin, ymin) is first pixel */ fullrect[0][0] += (rr->tilerect.xmin+rr->crop)*rw->zoom; - fullrect[0][1] += (rr->tilerect.ymin+rr->crop)*rw->zoom; + fullrect[0][1] += (rr->tilerect.ymin+rr->crop + ymin)*rw->zoom; glEnable(GL_SCISSOR_TEST); glaDefine2DArea(&win_rct); glDrawBuffer(GL_FRONT); glPixelZoom(rw->zoom, rw->zoom); - glaDrawPixelsSafe(fullrect[0][0], fullrect[0][1], rr->rectx-2*rr->crop, rr->recty-2*rr->crop, rr->rectx, + glaDrawPixelsSafe(fullrect[0][0], fullrect[0][1], rr->rectx-2*rr->crop, ymax, rr->rectx, GL_RGBA, GL_FLOAT, rectf); glPixelZoom(1.0, 1.0); glFlush(); |