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 /source | |
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!
Diffstat (limited to 'source')
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(); |