Orange; more render & compo stuff!
authorTon Roosendaal <ton@blender.org>
Thu, 26 Jan 2006 22:18:46 +0000 (22:18 +0000)
committerTon Roosendaal <ton@blender.org>
Thu, 26 Jan 2006 22:18:46 +0000 (22:18 +0000)
-> Rendering in RenderLayers

It's important to distinguish a 'render layer' from a 'pass'. The first is
control over the main pipeline itself, to indicate what geometry is being
is rendered. The 'pass' (not in this commit!) is related to internal
shading code, like shadow/spec/AO/normals/etc.

Options for RenderLayers now are:
- Indicate which 3d 'view layers' have to be included (so you can render
  front and back separately)
- "Solid", all solid faces, includes sky at the moment too
- "ZTransp", all transparent faces
- "Halo", the halos
- "Strand", the particle strands (not coded yet...)

Currently only 2 'passes' are exported for render, which is the "Combined"
buffer and the "Z. The latter now works, and can be turned on/off.

Note that all layers are still fully kept in memory now, saving the tiles
and layers to disk (in exr) is also todo.

-> New Blur options

The existing Blur Node (compositor) now has an optional input image. This
has to be a 'value buffer', which can be a Zbuffer, or any mask you can
think of. The input values have to be in the 0-1 range, so another new
node was added too "Map Value".
The value input can also be used to tweak blur size with the (todo)
Time Node.

Temporal screenies:
http://www.blender.org/bf/rt.jpg
http://www.blender.org/bf/rt1.jpg
http://www.blender.org/bf/rt2.jpg

BTW: The compositor is very slow still, it recalulates all nodes on each
change still. Persistant memory and dependency checks is coming!

22 files changed:
source/blender/blenkernel/BKE_node.h
source/blender/blenkernel/BKE_scene.h
source/blender/blenkernel/intern/node.c
source/blender/blenkernel/intern/node_composit.c
source/blender/blenkernel/intern/scene.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/include/butspace.h
source/blender/makesdna/DNA_node_types.h
source/blender/makesdna/DNA_scene_types.h
source/blender/render/extern/include/RE_pipeline.h
source/blender/render/intern/include/zbuf.h
source/blender/render/intern/source/envmap.c
source/blender/render/intern/source/pipeline.c
source/blender/render/intern/source/rendercore.c
source/blender/render/intern/source/zbuf.c
source/blender/src/buttons_scene.c
source/blender/src/drawnode.c
source/blender/src/editnode.c
source/blender/src/header_info.c
source/blender/src/previewrender.c
source/blender/src/renderwin.c

index 23004b0ebeafa751f8e171c2dde034dc819d71e6..622236a6264f4b4bcfd2d44445e1ab94526beee6 100644 (file)
@@ -194,6 +194,8 @@ void                        set_node_shader_lamp_loop(void (*lamp_loop_func)(struct ShadeInput *, str
 #define CMP_NODE_ALPHAOVER     210
 #define CMP_NODE_BLUR          211
 #define CMP_NODE_FILTER                212
+#define CMP_NODE_MAP_VALUE     213
+#define CMP_NODE_TIME          214
 
 #define CMP_NODE_IMAGE                 220
 #define CMP_NODE_R_RESULT              221
index 4aa4c09dccc6865a9c4273069d5fb62f40278053..a7e2839d20cbf640521eb459ddf584130aaf0a19 100644 (file)
@@ -75,5 +75,7 @@ void scene_select_base(struct Scene *sce, struct Base *selbase);
 
 void scene_update_for_newframe(struct Scene *sce, unsigned int lay);
 
+void scene_add_render_layer(struct Scene *sce);
+
 #endif
 
index 1b755a84efbab1ea742098b2a01ef2301cafed06..a1f0c4095e244d10002c3bf08a4242b501125f7c 100644 (file)
@@ -754,6 +754,8 @@ bNode *nodeAddNodeType(bNodeTree *ntree, int type, bNodeTree *ngroup)
                        node->storage= curvemapping_add(3, -1.0f, -1.0f, 1.0f, 1.0f);
                else if(type==CMP_NODE_CURVE_RGB)
                        node->storage= curvemapping_add(4, 0.0f, 0.0f, 1.0f, 1.0f);
+               else if(type==CMP_NODE_MAP_VALUE)
+                       node->storage= add_mapping();
        }
        
        return node;
@@ -1188,14 +1190,16 @@ void ntreeSolveOrder(bNodeTree *ntree)
                        for(tnode= ntree->nodes.first; tnode; tnode= tnode->next) {
                                if(tnode->typeinfo->nclass==NODE_CLASS_OUTPUT) {
                                        if(tnode->type==node->type) {
-                                               if(output==0)
-                                                       tnode->flag |= NODE_DO_OUTPUT;
-                                               else
-                                                       tnode->flag &= ~NODE_DO_OUTPUT;
-                                               output= 1;
+                                               if(tnode->flag & NODE_DO_OUTPUT) {
+                                                       if(output>1)
+                                                               tnode->flag &= ~NODE_DO_OUTPUT;
+                                                       output++;
+                                               }
                                        }
                                }
                        }
+                       if(output==0)
+                               node->flag |= NODE_DO_OUTPUT;
                }
        }
        
@@ -1210,14 +1214,6 @@ void ntreeSolveOrder(bNodeTree *ntree)
 static void nodeInitPreview(bNode *node, int xsize, int ysize)
 {
        
-       /* sanity checks & initialize */
-       if(node->preview && node->preview->rect) {
-               if(node->preview->xsize!=xsize && node->preview->ysize!=ysize) {
-                       MEM_freeN(node->preview->rect);
-                       node->preview->rect= NULL;
-               }
-       }
-       
        if(node->preview==NULL) {
                node->preview= MEM_callocN(sizeof(bNodePreview), "node preview");
                printf("added preview %s\n", node->name);
@@ -1226,7 +1222,15 @@ static void nodeInitPreview(bNode *node, int xsize, int ysize)
        /* node previews can get added with variable size this way */
        if(xsize==0 || ysize==0)
                return;
-
+       
+       /* sanity checks & initialize */
+       if(node->preview && node->preview->rect) {
+               if(node->preview->xsize!=xsize && node->preview->ysize!=ysize) {
+                       MEM_freeN(node->preview->rect);
+                       node->preview->rect= NULL;
+               }
+       }
+       
        if(node->preview->rect==NULL) {
                node->preview->rect= MEM_callocN(4*xsize + xsize*ysize*sizeof(float)*4, "node preview rect");
                node->preview->xsize= xsize;
index 0b7d5432614ee96591bdfb3165ffe46377074992..93e5bb8a902c9ffb517445e7d08c400170245b93 100644 (file)
@@ -216,7 +216,7 @@ static void composit2_pixel_processor(bNode *node, CompBuf *out, CompBuf *src_bu
                facx= fac_buf->x;
                facy= fac_buf->y;
                fac_stride= facx;
-               fac_pix= src_buf->type;
+               fac_pix= fac_buf->type;
                fac_data= fac_buf->rect;
        }
        
@@ -408,6 +408,7 @@ static void generate_preview(bNode *node, CompBuf *stackbuf)
 static bNodeSocketType cmp_node_viewer_in[]= {
        {       SOCK_RGBA, 1, "Image",          0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
        {       SOCK_VALUE, 1, "Alpha",         1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+       {       SOCK_VALUE, 1, "Z",             1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
        {       -1, 0, ""       }
 };
 
@@ -415,6 +416,10 @@ static void do_copy_rgba(bNode *node, float *out, float *in)
 {
        QUATCOPY(out, in);
 }
+static void do_copy_value(bNode *node, float *out, float *in)
+{
+       out[0]= in[0];
+}
 static void do_copy_a_rgba(bNode *node, float *out, float *in, float *fac)
 {
        VECCOPY(out, in);
@@ -424,7 +429,7 @@ static void do_copy_a_rgba(bNode *node, float *out, float *in, float *fac)
 static void node_composit_exec_viewer(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
 {
        /* image assigned to output */
-       /* stack order input sockets: col, alpha */
+       /* stack order input sockets: col, alpha, z */
        
        if(node->id && (node->flag & NODE_DO_OUTPUT)) { /* only one works on out */
                Image *ima= (Image *)node->id;
@@ -434,7 +439,7 @@ static void node_composit_exec_viewer(void *data, bNode *node, bNodeStack **in,
                /* scene size? */
                if(1) {
                        RenderData *rd= data;
-                       
+
                        /* re-create output, derive size from scene */
                        rectx= (rd->size*rd->xsch)/100;
                        recty= (rd->size*rd->ysch)/100;
@@ -451,6 +456,14 @@ static void node_composit_exec_viewer(void *data, bNode *node, bNodeStack **in,
                        else
                                composit2_pixel_processor(node, cbuf, in[0]->data, in[0]->vec, in[1]->data, in[1]->vec, do_copy_a_rgba);
                        
+                       if(in[2]->data) {
+                               CompBuf *zbuf= alloc_compbuf(rectx, recty, CB_VAL, 0);
+                               addzbuffloatImBuf(ima->ibuf);
+                               zbuf->rect= ima->ibuf->zbuf_float;
+                               composit1_pixel_processor(node, zbuf, in[2]->data, in[2]->vec, do_copy_value);
+                               free_compbuf(zbuf);
+                       }
+
                        generate_preview(node, cbuf);
                        free_compbuf(cbuf);
                }
@@ -465,8 +478,8 @@ static void node_composit_exec_viewer(void *data, bNode *node, bNodeStack **in,
                        cbuf->rect= NULL;
                }
 
-       }
-       else if(in[0]->data)
+       }       /* lets make only previews when not done yet, so activating doesnt update */
+       else if(in[0]->data && node->preview && node->preview->rect==NULL)
                generate_preview(node, in[0]->data);
 }
 
@@ -486,6 +499,7 @@ static bNodeType cmp_node_viewer= {
 static bNodeSocketType cmp_node_composite_in[]= {
        {       SOCK_RGBA, 1, "Image",          0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
        {       SOCK_VALUE, 1, "Alpha",         1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+       {       SOCK_VALUE, 1, "Z",                     1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
        {       -1, 0, ""       }
 };
 
@@ -493,14 +507,14 @@ static bNodeSocketType cmp_node_composite_in[]= {
 static void node_composit_exec_composite(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
 {
        /* image assigned to output */
-       /* stack order input sockets: col, alpha */
+       /* stack order input sockets: col, alpha, z */
        
        if(node->flag & NODE_DO_OUTPUT) {       /* only one works on out */
                RenderData *rd= data;
                if(rd->scemode & R_DOCOMP) {
                        RenderResult *rr= RE_GetResult(RE_GetRender("Render"));
                        if(rr) {
-                               CompBuf *outbuf;
+                               CompBuf *outbuf, *zbuf=NULL;
                                
                                if(rr->rectf) 
                                        MEM_freeN(rr->rectf);
@@ -511,6 +525,15 @@ static void node_composit_exec_composite(void *data, bNode *node, bNodeStack **i
                                else
                                        composit2_pixel_processor(node, outbuf, in[0]->data, in[0]->vec, in[1]->data, in[1]->vec, do_copy_a_rgba);
                                
+                               if(in[2]->data) {
+                                       if(rr->rectz) 
+                                               MEM_freeN(rr->rectz);
+                                       zbuf= alloc_compbuf(rr->rectx, rr->recty, CB_VAL, 1);
+                                       composit1_pixel_processor(node, zbuf, in[2]->data, in[2]->vec, do_copy_value);
+                                       rr->rectz= zbuf->rect;
+                                       zbuf->malloc= 0;
+                                       free_compbuf(zbuf);
+                               }
                                generate_preview(node, outbuf);
                                
                                /* we give outbuf to rr... */
@@ -675,6 +698,12 @@ static void node_composit_exec_image(void *data, bNode *node, bNodeStack **in, b
                if(out[1]->hasoutput)
                        out[1]->data= alphabuf_from_rgbabuf(stackbuf);
                
+               if(out[2]->hasoutput && ima->ibuf->zbuf_float) {
+                       CompBuf *zbuf= alloc_compbuf(ima->ibuf->x, ima->ibuf->y, CB_VAL, 0);
+                       zbuf->rect= ima->ibuf->zbuf_float;
+                       out[2]->data= zbuf;
+               }
+               
                generate_preview(node, stackbuf);
        }       
 }
@@ -705,28 +734,36 @@ static void node_composit_exec_rresult(void *data, bNode *node, bNodeStack **in,
 {
        RenderResult *rr= RE_GetResult(RE_GetRender("Render"));
        if(rr) {
-               RenderLayer *rl= rr->layers.first;
-               CompBuf *stackbuf;
-               
-               /* we put render rect on stack, cbuf knows rect is from other ibuf when freed! */
-               stackbuf= alloc_compbuf(rr->rectx, rr->recty, CB_RGBA, 0);
-               stackbuf->rect= rl->rectf;
-               
-               /* put on stack */      
-               out[0]->data= stackbuf;
-               
-               if(out[1]->hasoutput)
-                       out[1]->data= alphabuf_from_rgbabuf(stackbuf);
-               
-               generate_preview(node, stackbuf);
+               RenderLayer *rl= BLI_findlink(&rr->layers, node->custom1);
+               if(rl) {
+                       CompBuf *stackbuf;
+                       
+                       /* we put render rect on stack, cbuf knows rect is from other ibuf when freed! */
+                       stackbuf= alloc_compbuf(rr->rectx, rr->recty, CB_RGBA, 0);
+                       stackbuf->rect= rl->rectf;
+                       
+                       /* put on stack */      
+                       out[0]->data= stackbuf;
+                       
+                       if(out[1]->hasoutput)
+                               out[1]->data= alphabuf_from_rgbabuf(stackbuf);
+                       if(out[2]->hasoutput && rl->rectz) {
+                               CompBuf *zbuf= alloc_compbuf(rr->rectx, rr->recty, CB_VAL, 0);
+                               zbuf->rect= rl->rectz;
+                               out[2]->data= zbuf;
+                       }
+                       
+                       generate_preview(node, stackbuf);
+               }
        }       
 }
 
+/* custom1 = render layer in use */
 static bNodeType cmp_node_rresult= {
        /* type code   */       CMP_NODE_R_RESULT,
        /* name        */       "Render Result",
        /* width+range */       120, 80, 300,
-       /* class+opts  */       NODE_CLASS_GENERATOR, NODE_PREVIEW,
+       /* class+opts  */       NODE_CLASS_GENERATOR, NODE_PREVIEW|NODE_OPTIONS,
        /* input sock  */       NULL,
        /* output sock */       cmp_node_rresult_out,
        /* storage     */       "",
@@ -951,6 +988,7 @@ static void node_composit_exec_mix_rgb(void *data, bNode *node, bNodeStack **in,
        }
 }
 
+/* custom1 = mix type */
 static bNodeType cmp_node_mix_rgb= {
        /* type code   */       CMP_NODE_MIX_RGB,
        /* name        */       "Mix",
@@ -1082,6 +1120,7 @@ static void node_composit_exec_filter(void *data, bNode *node, bNodeStack **in,
        }
 }
 
+/* custom1 = filter type */
 static bNodeType cmp_node_filter= {
        /* type code   */       CMP_NODE_FILTER,
        /* name        */       "Filter",
@@ -1255,9 +1294,65 @@ static bNodeType cmp_node_alphaover= {
        
 };
 
+/* **************** MAP VALUE ******************** */
+static bNodeSocketType cmp_node_map_value_in[]= {
+       {       SOCK_VALUE, 1, "Value",                 1.0f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+static bNodeSocketType cmp_node_map_value_out[]= {
+       {       SOCK_VALUE, 0, "Value",                 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+
+static void do_map_value(bNode *node, float *out, float *src)
+{
+       TexMapping *texmap= node->storage;
+       
+       out[0]= (src[0] + texmap->loc[0])*texmap->size[0];
+       if(texmap->flag & TEXMAP_CLIP_MIN)
+               if(out[0]<texmap->min[0])
+                       out[0]= texmap->min[0];
+       if(texmap->flag & TEXMAP_CLIP_MAX)
+               if(out[0]>texmap->max[0])
+                       out[0]= texmap->max[0];
+}
+
+static void node_composit_exec_map_value(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       /* stack order in: col col */
+       /* stack order out: col */
+       
+       /* input no image? then only value operation */
+       if(in[0]->data==NULL) {
+               do_map_value(node, out[0]->vec, in[0]->vec);
+       }
+       else {
+               /* make output size of input image */
+               CompBuf *cbuf= in[0]->data;
+               CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1); // allocs
+               
+               composit1_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, do_map_value);
+               
+               out[0]->data= stackbuf;
+       }
+}
+
+static bNodeType cmp_node_map_value= {
+       /* type code   */       CMP_NODE_MAP_VALUE,
+       /* name        */       "Map Value",
+       /* width+range */       100, 60, 150,
+       /* class+opts  */       NODE_CLASS_OPERATOR, NODE_OPTIONS,
+       /* input sock  */       cmp_node_map_value_in,
+       /* output sock */       cmp_node_map_value_out,
+       /* storage     */       "TexMapping",
+       /* execfunc    */       node_composit_exec_map_value
+       
+};
+
 /* **************** GAUSS BLUR ******************** */
 static bNodeSocketType cmp_node_blur_in[]= {
        {       SOCK_RGBA, 1, "Image",                  0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+       {       SOCK_VALUE, 1, "Size",                  1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
        {       -1, 0, ""       }
 };
 static bNodeSocketType cmp_node_blur_out[]= {
@@ -1265,224 +1360,424 @@ static bNodeSocketType cmp_node_blur_out[]= {
        {       -1, 0, ""       }
 };
 
-
-static void node_composit_exec_blur(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+static float *make_gausstab(int rad)
 {
-       CompBuf *new, *work, *img= in[0]->data;
-       register float sum, val;
-       float rval, gval, bval, aval;
-       float *gausstab, *v;
-       int r, n, m;
-       int x, y;
-       int i;
-       int step, bigstep;
-       float *src, *dest;
-
-       
-       if(img==NULL || out[0]->hasoutput==0)
-               return;
-       
-       /* make output size of input image */
-       new= alloc_compbuf(img->x, img->y, CB_RGBA, 1); // allocs
-       out[0]->data= new;
+       float *gausstab, sum, val;
+       int i, n;
        
-       /* prepare for gauss tab */
-       r = (1.5 * node->custom1 + 1.5);
-       n = 2 * r + 1;
-       
-       /* ugly : */
-       if ((img->x <= n) || (img->y <= n)) {
-               printf("gauss filter too large/n");
-               return;
-       }
+       n = 2 * rad + 1;
        
        gausstab = (float *) MEM_mallocN(n * sizeof(float), "gauss");
        
        sum = 0.0f;
-       v = gausstab;
-       for (x = -r; x <= r; x++) {
-               val = exp(-4*(float ) (x*x)/ (float) (r*r));
+       for (i = -rad; i <= rad; i++) {
+               val = exp(-4.0*((float)i*i) / (float) (rad*rad));
                sum += val;
-               *v++ = val;
+               gausstab[i+rad] = val;
        }
        
-       i = n;
-       v = gausstab;
-       while (i--) {
-               *v++ /= sum;
+       sum= 1.0f/sum;
+       for(i=0; i<n; i++)
+               gausstab[i]*= sum;
+       
+       return gausstab;
+}
+
+static float *make_bloomtab(int rad)
+{
+       float *bloomtab, val;
+       int i, n;
+       
+       n = 2 * rad + 1;
+       
+       bloomtab = (float *) MEM_mallocN(n * sizeof(float), "bloom");
+       
+       for (i = -rad; i <= rad; i++) {
+               val = pow(1.0 - fabs((float)i)/((float)rad), 4.0);
+               bloomtab[i+rad] = val;
        }
        
+       return bloomtab;
+}
+
+static void blur_single_image(CompBuf *new, CompBuf *img, float blurx, float blury)
+{
+       CompBuf *work;
+       register float sum, val;
+       float rval, gval, bval, aval;
+       float *gausstab, *gausstabcent;
+       int rad, imgx= img->x, imgy= img->y;
+       int x, y, pix= img->type;
+       int i, bigstep;
+       float *src, *dest;
+
        /* helper image */
-       work= alloc_compbuf(img->x, img->y, CB_RGBA, 1); // allocs
+       work= alloc_compbuf(imgx, imgy, img->type, 1); // allocs
        
        /* horizontal */
-       step = (n - 1);
+       rad = ceil(blurx);
+       if(rad>imgx/2)
+               rad= imgx/2;
+       else if(rad<1) 
+               rad= 1;
+
+       gausstab= make_gausstab(rad);
+       gausstabcent= gausstab+rad;
        
-       for (y = 0; y < img->y; y++) {
-               src = img->rect + 4*(y * img->x);
-               dest = work->rect + 4*(y * img->x);
+       for (y = 0; y < imgy; y++) {
+               float *srcd= img->rect + pix*(y*img->x);
                
-               for (x = r; x > 0 ; x--) {
-                       m = n - x;
-                       gval = rval= bval= aval= 0.0f;
-                       sum = 0.0;
-                       v = gausstab + x;
-                       for (i = 0; i < m; i++) {
-                               val = *v++;
-                               sum += val;
-                               rval += val * (*src++);
-                               gval += val * (*src++);
-                               bval += val * (*src++);
-                               aval += val * (*src++);
-                       }
-                       *dest++ = rval / sum;
-                       *dest++ = gval / sum;
-                       *dest++ = bval / sum;
-                       *dest++ = aval / sum;
-                       
-                       src -= 4*m;
-               }
+               dest = work->rect + pix*(y * img->x);
                
-               for (x = 0; x <= (img->x - n); x++) {
-                       gval = rval= bval= aval= 0.0f;
-                       v = gausstab;
+               for (x = 0; x < imgx ; x++) {
+                       int minr= x-rad<0?-x:-rad;
+                       int maxr= x+rad>imgx?imgx-x:rad;
                        
-                       for (i = 0; i < n; i++) {
-                               val = *v++;
+                       src= srcd + pix*(x+minr);
+                       
+                       sum= gval = rval= bval= aval= 0.0f;
+                       for (i= minr; i < maxr; i++) {
+                               val= gausstabcent[i];
+                               sum+= val;
                                rval += val * (*src++);
-                               gval += val * (*src++);
-                               bval += val * (*src++);
-                               aval += val * (*src++);
+                               if(pix==4) {
+                                       gval += val * (*src++);
+                                       bval += val * (*src++);
+                                       aval += val * (*src++);
+                               }
                        }
-                       *dest++ = rval;
-                       *dest++ = gval;
-                       *dest++ = bval;
-                       *dest++ = aval;
-                       src -= 4*step;
-               }       
-               
-               for (x = 1; x <= r ; x++) {
-                       m = n - x;
-                       gval = rval= bval= aval= 0.0f;
-                       sum = 0.0;
-                       v = gausstab;
-                       for (i = 0; i < m; i++) {
-                               val = *v++;
-                               sum += val;
-                               rval += val * (*src++);
-                               gval += val * (*src++);
-                               bval += val * (*src++);
-                               aval += val * (*src++);
+                       sum= 1.0f/sum;
+                       *dest++ = rval*sum;
+                       if(pix==4) {
+                               *dest++ = gval*sum;
+                               *dest++ = bval*sum;
+                               *dest++ = aval*sum;
                        }
-                       *dest++ = rval / sum;
-                       *dest++ = gval / sum;
-                       *dest++ = bval / sum;
-                       *dest++ = aval / sum;
-                       src -= 4*(m - 1);
                }
        }
        
        /* vertical */
        MEM_freeN(gausstab);
        
-       /* prepare for gauss tab */
-       r = (1.5 * node->custom2 + 1.5);
-       n = 2 * r + 1;
+       rad = ceil(blury);
+       if(rad>imgy/2)
+               rad= imgy/2;
+       else if(rad<1) 
+               rad= 1;
+
+       gausstab= make_gausstab(rad);
+       gausstabcent= gausstab+rad;
        
-       /* ugly : */
-       if ((img->x <= n) || (img->y <= n)) {
-               printf("gauss filter too large/n");
-               return;
+       bigstep = pix*imgx;
+       for (x = 0; x < imgx; x++) {
+               float *srcd= work->rect + pix*x;
+               
+               dest = new->rect + pix*x;
+               
+               for (y = 0; y < imgy ; y++) {
+                       int minr= y-rad<0?-y:-rad;
+                       int maxr= y+rad>imgy?imgy-y:rad;
+                       
+                       src= srcd + bigstep*(y+minr);
+                       
+                       sum= gval = rval= bval= aval= 0.0f;
+                       for (i= minr; i < maxr; i++) {
+                               val= gausstabcent[i];
+                               sum+= val;
+                               rval += val * src[0];
+                               if(pix==4) {
+                                       gval += val * src[1];
+                                       bval += val * src[2];
+                                       aval += val * src[3];
+                               }
+                               src += bigstep;
+                       }
+                       sum= 1.0f/sum;
+                       dest[0] = rval*sum;
+                       if(pix==4) {
+                               dest[1] = gval*sum;
+                               dest[2] = bval*sum;
+                               dest[3] = aval*sum;
+                       }
+                       dest+= bigstep;
+               }
        }
        
-       gausstab = (float *) MEM_mallocN(n * sizeof(float), "gauss");
+       free_compbuf(work);
+       MEM_freeN(gausstab);
+}
+
+/* reference has to be mapped 0-1, and equal in size */
+static void bloom_with_reference(CompBuf *new, CompBuf *img, CompBuf *ref, float blurx, float blury)
+{
+       CompBuf *wbuf;
+       register float val;
+       float radxf, radyf;
+       float **maintabs;
+       float *gausstabx, *gausstabcenty;
+       float *gausstaby, *gausstabcentx;
+       int radx, rady, imgx= img->x, imgy= img->y;
+       int x, y;
+       int i, j;
+       float *src, *dest, *wb;
        
-       sum = 0.0f;
-       v = gausstab;
-       for (x = -r; x <= r; x++) {
-               val = exp(-4*(float ) (x*x)/ (float) (r*r));
-               sum += val;
-               *v++ = val;
-       }
+       wbuf= alloc_compbuf(imgx, imgy, CB_VAL, 1);
+       memset(wbuf->rect, sizeof(float)*imgx*imgy, 0);
        
-       i = n;
-       v = gausstab;
-       while (i--) {
-               *v++ /= sum;
-       }
+       /* horizontal */
+       radx = ceil(blurx);
+       if(radx>imgx/2)
+               radx= imgx/2;
+       else if(radx<1) 
+               radx= 1;
        
-       step = img->x;
-       bigstep = (n - 1) * step;
-       for (x = 0; x < step  ; x++) {
-               dest = new->rect + 4*x;
-               src = work->rect + 4*x;
+       /* vertical */
+       rady = ceil(blury);
+       if(rady>imgy/2)
+               rady= imgy/2;
+       else if(rady<1) 
+               rady= 1;
+       
+       x= MAX2(radx, rady);
+       maintabs= MEM_mallocN(x*sizeof(void *), "gauss array");
+       for(i= 0; i<x; i++)
+               maintabs[i]= make_bloomtab(i+1);
                
-               for (y = r; y > 0; y--) {
-                       m = n - y;
-                       gval = rval= bval= aval= 0.0f;
-                       sum = 0.0;
-                       v = gausstab + y;
-                       for (i = 0; i < m; i++) {
-                               val = *v++;
-                               sum += val;
-                               rval += val * src[0];
-                               gval += val * src[1];
-                               bval += val * src[2];
-                               aval += val * src[3];
-                               src += 4 * step;
+       /* vars to store before we go */
+//     refd= ref->rect;
+       src= img->rect;
+       
+       memset(new->rect, 4*imgx*imgy, 0);
+       
+       radxf= (float)radx;
+       radyf= (float)rady;
+       
+       for (y = 0; y < imgy; y++) {
+               for (x = 0; x < imgx ; x++, src+=4) {//, refd++) {
+                       
+//                     int refradx= (int)(refd[0]*radxf);
+//                     int refrady= (int)(refd[0]*radyf);
+                       
+                       int refradx= (int)(radxf*0.3f*src[3]*(src[0]+src[1]+src[2]));
+                       int refrady= (int)(radyf*0.3f*src[3]*(src[0]+src[1]+src[2]));
+                       
+                       if(refradx>radx) refradx= radx;
+                       else if(refradx<1) refradx= 1;
+                       if(refrady>rady) refrady= rady;
+                       else if(refrady<1) refrady= 1;
+                       
+                       if(refradx==1 && refrady==1) {
+                               wb= wbuf->rect + ( y*imgx + x);
+                               dest= new->rect + 4*( y*imgx + x);
+                               wb[0]+= 1.0f;
+                               dest[0] += src[0];
+                               dest[1] += src[1];
+                               dest[2] += src[2];
+                               dest[3] += src[3];
                        }
-                       dest[0] = rval / sum;
-                       dest[1] = gval / sum;
-                       dest[2] = bval / sum;
-                       dest[3] = aval / sum;
-                       src -= 4 * m * step;
-                       dest+= 4 * step;
-               }
-               for (y = 0; y <= (img->y - n); y++) {
-                       gval = rval= bval= aval= 0.0f;
-                       v = gausstab;
-                       for (i = 0; i < n; i++) {
-                               val = *v++;
-                               rval += val * src[0];
-                               gval += val * src[1];
-                               bval += val * src[2];
-                               aval += val * src[3];
-                               src += 4 * step;
+                       else {
+                               int minxr= x-refradx<0?-x:-refradx;
+                               int maxxr= x+refradx>imgx?imgx-x:refradx;
+                               int minyr= y-refrady<0?-y:-refrady;
+                               int maxyr= y+refrady>imgy?imgy-y:refrady;
+                               
+                               float *destd= new->rect + 4*( (y + minyr)*imgx + x + minxr);
+                               float *wbufd= wbuf->rect + ( (y + minyr)*imgx + x + minxr);
+                               
+                               gausstabx= maintabs[refradx-1];
+                               gausstabcentx= gausstabx+refradx;
+                               gausstaby= maintabs[refrady-1];
+                               gausstabcenty= gausstaby+refrady;
+                               
+                               for (i= minyr; i < maxyr; i++, destd+= 4*imgx, wbufd+= imgx) {
+                                       dest= destd;
+                                       wb= wbufd;
+                                       for (j= minxr; j < maxxr; j++, dest+=4, wb++) {
+                                               
+                                               val= gausstabcenty[i]*gausstabcentx[j];
+                                               wb[0]+= val;
+                                               dest[0] += val * src[0];
+                                               dest[1] += val * src[1];
+                                               dest[2] += val * src[2];
+                                               dest[3] += val * src[3];
+                                       }
+                               }
                        }
-                       dest[0] = rval;
-                       dest[1] = gval;
-                       dest[2] = bval;
-                       dest[3] = aval;
-                       dest += 4 * step;
-                       src -= 4 * bigstep;
                }
-               for (y = 1; y <= r ; y++) {
-                       m = n - y;
-                       gval = rval= bval= aval= 0.0f;
-                       sum = 0.0;
-                       v = gausstab;
-                       for (i = 0; i < m; i++) {
-                               val = *v++;
-                               sum += val;
-                               rval += val * src[0];
-                               gval += val * src[1];
-                               bval += val * src[2];
-                               aval += val * src[3];
-                               src += 4 * step;
+       }
+       
+       x= imgx*imgy;
+       dest= new->rect;
+       wb= wbuf->rect;
+       while(x--) {
+               val= 1.0f/wb[0];
+               dest[0]*= val;
+               dest[1]*= val;
+               dest[2]*= val;
+               dest[3]*= val;
+               wb++;
+               dest+= 4;
+       }
+       
+       free_compbuf(wbuf);
+       
+       x= MAX2(radx, rady);
+       for(i= 0; i<x; i++)
+               MEM_freeN(maintabs[i]);
+       MEM_freeN(maintabs);
+       
+}
+
+/* reference has to be mapped 0-1, and equal in size */
+static void blur_with_reference(CompBuf *new, CompBuf *img, CompBuf *ref, float blurx, float blury)
+{
+       CompBuf *blurbuf;
+       register float sum, val;
+       float rval, gval, bval, aval, radxf, radyf;
+       float **maintabs;
+       float *gausstabx, *gausstabcenty;
+       float *gausstaby, *gausstabcentx;
+       int radx, rady, imgx= img->x, imgy= img->y;
+       int x, y;
+       int i, j;
+       float *src, *dest, *refd, *blurd;
+
+       /* trick is; we blur the reference image... but only works with clipped values*/
+       blurbuf= alloc_compbuf(imgx, imgy, CB_VAL, 1);
+       blurd= blurbuf->rect;
+       refd= ref->rect;
+       for(x= imgx*imgy; x>0; x--, refd++, blurd++) {
+               if(refd[0]<0.0f) blurd[0]= 0.0f;
+               else if(refd[0]>1.0f) blurd[0]= 1.0f;
+               else blurd[0]= refd[0];
+       }
+       
+       blur_single_image(blurbuf, blurbuf, blurx, blury);
+       
+       /* horizontal */
+       radx = ceil(blurx);
+       if(radx>imgx/2)
+               radx= imgx/2;
+       else if(radx<1) 
+               radx= 1;
+       
+       /* vertical */
+       rady = ceil(blury);
+       if(rady>imgy/2)
+               rady= imgy/2;
+       else if(rady<1) 
+               rady= 1;
+       
+       x= MAX2(radx, rady);
+       maintabs= MEM_mallocN(x*sizeof(void *), "gauss array");
+       for(i= 0; i<x; i++)
+               maintabs[i]= make_gausstab(i+1);
+       
+       refd= blurbuf->rect;
+       dest= new->rect;
+       radxf= (float)radx;
+       radyf= (float)rady;
+       
+       for (y = 0; y < imgy; y++) {
+               for (x = 0; x < imgx ; x++, dest+=4, refd++) {
+                       int refradx= (int)(refd[0]*radxf);
+                       int refrady= (int)(refd[0]*radyf);
+                       
+                       if(refradx>radx) refradx= radx;
+                       else if(refradx<1) refradx= 1;
+                       if(refrady>rady) refrady= rady;
+                       else if(refrady<1) refrady= 1;
+
+                       if(refradx==1 && refrady==1) {
+                               src= img->rect + 4*( y*imgx + x);
+                               QUATCOPY(dest, src);
+                       }
+                       else {
+                               int minxr= x-refradx<0?-x:-refradx;
+                               int maxxr= x+refradx>imgx?imgx-x:refradx;
+                               int minyr= y-refrady<0?-y:-refrady;
+                               int maxyr= y+refrady>imgy?imgy-y:refrady;
+       
+                               float *srcd= img->rect + 4*( (y + minyr)*imgx + x + minxr);
+                               
+                               gausstabx= maintabs[refradx-1];
+                               gausstabcentx= gausstabx+refradx;
+                               gausstaby= maintabs[refrady-1];
+                               gausstabcenty= gausstaby+refrady;
+
+                               sum= gval = rval= bval= aval= 0.0f;
+                               
+                               for (i= minyr; i < maxyr; i++, srcd+= 4*imgx) {
+                                       src= srcd;
+                                       for (j= minxr; j < maxxr; j++, src+=4) {
+                                       
+                                               val= gausstabcenty[i]*gausstabcentx[j];
+                                               sum+= val;
+                                               rval += val * src[0];
+                                               gval += val * src[1];
+                                               bval += val * src[2];
+                                               aval += val * src[3];
+                                       }
+                               }
+                               sum= 1.0f/sum;
+                               dest[0] = rval*sum;
+                               dest[1] = gval*sum;
+                               dest[2] = bval*sum;
+                               dest[3] = aval*sum;
                        }
-                       dest[0] = rval / sum;
-                       dest[1] = gval / sum;
-                       dest[2] = bval / sum;
-                       dest[3] = aval / sum;
-                       dest += 4* step;
-                       src -= 4 * (m - 1) * step;
                }
        }
+       
+       free_compbuf(blurbuf);
+       
+       x= MAX2(radx, rady);
+       for(i= 0; i<x; i++)
+               MEM_freeN(maintabs[i]);
+       MEM_freeN(maintabs);
+       
+}
 
-       free_compbuf(work);
-       MEM_freeN(gausstab);
+
+
+static void node_composit_exec_blur(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       CompBuf *new, *img= in[0]->data;
+       
+       if(img==NULL || out[0]->hasoutput==0)
+               return;
+       
+       /* if fac input, we do it different */
+       if(in[1]->data) {
+               
+               /* test fitness if reference */
+               
+               /* make output size of input image */
+               new= alloc_compbuf(img->x, img->y, CB_RGBA, 1); // allocs
+               
+               blur_with_reference(new, img, in[1]->data, (float)node->custom1, (float)node->custom2);
+               
+               out[0]->data= new;
+       }
+       else {
+               if(in[1]->vec[0]==0.0f) {
+                       /* pass on image */
+                       new= alloc_compbuf(img->x, img->y, img->type, 0);
+                       new->rect= img->rect;
+               }
+               else {
+                       /* make output size of input image */
+                       new= alloc_compbuf(img->x, img->y, img->type, 1); // allocs
+                       if(1)
+                               blur_single_image(new, img, in[1]->vec[0]*(float)node->custom1, in[1]->vec[0]*(float)node->custom2);
+                       else    /* bloom experimental... */
+                               bloom_with_reference(new, img, NULL, in[1]->vec[0]*(float)node->custom1, in[1]->vec[0]*(float)node->custom2);
+               }
+               out[0]->data= new;
+       }
 }
+       
 
+/* custom1 custom2 = blur filter size */
 static bNodeType cmp_node_blur= {
        /* type code   */       CMP_NODE_BLUR,
        /* name        */       "Blur",
@@ -1516,6 +1811,7 @@ bNodeType *node_all_composit[]= {
        &cmp_node_rresult,
        &cmp_node_alphaover,
        &cmp_node_blur,
+       &cmp_node_map_value,
        NULL
 };
 
index 546a22c361bba84177b0ebce2eed37bfb3fbdd0c..1a42c299335bd279a0a39032779c497afe69cae0 100644 (file)
@@ -114,6 +114,8 @@ void free_qtcodecdata(QuicktimeCodecData *qcd)
        }
 }
 
+/* copy_scene moved to src/header_info.c... should be back */
+
 /* do not free scene itself */
 void free_scene(Scene *sce)
 {
@@ -144,6 +146,7 @@ void free_scene(Scene *sce)
        }
        
        BLI_freelistN(&sce->markers);
+       BLI_freelistN(&sce->r.layers);
        
        if(sce->toolsettings){
                MEM_freeN(sce->toolsettings);
@@ -224,6 +227,8 @@ Scene *add_scene(char *name)
        BLI_init_rctf(&sce->r.safety, 0.1f, 0.9f, 0.1f, 0.9f);
        sce->r.osa= 8;
        
+       scene_add_render_layer(sce);
+       
        return sce;
 }
 
@@ -479,3 +484,19 @@ void scene_update_for_newframe(Scene *sce, unsigned int lay)
                setcount++;
        }
 }
+
+/* return default layer, also used to patch old files */
+void scene_add_render_layer(Scene *sce)
+{
+       SceneRenderLayer *srl;
+       int tot= 1 + BLI_countlist(&sce->r.layers);
+       
+       srl= MEM_callocN(sizeof(SceneRenderLayer), "new render layer");
+       sprintf(srl->name, "%d RenderLayer", tot);
+       BLI_addtail(&sce->r.layers, srl);
+       
+       srl->lay= (1<<20) -1;
+       srl->layflag= 0x7FFF;   /* solid ztra halo strand */
+       srl->passflag= SCE_PASS_COMBINED|SCE_PASS_Z;
+}
+
index 3cd31740520280562c34f4032d0d603deaf6c2ea..5433d2b7ce1d3c2acb0e07bf94524f36944a36ef 100644 (file)
@@ -2807,6 +2807,7 @@ static void direct_link_scene(FileData *fd, Scene *sce)
        }
        
        link_list(fd, &(sce->markers));
+       link_list(fd, &(sce->r.layers));
        
        sce->nodetree= newdataadr(fd, sce->nodetree);
        if(sce->nodetree)
@@ -5259,6 +5260,9 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                for(sce= main->scene.first; sce; sce= sce->id.next) {
                        if(sce->r.xparts<2) sce->r.xparts= 4;
                        if(sce->r.yparts<2) sce->r.yparts= 4;
+                       /* adds default layer */
+                       if(sce->r.layers.first==NULL)
+                               scene_add_render_layer(sce);
                }
        }
        
index 2bf263aa7e4205f8722071975dec52a5496161dc..ccd9314d4fdcf63a6191deab2eabcdd97fb25e92 100644 (file)
@@ -1137,7 +1137,8 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
        MetaStack *ms;
        Strip *strip;
        TimeMarker *marker;
-
+       SceneRenderLayer *srl;
+       
        sce= scebase->first;
        while(sce) {
                /* write LibData */
@@ -1213,11 +1214,11 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
                }
 
                /* writing dynamic list of TimeMarkers to the blend file */
-               marker= sce->markers.first;
-               while(marker){
+               for(marker= sce->markers.first; marker; marker= marker->next)
                        writestruct(wd, DATA, "TimeMarker", 1, marker);
-                       marker= marker->next;
-               }
+               
+               for(srl= sce->r.layers.first; srl; srl= srl->next)
+                       writestruct(wd, DATA, "SceneRenderLayer", 1, srl);
                
                if(sce->nodetree) {
                        writestruct(wd, DATA, "bNodeTree", 1, sce->nodetree);
index aca652d52bdd52642cb24a74e96ab6eed83e1c4e..bc6529f1d3ddd0ced52ebd95bbac1f98c9e2f8a4 100644 (file)
@@ -319,8 +319,9 @@ void curvemap_buttons(struct uiBlock *block, struct CurveMapping *cumap, char la
 #define B_SWITCHRENDER         1641
 #define B_FBUF_REDO            1642
 
-#define B_SET_EDGE             1643
-#define B_SET_ZBLUR            1644
+#define B_SET_EDGE                     1643
+#define B_SET_ZBLUR                    1644
+#define B_ADD_RENDERLAYER      1645
 
 /* *********************** */
 #define B_ARMATUREBUTS         1800
index 5ec487ab3d07dedde28f102f4a43a35608ba162e..700de9531dacbba50b96e568d09dc880e0c13a2d 100644 (file)
 #ifndef DNA_NODE_TYPES_H
 #define DNA_NODE_TYPES_H
 
+#include "DNA_ID.h"
 #include "DNA_vec_types.h"
 #include "DNA_listBase.h"
 
-struct ID;
+
 struct SpaceNode;
 struct bNodeLink;
 struct bNodeType;
index 2f3452c5c757be864281d1f1fd03239de3f11a35..01776a2e98120202dc1d2a351a1e0596baf453b2 100644 (file)
@@ -94,6 +94,34 @@ typedef struct AudioData {
        short pad[3];
 } AudioData;
 
+typedef struct SceneRenderLayer {
+       struct SceneRenderLayer *next, *prev;
+       
+       char name[32];
+       struct Scene *scene;    /* unused still */
+       unsigned int lay;               /* scene->lay itself has priority over this */
+       short layflag;
+       short passflag;
+} SceneRenderLayer;
+
+/* srl->layflag */
+#define SCE_LAY_SOLID  1
+#define SCE_LAY_ZTRA   2
+#define SCE_LAY_HALO   4
+#define SCE_LAY_STRAND 8
+
+/* srl->passflag */
+#define SCE_PASS_COMBINED      1
+#define SCE_PASS_Z                     2
+#define SCE_PASS_RGBA          4
+#define SCE_PASS_DIFFUSE       8
+#define SCE_PASS_SPEC          16
+#define SCE_PASS_SHADOW                32
+#define SCE_PASS_AO                    64
+#define SCE_PASS_MIRROR                128
+#define SCE_PASS_NORMAL                256
+#define SCE_PASS_VECTOR                512
+
 typedef struct RenderData {
        struct AviCodecData *avicodecdata;
        struct QuicktimeCodecData *qtcodecdata;
@@ -209,6 +237,11 @@ typedef struct RenderData {
        /* safety and border rect */
        rctf safety, border;
        
+       /* information on different layers to be rendered */
+       ListBase layers;
+       short actlay, pad;
+       int pad2;
+       
        /**
         * The gamma for the normal rendering. Used when doing
         * oversampling, to correctly blend subpixels to pixels.  */
index b0a12d7f35789676993b12af3032b8cc447d4f99..d34fc968e773c478b8e0c05f30bed2654f11d230 100644 (file)
@@ -60,8 +60,10 @@ typedef struct Render Render;
 typedef struct RenderLayer {
        struct RenderLayer *next, *prev;
        
-       char name[RE_MAXNAME];
-       int flag, type;
+       /* copy of RenderData */
+       char name[RE_MAXNAME];          
+       unsigned int lay;                       
+       int layflag, passflag;          
        
        float *rectf;   /* standard rgba buffer */
        float *rectz;   /* standard camera coordinate zbuffer */
@@ -88,6 +90,7 @@ typedef struct RenderResult {
        
        /* the main buffers */
        ListBase layers;
+       int actlay;                             /* copy of renderdata..., so display callbacks can find out */
        
        /* optional saved endresult on disk */
        char exrfile[FILE_MAXDIR];
index 7a6c78d5728a574fc05ba637f8275a7371bd810a..82455088565592a5223c796002301dc6646b9907 100644 (file)
@@ -31,6 +31,7 @@
 #define ZBUF_H
 
 struct RenderPart;
+struct RenderLayer;
 struct LampRen;
 struct VlakRen;
 struct ListBase;
@@ -47,8 +48,9 @@ int testclip(float *v);
 
 void set_part_zbuf_clipflag(struct RenderPart *pa);
 void zbuffer_shadow(struct Render *re, struct LampRen *lar, int *rectz, int size);
-void zbuffer_solid(struct RenderPart *pa);
-void zbuffer_transp_shade(struct RenderPart *pa, float *pass);
+void zbuffer_solid(struct RenderPart *pa, unsigned int layer, short layflag);
+void zbuffer_transp_shade(struct RenderPart *pa, float *pass, unsigned int layer, short layflag);
+void convert_zbuf_to_distbuf(struct RenderPart *pa, struct RenderLayer *rl);
 
 typedef struct APixstr {
     unsigned short mask[4]; /* jitter mask */
index d38ff7d2d384d0433ac73eeaf14c70e3c38c4eda..80e902e2a453eafafa5ae607c2698766aa607602 100644 (file)
@@ -126,8 +126,9 @@ static Render *envmap_render_copy(Render *re, EnvMap *env)
        /* set up renderdata */
        envre->r= re->r;
        envre->r.mode &= ~(R_BORDER | R_PANORAMA | R_ORTHO | R_MBLUR);
+       envre->r.layers.first= envre->r.layers.last= NULL;
        envre->r.filtertype= 0;
-       envre->r.xparts= envre->r.yparts= 1;
+       envre->r.xparts= envre->r.yparts= 2;
        envre->r.bufflag= 0;
        envre->r.size= 100;
        envre->r.yasp= envre->r.xasp= 1;
index 1cbe6273757ddf5ee31e4ef8f86958d5954df92c..b53393b1cd0fe7b84648a62742c831709f1ce964 100644 (file)
@@ -154,6 +154,8 @@ static void free_render_result(RenderResult *res)
        
        if(res->rect32)
                MEM_freeN(res->rect32);
+       if(res->rectz)
+               MEM_freeN(res->rectz);
        if(res->rectf)
                MEM_freeN(res->rectf);
        
@@ -168,6 +170,7 @@ static RenderResult *new_render_result(Render *re, rcti *partrct, int crop)
 {
        RenderResult *rr;
        RenderLayer *rl;
+       SceneRenderLayer *srl;
        int rectx, recty;
        
        rectx= partrct->xmax - partrct->xmin;
@@ -188,64 +191,89 @@ 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;
        
-       /* check renderdata for amount of layers */
-       /* for now just one */
-       rl= RE_callocN(sizeof(RenderLayer), "new render layer");
-       BLI_addtail(&rr->layers, rl);
+       /* copy, so display callbacks can find out too */
+       rr->actlay= re->r.actlay;
        
-       rl->rectf= RE_callocN(rectx*recty*sizeof(float)*4, "layer float rgba");
-       rl->rectz= RE_callocN(rectx*recty*sizeof(float), "layer float Z");
+       /* check renderdata for amount of layers */
+       for(srl= re->r.layers.first; srl; srl= srl->next) {
+               rl= RE_callocN(sizeof(RenderLayer), "new render layer");
+               BLI_addtail(&rr->layers, rl);
+               
+               strcpy(rl->name, srl->name);
+               rl->lay= srl->lay;
+               rl->layflag= srl->layflag;
+               rl->passflag= srl->passflag;
+               
+               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");
+               
+       }
+       /* previewrender and envmap don't do layers, so we make a default one */
+       if(rr->layers.first==NULL) {
+               rl= RE_callocN(sizeof(RenderLayer), "new render layer");
+               BLI_addtail(&rr->layers, rl);
+               
+               rl->rectf= RE_callocN(rectx*recty*sizeof(float)*4, "layer float rgba");
+               rl->rectz= RE_callocN(rectx*recty*sizeof(float), "layer float Z");
+       }
        
        return rr;
 }
 
 
 /* used when rendering to a full buffer, or when reading the exr part-layer-pass file */
-/* no test happens here if it fits... */
+/* no test happens here if it fits... we also assume layers are in sync */
 /* is used within threads */
 static void merge_render_result(RenderResult *rr, RenderResult *rrpart)
 {
-       RenderLayer *rl= rr->layers.first;
-       RenderLayer *rlp= rrpart->layers.first;
+       RenderLayer *rl, *rlp;
        float *rf, *rfp;
-       int *rz=NULL, *rzp;
+       float *rz, *rzp;
        int y, height, len, copylen;
        
-       if(rlp->rectf==NULL) return;
-       if(rl->rectf==NULL) return;
-       
-       rzp= NULL; //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;
+       for(rl= rr->layers.first, rlp= rrpart->layers.first; rl && rlp; rl= rl->next, rlp= rlp->next) {
                
-               //              rz= re->rectz+ (pa->miny + rrpart->crop)*rr->rectx+ (pa->minx+rrpart->crop);
-               rf= rl->rectf+ ( (rrpart->tilerect.ymin + rrpart->crop)*rr->rectx + (rrpart->tilerect.xmin+rrpart->crop) )*4;
-       }
-       else {
-               //              rz= re->rectz +  (pa->disprect.ymin*rr->rectx + pa->disprect.xmin);
-               rf= rl->rectf+ (rrpart->tilerect.ymin*rr->rectx + rrpart->tilerect.xmin)*4;
-       }
+               /* 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;
+                       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;
+                               }
+                       }
                }
        }
 }
@@ -278,22 +306,25 @@ RenderResult *RE_GetResult(Render *re)
 void RE_GetResultImage(Render *re, RenderResult *rr)
 {
        memset(rr, sizeof(RenderResult), 0);
-       
+
        if(re && re->result) {
                RenderLayer *rl;
                
                rr->rectx= re->result->rectx;
                rr->recty= re->result->recty;
+               
                rr->rectf= re->result->rectf;
                rr->rectz= re->result->rectz;
                rr->rect32= re->result->rect32;
                
-               /* will become 'active' call */
-               rl= re->result->layers.first;
-               if(rr->rectf==NULL)
-                       rr->rectf= rl->rectf;
-               if(rr->rectz==NULL)
-                       rr->rectz= rl->rectz;   
+               /* active layer */
+               rl= BLI_findlink(&re->result->layers, re->r.actlay);
+               if(rl) {
+                       if(rr->rectf==NULL)
+                               rr->rectf= rl->rectf;
+                       if(rr->rectz==NULL)
+                               rr->rectz= rl->rectz;   
+               }
        }
 }
 
index b226346ede9b6c3b3eca125b637ce3446f03c79d..87c1330d5ef3cca62494562ece54744a52b3913c 100644 (file)
@@ -471,7 +471,7 @@ static void halo_pixelstruct(HaloRen *har, float *rb, float dist, float xn, floa
        
 }
 
-static void halo_tile(RenderPart *pa, float *pass)
+static void halo_tile(RenderPart *pa, float *pass, unsigned int lay)
 {
        HaloRen *har = NULL;
        rcti disprect= pa->disprect;
@@ -488,8 +488,9 @@ static void halo_tile(RenderPart *pa, float *pass)
                }
                else har++;
 
-               /* clip halo with y */
-               if(disprect.ymin > har->maxy);
+               /* layer test, clip halo with y */
+               if((har->lay & lay)==0);
+               else if(disprect.ymin > har->maxy);
                else if(disprect.ymax < har->miny);
                else {
                        
@@ -2646,6 +2647,7 @@ static void freeps(ListBase *lb)
                        RE_freeN(psm->ps);
                RE_freeN(psm);
        }
+       lb->first= lb->last= NULL;
 }
 
 static void addps(ListBase *lb, long *rd, int facenr, int z, unsigned short mask)
@@ -2704,53 +2706,77 @@ static void make_pixelstructs(RenderPart *pa, ListBase *lb)
 /* supposed to be fully threadable! */
 void zbufshadeDA_tile(RenderPart *pa)
 {
-       RenderLayer *rl= pa->result->layers.first;
+       RenderLayer *rl;
        ListBase psmlist= {NULL, NULL};
        float *acolrect= NULL, *edgerect= NULL;
        
        set_part_zbuf_clipflag(pa);
        
        /* allocate the necessary buffers */
-       pa->rectdaps= RE_callocN(sizeof(long)*pa->rectx*pa->recty+4, "zbufDArectd");
                                /* zbuffer inits these rects */
        pa->rectp= RE_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectp");
        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");
        
-       /* initialize pixelstructs */
-       addpsmain(&psmlist);
-       
-       for(pa->sample=0; pa->sample<R.osa; pa->sample++) {
-               zbuffer_solid(pa);
-               make_pixelstructs(pa, &psmlist);
+       for(rl= pa->result->layers.first; rl; rl= rl->next) {
+
+               /* initialize pixelstructs */
+               addpsmain(&psmlist);
+               pa->rectdaps= RE_callocN(sizeof(long)*pa->rectx*pa->recty+4, "zbufDArectd");
                
-               if(R.r.mode & R_EDGE) edge_enhance_calc(pa, edgerect);
-               if(R.test_break()) break; 
-       }
-       
-       /* we do transp layer first, so its get added with filter in main buffer... still incorrect though */
-       if(R.flag & R_ZTRA) {
-               acolrect= RE_callocN(4*sizeof(float)*pa->rectx*pa->recty, "alpha layer");
-               zbuffer_transp_shade(pa, acolrect);
-       }
+               if(rl->layflag & SCE_LAY_SOLID) {
+                       for(pa->sample=0; pa->sample<R.osa; pa->sample++) {
+                               zbuffer_solid(pa, rl->lay, rl->layflag);
+                               make_pixelstructs(pa, &psmlist);
+                               
+                               if(R.r.mode & R_EDGE) edge_enhance_calc(pa, edgerect);
+                               if(R.test_break()) break; 
+                       }
+               }
+               else    /* need to clear rectz for next passes */
+                       fillrect(pa->rectz, pa->rectx, pa->recty, 0x7FFFFFFF);
 
-       /* shades solid and adds transparent layer */
-       shadeDA_tile(pa, rl->rectf, acolrect);
-       
-       /* extra layers */
-       if(R.r.mode & R_EDGE) 
-               edge_enhance_add(pa, rl->rectf, edgerect);
-       if(R.flag & R_HALO)
-               halo_tile(pa, rl->rectf);
+               
+               /* we do transp layer first, so its get added with filter in main buffer... still incorrect though */
+               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);
+                       }
+               }
+
+               /* 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) 
+                       edge_enhance_add(pa, rl->rectf, edgerect);
+               if(R.flag & R_HALO)
+                       if(rl->layflag & SCE_LAY_HALO)
+                               halo_tile(pa, rl->rectf, rl->lay);
+               
+               if(rl->passflag & SCE_PASS_Z)
+                       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);
+       }
        
        /* free all */
        RE_freeN(pa->rectp); pa->rectp= NULL;
        RE_freeN(pa->rectz); pa->rectz= NULL;
-       RE_freeN(pa->rectdaps); pa->rectdaps= NULL;
-       if(acolrect) RE_freeN(acolrect);
+       
        if(edgerect) RE_freeN(edgerect);
        
-       freeps(&psmlist);
 
 }
 
@@ -2760,43 +2786,53 @@ void zbufshadeDA_tile(RenderPart *pa)
 /* supposed to be fully threadable! */
 void zbufshade_tile(RenderPart *pa)
 {
-       RenderLayer *rl= pa->result->layers.first;
-       float *fcol;
-       int x, y, *rp, *rz;
+       RenderLayer *rl;
        
        set_part_zbuf_clipflag(pa);
        
        /* zbuffer code clears/inits rects */
-       rp= pa->rectp= RE_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectp");
-       rz= pa->rectz= RE_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectz");
-       
-       zbuffer_solid(pa);
+       pa->rectp= RE_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectp");
+       pa->rectz= RE_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectz");
        
-       if(!R.test_break()) {
-               fcol= rl->rectf;
-               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);
+       for(rl= pa->result->layers.first; rl; rl= rl->next) {
+               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);
+                                       }
+                                       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)
-                       zbuffer_transp_shade(pa, rl->rectf);
-       
-       if(!R.test_break()) {
-               if(R.r.mode & R_EDGE) {
-                       fillrect(pa->rectp, pa->rectx, pa->recty, 0);
-                       edge_enhance_calc(pa, (float *)pa->rectp);
-                       edge_enhance_add(pa, rl->rectf, (float *)pa->rectp);
+               
+               if(!R.test_break())
+                       if(R.flag & R_ZTRA)
+                               if(rl->layflag & SCE_LAY_ZTRA)
+                                       zbuffer_transp_shade(pa, rl->rectf, rl->lay, rl->layflag);
+               
+               if(!R.test_break()) {
+                       if(R.r.mode & R_EDGE) {
+                               fillrect(pa->rectp, pa->rectx, pa->recty, 0);
+                               edge_enhance_calc(pa, (float *)pa->rectp);
+                               edge_enhance_add(pa, rl->rectf, (float *)pa->rectp);
+                       }
                }
+               
+               if(!R.test_break())
+                       if(R.flag & R_HALO)
+                               if(rl->layflag & SCE_LAY_HALO)
+                                       halo_tile(pa, rl->rectf, rl->lay);
+               
+               if(rl->passflag & SCE_PASS_Z)
+                       convert_zbuf_to_distbuf(pa, rl);
+
        }
-       
-       if(!R.test_break())
-               if(R.flag & R_HALO)
-                       halo_tile(pa, rl->rectf);
 
        RE_freeN(pa->rectp); pa->rectp= NULL;
        RE_freeN(pa->rectz); pa->rectz= NULL;
index 6fe31075847e703a0924dd63e190d608b2626bc8..3be859019edc95a1ebbf972b8455a5f93257ce67 100644 (file)
@@ -1592,7 +1592,7 @@ void set_part_zbuf_clipflag(RenderPart *pa)
        }
 }
 
-void zbuffer_solid(RenderPart *pa)
+void zbuffer_solid(RenderPart *pa, unsigned int lay, short layflag)
 {
        ZSpan zspan;
        VlakRen *vlr= NULL;
@@ -1633,7 +1633,7 @@ void zbuffer_solid(RenderPart *pa)
                if((v & 255)==0) vlr= R.blovl[v>>8];
                else vlr++;
                
-               if(vlr->flag & R_VISIBLE) {
+               if((vlr->flag & R_VISIBLE) && (vlr->lay & lay)) {
                        if(vlr->mat!=ma) {
                                ma= vlr->mat;
                                transp= ma->mode & MA_ZTRA;
@@ -1906,7 +1906,7 @@ static void copyto_abufz(RenderPart *pa, int *arectz, int sample)
  * Do accumulation z buffering.
  */
 
-static void zbuffer_abuf(RenderPart *pa, APixstr *APixbuf, ListBase *apsmbase)
+static void zbuffer_abuf(RenderPart *pa, APixstr *APixbuf, ListBase *apsmbase, unsigned int lay, short layflag)
 {
        ZSpan zspan;
        Material *ma=0;
@@ -1952,7 +1952,7 @@ static void zbuffer_abuf(RenderPart *pa, APixstr *APixbuf, ListBase *apsmbase)
                        
                        ma= vlr->mat;
                        if(ma->mode & (MA_ZTRA)) {
-                               if(vlr->flag & R_VISIBLE) {
+                               if((vlr->flag & R_VISIBLE) && (vlr->lay & lay)) {
                                        unsigned short partclip;
                                        
                                        /* partclipping doesn't need viewplane clipping */
@@ -2075,7 +2075,7 @@ static int addtosampcol(float *sampcol, float *fcol, int mask)
 #define MAX_ZROW       1000
 /* main render call to fill in pass the full transparent layer */
 
-void zbuffer_transp_shade(RenderPart *pa, float *pass)
+void zbuffer_transp_shade(RenderPart *pa, float *pass, unsigned int lay, short layflag)
 {
        APixstr *APixbuf;      /* Zbuffer: linked list of face samples */
        APixstr *ap, *apn;
@@ -2106,7 +2106,7 @@ void zbuffer_transp_shade(RenderPart *pa, float *pass)
        }
        
        /* fill the Apixbuf */
-       zbuffer_abuf(pa, APixbuf, &apsmbase);
+       zbuffer_abuf(pa, APixbuf, &apsmbase, lay, layflag);
        
        /* render tile */
        ap= APixbuf;
@@ -2229,6 +2229,39 @@ void zbuffer_transp_shade(RenderPart *pa, float *pass)
 
 }
 
+/* *************** */
+
+/* uses part zbuffer values to convert into distances from camera in renderlayer */
+void convert_zbuf_to_distbuf(RenderPart *pa, RenderLayer *rl)
+{
+       float *rectzf, zco;
+       int a, *rectz, ortho= R.r.mode & R_ORTHO;
+       
+       if(pa->rectz==NULL) return;
+       if(rl->rectz==NULL) {
+               printf("called convert zbuf wrong...\n");
+               return;
+       }
+       rectzf= rl->rectz;
+       rectz= pa->rectz;
+       
+       for(a=pa->rectx*pa->recty; a>0; a--, rectz++, rectzf++) {
+               if(*rectz==0x7FFFFFFF)
+                       *rectzf= 10e10;
+               else {
+                       /* inverse of zbuf calc: zbuf = MAXZ*hoco_z/hoco_w */
+                       /* or: (R.winmat[3][2] - zco*R.winmat[3][3])/(R.winmat[2][2] - R.winmat[2][3]*zco); */
+                       /* if ortho [2][3] is zero, else [3][3] is zero */
+                       
+                       zco= ((float)*rectz)/2147483647.0f;
+                       if(ortho)
+                               *rectzf= (R.winmat[3][2] - zco*R.winmat[3][3])/(R.winmat[2][2]);
+                       else
+                               *rectzf= (R.winmat[3][2])/(R.winmat[2][2] - R.winmat[2][3]*zco);
+               }
+       }
+}
+
 
 /* end of zbuf.c */
 
index 83647424e3d2085f5e3c8d1cea0c779fe7e89392..63acf6399139e0decff07913e528fed2d3c1a6a1 100644 (file)
@@ -36,6 +36,7 @@
 #include <string.h>
 
 #include "MEM_guardedalloc.h"
+#include "DNA_node_types.h"
 #include "DNA_screen_types.h"
 #include "DNA_space_types.h"
 #include "DNA_scene_types.h"
@@ -45,7 +46,9 @@
 
 #include "BKE_global.h"
 #include "BKE_main.h"
+#include "BKE_node.h"
 #include "BKE_library.h"
+#include "BKE_scene.h"
 #include "BKE_sound.h"
 #include "BKE_packedFile.h"
 #include "BKE_utildefines.h"
@@ -816,6 +819,13 @@ void do_render_panels(unsigned short event)
                G.scene->r.mode &= ~R_EDGE;
                allqueue(REDRAWBUTSSCENE, 0);
                break;
+       case B_ADD_RENDERLAYER:
+               if(G.scene->r.actlay==32767) {
+                       scene_add_render_layer(G.scene);
+                       G.scene->r.actlay= BLI_countlist(&G.scene->r.layers) - 1;
+               }
+               allqueue(REDRAWBUTSSCENE, 0);
+               allqueue(REDRAWNODE, 0);
        }
 }
 
@@ -1475,12 +1485,152 @@ static void render_panel_sfx(void)
 }
 #endif
 
+static void layer_copy_func(void *lay_v, void *lay_p)
+{
+       unsigned int *lay= lay_p;
+       int laybit= (int)lay_v;
+
+       if(G.qual & LR_SHIFTKEY) {
+               if(*lay==0) *lay= 1<<laybit;
+       }
+       else
+               *lay= 1<<laybit;
+       
+       copy_view3d_lock(REDRAW);
+       allqueue(REDRAWBUTSSCENE, 0);
+}
+
+static void delete_scene_layer_func(void *srl_v, void *unused1)
+{
+       if(BLI_countlist(&G.scene->r.layers)>1) {
+               BLI_remlink(&G.scene->r.layers, srl_v);
+               MEM_freeN(srl_v);
+               G.scene->r.actlay= 0;
+               
+               allqueue(REDRAWBUTSSCENE, 0);
+               allqueue(REDRAWNODE, 0);
+       }
+}
+
+static void rename_scene_layer_func(void *srl_v, void *unused_v)
+{
+       if(G.scene->nodetree) {
+               SceneRenderLayer *srl= srl_v;
+               bNode *node;
+               for(node= G.scene->nodetree->nodes.first; node; node= node->next) {
+                       if(node->type==CMP_NODE_R_RESULT) {
+                               if(node->custom1==G.scene->r.actlay)
+                                       BLI_strncpy(node->name, srl->name, NODE_MAXSTR);
+                       }
+               }
+       }
+       allqueue(REDRAWNODE, 0);
+}
+
+static char *scene_layer_menu(void)
+{
+       SceneRenderLayer *srl;
+       int len= 32 + 32*BLI_countlist(&G.scene->r.layers);
+       short a, nr;
+       char *str= MEM_callocN(len, "menu layers");
+       
+       strcpy(str, "ADD NEW %x32767");
+       a= strlen(str);
+       for(nr=0, srl= G.scene->r.layers.first; srl; srl= srl->next, nr++) {
+               a+= sprintf(str+a, "|%s %%x%d", srl->name, nr);
+       }
+       
+       return str;
+}
+
+static void draw_3d_layer_buttons(uiBlock *block, unsigned int *poin, short xco, short yco, short dx, short dy, int event)
+{
+       uiBut *bt;
+       long a;
+       
+       uiBlockBeginAlign(block);
+       for(a=0; a<5; a++) {
+               bt= uiDefButBitI(block, TOG, 1<<a, B_NOP, "",   (short)(xco+a*(dx/2)), yco+dy/2, (short)(dx/2), (short)(dy/2), poin, 0, 0, 0, 0, "");
+               uiButSetFunc(bt, layer_copy_func, (void *)a, poin);
+       }
+       for(a=0; a<5; a++) {
+               bt=uiDefButBitI(block, TOG, 1<<(a+10), B_NOP, "",       (short)(xco+a*(dx/2)), yco, (short)(dx/2), (short)(dy/2), poin, 0, 0, 0, 0, "");
+               uiButSetFunc(bt, layer_copy_func, (void *)(a+10), poin);
+       }
+       
+       xco+= 7;
+       uiBlockBeginAlign(block);
+       for(a=5; a<10; a++) {
+               bt=uiDefButBitI(block, TOG, 1<<a, B_NOP, "",    (short)(xco+a*(dx/2)), yco+dy/2, (short)(dx/2), (short)(dy/2), poin, 0, 0, 0, 0, "");
+               uiButSetFunc(bt, layer_copy_func, (void *)a, poin);
+       }
+       for(a=5; a<10; a++) {
+               bt=uiDefButBitI(block, TOG, 1<<(a+10), B_NOP, "",       (short)(xco+a*(dx/2)), yco, (short)(dx/2), (short)(dy/2), poin, 0, 0, 0, 0, "");
+               uiButSetFunc(bt, layer_copy_func, (void *)(a+10), poin);
+       }
+       
+       uiBlockEndAlign(block);
+}
+
+static void render_panel_layers(void)
+{
+       uiBlock *block;
+       uiBut *bt;
+       SceneRenderLayer *srl= BLI_findlink(&G.scene->r.layers, G.scene->r.actlay);
+       char *strp;
+       
+       block= uiNewBlock(&curarea->uiblocks, "render_panel_layers", UI_EMBOSS, UI_HELV, curarea->win);
+       uiNewPanelTabbed("Output", "Render");
+       if(uiNewPanel(curarea, block, "Render Layers", "Render", 320, 0, 318, 204)==0) return;
+       
+       /* first, as reminder, the scene layers */
+       uiDefBut(block, LABEL, 0, "Scene:",                             10,170,100,20, NULL, 0, 0, 0, 0, "");
+       
+       draw_3d_layer_buttons(block, &G.scene->lay, 130, 170, 35, 30, B_LAY);
+       
+       /* layer menu, name, delete button */
+       uiBlockBeginAlign(block);
+       strp= scene_layer_menu();
+       uiDefButS(block, MENU, B_ADD_RENDERLAYER, strp, 10,130,23,20, &(G.scene->r.actlay), 0, 0, 0, 0, "Choose Active Render Layer");
+       MEM_freeN(strp);
+       
+       bt= uiDefBut(block, TEX, REDRAWNODE, "",  33,130,252,20, srl->name, 0.0, 31.0, 0, 0, "");
+       uiButSetFunc(bt, rename_scene_layer_func, srl, NULL);
+       bt=uiDefIconBut(block, BUT, B_NOP, ICON_X,      285, 130, 25, 20, 0, 0, 0, 0, 0, "Deletes current Render Layer");
+       uiButSetFunc(bt, delete_scene_layer_func, srl, NULL);
+       uiBlockEndAlign(block);
+
+       /* RenderLayer visible-layers */
+       uiDefBut(block, LABEL, 0, "Layer:",     10,95,100,20, NULL, 0, 0, 0, 0, "");
+       draw_3d_layer_buttons(block, &srl->lay,         130, 95, 35, 30, B_NOP);
+       
+       uiBlockBeginAlign(block);
+       uiDefButBitS(block, TOG, SCE_LAY_SOLID, B_NOP,"Solid",  10, 70, 75, 20, &srl->layflag, 0, 0, 0, 0, "Render Solid faces in this Layer"); 
+       uiDefButBitS(block, TOG, SCE_LAY_ZTRA, B_NOP,"Ztra",    85, 70, 75, 20, &srl->layflag, 0, 0, 0, 0, "Render Z-Transparent faces in this Layer"); 
+       uiDefButBitS(block, TOG, SCE_LAY_HALO, B_NOP,"Halo",    160, 70, 75, 20, &srl->layflag, 0, 0, 0, 0, "Render Halos in this Layer");      
+       uiDefButBitS(block, TOG, SCE_LAY_STRAND, B_NOP,"Strand",        235, 70, 75, 20, &srl->layflag, 0, 0, 0, 0, "Render Particle Strands in this Layer");   
+       uiBlockEndAlign(block);
+
+       uiDefBut(block, LABEL, 0, "Passes:",                                    10,30,150,20, NULL, 0, 0, 0, 0, "");
+       uiBlockBeginAlign(block);
+       uiDefButBitS(block, TOG, SCE_PASS_COMBINED, B_NOP,"Combined",   130, 30, 155, 20, &srl->passflag, 0, 0, 0, 0, "Deliver full combined RGBA buffer");     
+       uiDefButBitS(block, TOG, SCE_PASS_Z, B_NOP,"Z",                 285, 30, 25, 20, &srl->passflag, 0, 0, 0, 0, "Deliver Z values pass");  
+       
+       uiDefButBitS(block, TOG, SCE_PASS_DIFFUSE, B_NOP,"Diff",10, 10, 45, 20, &srl->passflag, 0, 0, 0, 0, "Deliver Diffuse pass");    
+       uiDefButBitS(block, TOG, SCE_PASS_SPEC, B_NOP,"Spec",   55, 10, 45, 20, &srl->passflag, 0, 0, 0, 0, "Deliver Diffuse pass");    
+       uiDefButBitS(block, TOG, SCE_PASS_SHADOW, B_NOP,"Shad", 100, 10, 45, 20, &srl->passflag, 0, 0, 0, 0, "Deliver Diffuse pass");   
+       uiDefButBitS(block, TOG, SCE_PASS_AO, B_NOP,"AO",               145, 10, 40, 20, &srl->passflag, 0, 0, 0, 0, "Deliver Diffuse pass");   
+       uiDefButBitS(block, TOG, SCE_PASS_MIRROR, B_NOP,"Mirr", 185, 10, 45, 20, &srl->passflag, 0, 0, 0, 0, "Deliver Diffuse pass");   
+       uiDefButBitS(block, TOG, SCE_PASS_NORMAL, B_NOP,"Nor",  230, 10, 40, 20, &srl->passflag, 0, 0, 0, 0, "Deliver Diffuse pass");   
+       uiDefButBitS(block, TOG, SCE_PASS_VECTOR, B_NOP,"Vec",  270, 10, 40, 20, &srl->passflag, 0, 0, 0, 0, "Deliver Diffuse pass");   
+}      
 
 void render_panels()
 {
 
        render_panel_output();
 //     render_panel_sfx();
+       render_panel_layers();
        render_panel_render();
        render_panel_anim();
        render_panel_format();
index e764b08ee6c0cc0db8fb08824ef1615dbef48195..467bc2fa60feb730a10438481f3a6b4ad0eb36c1 100644 (file)
 
 #include "BMF_Api.h"
 
+#include "MEM_guardedalloc.h"
+
+#include "RE_pipeline.h"
+
 #include "blendef.h"
 #include "butspace.h"
 #include "interface.h" /* urm...  for rasterpos_safe, roundbox */
 #include "mydevice.h"
 
-#include "MEM_guardedalloc.h"
+
 
 static void snode_drawstring(SpaceNode *snode, char *str, int okwidth)
 {
@@ -659,6 +663,39 @@ static int node_composit_buts_image(uiBlock *block, bNodeTree *ntree, bNode *nod
                return 19;
 }
 
+static char *scene_layer_menu(void)
+{
+       SceneRenderLayer *srl;
+       int len= 32 + 32*BLI_countlist(&G.scene->r.layers);
+       short a, nr;
+       char *str= MEM_callocN(len, "menu layers");
+       
+       strcpy(str, "Active Layer %t");
+       a= strlen(str);
+       for(nr=0, srl= G.scene->r.layers.first; srl; srl= srl->next, nr++) {
+               a+= sprintf(str+a, "|%s %%x%d", srl->name, nr);
+       }
+       
+       return str;
+}
+
+
+static int node_composit_buts_renderresult(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+       if(block) {
+               uiBut *bt;
+               char *strp;
+               
+               strp= scene_layer_menu();
+               bt= uiDefButS(block, MENU, B_NODE_EXEC, strp, 
+                                 butr->xmin, butr->ymin, (butr->xmax-butr->xmin), 19, 
+                                 &node->custom1, 0, 0, 0, 0, "Choose Render Layer");
+               uiButSetFunc(bt, node_but_title_cb, node, bt);
+               MEM_freeN(strp);
+       }
+       return 19;
+}
+
 static int node_composit_buts_blur(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
 {
        if(block) {
@@ -689,6 +726,29 @@ static int node_composit_buts_filter(uiBlock *block, bNodeTree *ntree, bNode *no
        return 20;
 }
 
+static int node_composit_buts_map_value(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+       if(block) {
+               TexMapping *texmap= node->storage;
+               short xstart= (short)butr->xmin;
+               short dy= (short)(butr->ymax-19.0f);
+               short dx= (short)(butr->xmax-butr->xmin)/2;
+               
+               uiBlockBeginAlign(block);
+               uiDefButF(block, NUM, B_NODE_EXEC, "Offs:", xstart, dy, 2*dx, 19, texmap->loc, -1000.0f, 1000.0f, 10, 2, "");
+               dy-= 19;
+               uiDefButF(block, NUM, B_NODE_EXEC, "Size:", xstart, dy, 2*dx, 19, texmap->size, -1000.0f, 1000.0f, 10, 3, "");
+               dy-= 23;
+               uiBlockBeginAlign(block);
+               uiDefButBitI(block, TOG, TEXMAP_CLIP_MIN, B_NODE_EXEC, "Min", xstart, dy, dx, 19, &texmap->flag, 0.0f, 0.0f, 0, 0, "");
+               uiDefButF(block, NUM, B_NODE_EXEC, "", xstart+dx, dy, dx, 19, texmap->min, -1000.0f, 1000.0f, 10, 2, "");
+               dy-= 19;
+               uiDefButBitI(block, TOG, TEXMAP_CLIP_MIN, B_NODE_EXEC, "Max", xstart, dy, dx, 19, &texmap->flag, 0.0f, 0.0f, 0, 0, "");
+               uiDefButF(block, NUM, B_NODE_EXEC, "", xstart+dx, dy, dx, 19, texmap->min, -1000.0f, 1000.0f, 10, 2, "");
+       }
+       return 80;
+}
+
 
 /* only once called */
 static void node_composit_set_butfunc(bNodeType *ntype)
@@ -700,6 +760,9 @@ static void node_composit_set_butfunc(bNodeType *ntype)
                case CMP_NODE_IMAGE:
                        ntype->butfunc= node_composit_buts_image;
                        break;
+               case CMP_NODE_R_RESULT:
+                       ntype->butfunc= node_composit_buts_renderresult;
+                       break;
                case CMP_NODE_NORMAL:
                        ntype->butfunc= node_buts_normal;
                        break;
@@ -727,6 +790,9 @@ static void node_composit_set_butfunc(bNodeType *ntype)
                case CMP_NODE_FILTER:
                        ntype->butfunc= node_composit_buts_filter;
                        break;
+               case CMP_NODE_MAP_VALUE:
+                       ntype->butfunc= node_composit_buts_map_value;
+                       break;
                default:
                        ntype->butfunc= NULL;
        }
@@ -986,15 +1052,27 @@ static void node_update(bNode *node)
        
        /* preview rect? */
        if(node->flag & NODE_PREVIEW) {
-               float aspect= 1.0f;
-               
-               if(node->preview && node->preview->xsize && node->preview->ysize) 
-                       aspect= (float)node->preview->ysize/(float)node->preview->xsize;
-               
-               dy-= NODE_DYS/2;
-               node->prvr.ymax= dy;
-               node->prvr.ymin= dy - aspect*(node->width-NODE_DY);
-               dy= node->prvr.ymin - NODE_DYS/2;
+               /* only recalculate size when there's a preview actually, otherwise we use stored result */
+               if(node->preview && node->preview->rect) {
+                       float aspect= 1.0f;
+                       
+                       if(node->preview && node->preview->xsize && node->preview->ysize) 
+                               aspect= (float)node->preview->ysize/(float)node->preview->xsize;
+                       
+                       dy-= NODE_DYS/2;
+                       node->prvr.ymax= dy;
+                       node->prvr.ymin= dy - aspect*(node->width-NODE_DY);
+                       dy= node->prvr.ymin - NODE_DYS/2;
+               }
+               else {
+                       float oldh= node->prvr.ymax - node->prvr.ymin;
+                       if(oldh==0.0f)
+                               oldh= node->width-NODE_DY;
+                       dy-= NODE_DYS/2;
+                       node->prvr.ymax= dy;
+                       node->prvr.ymin= dy - oldh;
+                       dy= node->prvr.ymin - NODE_DYS/2;
+               }
        }
        
        /* buttons rect? */
index fc0aed7728a091aac9fcd32519dcd3e98c0f39b3..8a90d31be578dbe31f24442e5e5314f796822525 100644 (file)
@@ -203,10 +203,6 @@ static void composit_node_event(SpaceNode *snode, short event)
                                strcpy(name, ((Image *)node->id)->name);
                        else strcpy(name, U.textudir);
                        
-                       /* node->block pointers are stored, but filesel frees it, so we need to clear them */
-                       for(node= snode->edittree->nodes.first; node; node= node->next)
-                               node->block= NULL;
-                       
                        activate_fileselect(FILE_SPECIAL, "SELECT IMAGE", name, load_node_image);
                }
        }
@@ -338,6 +334,34 @@ static void node_set_active(SpaceNode *snode, bNode *node)
                        
                        allqueue(REDRAWBUTSSHADING, 1);
                }
+               else if(snode->treetype==NTREE_COMPOSIT) {
+                       /* make active viewer, currently only 1 supported... */
+                       if(node->type==CMP_NODE_VIEWER) {
+                               bNode *tnode;
+                               int was_output= node->flag & NODE_DO_OUTPUT;
+
+                               for(tnode= snode->edittree->nodes.first; tnode; tnode= tnode->next)
+                                       if(tnode->type==CMP_NODE_VIEWER)
+                                               tnode->flag &= ~NODE_DO_OUTPUT;
+                               
+                               node->flag |= NODE_DO_OUTPUT;
+                               if(was_output==0) snode_handle_recalc(snode);
+                               
+                               /* add node doesnt link this yet... */
+                               if(node->id==NULL) {
+                                       node->id= find_id("IM", "Compositor");
+                                       if(node->id==NULL) {
+                                               Image *ima= alloc_libblock(&G.main->image, ID_IM, "Compositor");
+                                               strcpy(ima->name, "Compositor");
+                                               ima->ok= 1;
+                                               ima->xrep= ima->yrep= 1;
+                                               node->id= &ima->id;
+                                       }
+                                       else 
+                                               node->id->us++;
+                               }
+                       }
+               }
        }
 }
 
@@ -1134,7 +1158,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|Normal %x207");
+               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");
                if(event<1) return;
        }
        else return;
@@ -1480,6 +1504,19 @@ void node_make_group(SpaceNode *snode)
                return;
        }
        
+       /* for time being... is too complex to handle */
+       if(snode->treetype==NTREE_COMPOSIT) {
+               for(gnode=snode->nodetree->nodes.first; gnode; gnode= gnode->next) {
+                       if(gnode->flag & SELECT)
+                               if(gnode->type==CMP_NODE_R_RESULT)
+                                       break;
+               }
+               if(gnode) {
+                       error("Can not add RenderResult in a Group");
+                       return;
+               }
+       }
+       
        gnode= nodeMakeGroupFromSelected(snode->nodetree);
        if(gnode==NULL) {
                error("Can not make Group");
@@ -1496,7 +1533,7 @@ void node_make_group(SpaceNode *snode)
 
 /* special version to prevent overlapping buttons, has a bit of hack... */
 /* yes, check for example composit_node_event(), file window use... */
-int node_uiDoBlocks(SpaceNode *snode, ListBase *lb, short event)
+static int node_uiDoBlocks(SpaceNode *snode, ListBase *lb, short event)
 {
        bNode *node;
        rctf rect;
@@ -1507,6 +1544,11 @@ int node_uiDoBlocks(SpaceNode *snode, ListBase *lb, short event)
        
        getmouseco_areawin(mval);
        areamouseco_to_ipoco(G.v2d, mval, &rect.xmin, &rect.ymin);
+
+       /* this happens after filesel usage... */
+       if(lb->first==NULL) {
+               return UI_NOTHING;
+       }
        
        rect.xmin -= 2.0f;
        rect.ymin -= 2.0f;
index 4ad9b559b2e83aec609085cd59daae7bb6fdb9dd..ce8d21612bd836c9057fe456e0cb9130a2a9b230 100644 (file)
@@ -316,6 +316,7 @@ Scene *copy_scene(Scene *sce, int level)
        scen->toolsettings= MEM_dupallocN(sce->toolsettings);
 
        duplicatelist(&(scen->markers), &(sce->markers));
+       duplicatelist(&(scen->r.layers), &(sce->r.layers));
        
        scen->nodetree= ntreeCopyTree(sce->nodetree, 0);
        
index 043128673aa8d940e59ce4d3a7b213c2f045a44e..0109d0d146c03ab2b84baa9155fe619386a55800 100644 (file)
@@ -650,6 +650,7 @@ void BIF_view3d_previewrender(ScrArea *sa)
                /* no osa, blur, seq, for preview render */
                rdata= G.scene->r;
                rdata.mode &= ~(R_OSA|R_MBLUR|R_DOSEQ);
+               rdata.layers.first= rdata.layers.last= NULL;
        
                RE_InitState(re, &rdata, sa->winx, sa->winy, &ri->disprect);
        
index 493621269e64ec9d412b163ca05566f71f46fae2..4b5b7ceedf76fc2f95ca9fb865520688cea8ee32 100644 (file)
@@ -287,46 +287,46 @@ static void renderwin_draw_render_info(RenderWin *rw)
 
 static void renderwin_draw(RenderWin *rw, int just_clear)
 {
-       RenderResult rres;
+       float fullrect[2][2];
+       int set_back_mainwindow;
+       rcti rect;
+
+       /* since renderwin uses callbacks (controlled by ghost) it can
+               mess up active window output with redraw events after a render. 
+               this is patchy, still WIP */
+       set_back_mainwindow = (winlay_get_active_window() != rw->win);
+       window_make_active(rw->win);
        
-       RE_GetResultImage(RE_GetRender("Render"), &rres);
-
-       if(rres.rectf) {
-               float fullrect[2][2];
-               int set_back_mainwindow;
-               rcti rect;
-
-               /* since renderwin uses callbacks (controlled by ghost) it can
-                       mess up active window output with redraw events after a render. 
-                       this is patchy, still WIP */
-               set_back_mainwindow = (winlay_get_active_window() != rw->win);
-               window_make_active(rw->win);
-               
-               rect.xmin= rect.ymin= 0;
-               window_get_size(rw->win, &rect.xmax, &rect.ymax);
-               rect.ymax-= RW_HEADERY;
-               
-               renderwin_get_fullrect(rw, fullrect);
-               
-               /* do this first, so window ends with correct scissor */
-               renderwin_draw_render_info(rw);
-               
-               glEnable(GL_SCISSOR_TEST);
-               glaDefine2DArea(&rect);
+       rect.xmin= rect.ymin= 0;
+       window_get_size(rw->win, &rect.xmax, &rect.ymax);
+       rect.ymax-= RW_HEADERY;
+       
+       renderwin_get_fullrect(rw, fullrect);
+       
+       /* do this first, so window ends with correct scissor */
+       renderwin_draw_render_info(rw);
+       
+       glEnable(GL_SCISSOR_TEST);
+       glaDefine2DArea(&rect);
+       
+       glClearColor(.1875, .1875, .1875, 1.0); 
+       glClear(GL_COLOR_BUFFER_BIT);
+
+       if (just_clear) {
+               glColor3ub(0, 0, 0);
+               glRectfv(fullrect[0], fullrect[1]);
+       } else {
+               RenderResult rres;
                
-               glClearColor(.1875, .1875, .1875, 1.0); 
-               glClear(GL_COLOR_BUFFER_BIT);
-
-               if (just_clear) {
-                       glColor3ub(0, 0, 0);
-                       glRectfv(fullrect[0], fullrect[1]);
-               } else {
+               RE_GetResultImage(RE_GetRender("Render"), &rres);
+               if(rres.rectf) {
+                       
                        glPixelZoom(rw->zoom, rw->zoom);
                        if(rw->flags & RW_FLAGS_ALPHA) {
                                /* swap bytes, so alpha is most significant one, then just draw it as luminance int */
-//                             glPixelStorei(GL_UNPACK_SWAP_BYTES, 1);
-//                             glaDrawPixelsSafe(fullrect[0][0], fullrect[0][1], rr->rectx, rr->recty, GL_LUMINANCE, GL_UNSIGNED_INT, R.rectot);
-//                             glPixelStorei(GL_UNPACK_SWAP_BYTES, 0);
+       //                              glPixelStorei(GL_UNPACK_SWAP_BYTES, 1);
+       //                              glaDrawPixelsSafe(fullrect[0][0], fullrect[0][1], rr->rectx, rr->recty, GL_LUMINANCE, GL_UNSIGNED_INT, R.rectot);
+       //                              glPixelStorei(GL_UNPACK_SWAP_BYTES, 0);
                        }
                        else {
                                if(rres.rect32)
@@ -336,25 +336,25 @@ static void renderwin_draw(RenderWin *rw, int just_clear)
                        }
                        glPixelZoom(1.0, 1.0);
                }
-               
-               /* info text is overlayed on bottom */
-               if (rw->info_text) {
-                       float w;
-                       glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
-                       glEnable(GL_BLEND);
-                       w=186.0*strlen(rw->info_text)/30;
-                       glColor4f(.5,.5,.5,.25);
-                       glRectf(0.0,0.0,w,30.0);
-                       glDisable(GL_BLEND);
-                       glColor3ub(255, 255, 255);
-                       glRasterPos2i(10, 10);
-                       BMF_DrawString(G.font, rw->info_text);
-               }
-               
-               window_swap_buffers(rw->win);
-               
-               if (set_back_mainwindow) mainwindow_make_active();      
        }
+       
+       /* info text is overlayed on bottom */
+       if (rw->info_text) {
+               float w;
+               glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+               glEnable(GL_BLEND);
+               w=186.0*strlen(rw->info_text)/30;
+               glColor4f(.5,.5,.5,.25);
+               glRectf(0.0,0.0,w,30.0);
+               glDisable(GL_BLEND);
+               glColor3ub(255, 255, 255);
+               glRasterPos2i(10, 10);
+               BMF_DrawString(G.font, rw->info_text);
+       }
+       
+       window_swap_buffers(rw->win);
+       
+       if (set_back_mainwindow) mainwindow_make_active();      
 }
 
 /* ------ interactivity calls for RenderWin ------------- */
@@ -736,7 +736,7 @@ static void renderwin_progress(RenderWin *rw, RenderResult *rr, rcti *unused)
        if(rr->rectf)
                rectf= rr->rectf;
        else {
-               RenderLayer *rl= rr->layers.first;
+               RenderLayer *rl= BLI_findlink(&rr->layers, rr->actlay);
                rectf= rl->rectf;
        }       
        /* when rendering more pixels than needed, we crop away cruft */