Fix #27120: Bake to image used for rendering glitch (bake feedback loop)
authorSergey Sharybin <sergey.vfx@gmail.com>
Fri, 20 Jan 2012 07:43:46 +0000 (07:43 +0000)
committerSergey Sharybin <sergey.vfx@gmail.com>
Fri, 20 Jan 2012 07:43:46 +0000 (07:43 +0000)
Detect feedback loop and do not bake to images detected in this loop and show
nice warning message in such cases.

It's a way which wouldn't overcomplicate code trying to duplicate images and so
without real benefit.

source/blender/editors/object/object_bake.c
source/blender/makesdna/DNA_image_types.h
source/blender/render/extern/include/RE_shader_ext.h
source/blender/render/intern/source/imagetexture.c
source/blender/render/intern/source/rendercore.c

index 6ec778d7ee923b9c133d7ada95a191e2a839dc35..2fe2e71f2d95457ede8fcdba0f2a318a14785a94 100644 (file)
@@ -1255,7 +1255,7 @@ typedef struct BakeRender {
        Main *main;
        Scene *scene;
        struct Object *actob;
        Main *main;
        Scene *scene;
        struct Object *actob;
-       int tot, ready;
+       int result, ready;
 
        ReportList *reports;
 
 
        ReportList *reports;
 
@@ -1328,7 +1328,7 @@ static void finish_bake_internal(BakeRender *bkr)
                if(bkr->prev_r_raytrace == 0)
                        bkr->scene->r.mode &= ~R_RAYTRACE;
 
                if(bkr->prev_r_raytrace == 0)
                        bkr->scene->r.mode &= ~R_RAYTRACE;
 
-       if(bkr->tot) {
+       if(bkr->result==BAKE_RESULT_OK) {
                Image *ima;
                /* force OpenGL reload and mipmap recalc */
                for(ima= G.main->image.first; ima; ima= ima->id.next) {
                Image *ima;
                /* force OpenGL reload and mipmap recalc */
                for(ima= G.main->image.first; ima; ima= ima->id.next) {
@@ -1355,7 +1355,7 @@ static void *do_bake_render(void *bake_v)
 {
        BakeRender *bkr= bake_v;
 
 {
        BakeRender *bkr= bake_v;
 
-       bkr->tot= RE_bake_shade_all_selected(bkr->re, bkr->scene->r.bake_mode, bkr->actob, NULL, bkr->progress);
+       bkr->result= RE_bake_shade_all_selected(bkr->re, bkr->scene->r.bake_mode, bkr->actob, NULL, bkr->progress);
        bkr->ready= 1;
 
        return NULL;
        bkr->ready= 1;
 
        return NULL;
@@ -1377,7 +1377,7 @@ static void bake_startjob(void *bkv, short *stop, short *do_update, float *progr
        RE_Database_Baking(bkr->re, bmain, scene, scene->lay, scene->r.bake_mode, bkr->actob);
 
        /* baking itself is threaded, cannot use test_break in threads. we also update optional imagewindow */
        RE_Database_Baking(bkr->re, bmain, scene, scene->lay, scene->r.bake_mode, bkr->actob);
 
        /* baking itself is threaded, cannot use test_break in threads. we also update optional imagewindow */
-       bkr->tot= RE_bake_shade_all_selected(bkr->re, scene->r.bake_mode, bkr->actob, bkr->do_update, bkr->progress);
+       bkr->result= RE_bake_shade_all_selected(bkr->re, scene->r.bake_mode, bkr->actob, bkr->do_update, bkr->progress);
 }
 
 static void bake_update(void *bkv)
 }
 
 static void bake_update(void *bkv)
@@ -1396,7 +1396,11 @@ static void bake_freejob(void *bkv)
        BakeRender *bkr= bkv;
        finish_bake_internal(bkr);
 
        BakeRender *bkr= bkv;
        finish_bake_internal(bkr);
 
-       if(bkr->tot==0) BKE_report(bkr->reports, RPT_ERROR, "No objects or images found to bake to");
+       if(bkr->result==BAKE_RESULT_NO_OBJECTS)
+               BKE_report(bkr->reports, RPT_ERROR, "No objects or images found to bake to");
+       else if(bkr->result==BAKE_RESULT_FEEDBACK_LOOP)
+               BKE_report(bkr->reports, RPT_WARNING, "Feedback loop detected");
+
        MEM_freeN(bkr);
        G.rendering = 0;
 }
        MEM_freeN(bkr);
        G.rendering = 0;
 }
@@ -1513,7 +1517,10 @@ static int bake_image_exec(bContext *C, wmOperator *op)
                        }
                        BLI_end_threads(&threads);
 
                        }
                        BLI_end_threads(&threads);
 
-                       if(bkr.tot==0) BKE_report(op->reports, RPT_ERROR, "No valid images found to bake to");
+                       if(bkr.result==BAKE_RESULT_NO_OBJECTS)
+                               BKE_report(op->reports, RPT_ERROR, "No valid images found to bake to");
+                       else if(bkr.result==BAKE_RESULT_FEEDBACK_LOOP)
+                               BKE_report(op->reports, RPT_ERROR, "Feedback loop detected");
 
                        finish_bake_internal(&bkr);
 
 
                        finish_bake_internal(&bkr);
 
index 110ac59edc9f2e5f88ac551b0f0d897ca61d70be..efe6c4d2586285234f7445918e431829340adb0d 100644 (file)
@@ -120,6 +120,7 @@ typedef struct Image {
 #define IMA_DEPRECATED         64
 #define IMA_OLD_PREMUL         128
 #define IMA_CM_PREDIVIDE       256
 #define IMA_DEPRECATED         64
 #define IMA_OLD_PREMUL         128
 #define IMA_CM_PREDIVIDE       256
+#define IMA_USED_FOR_RENDER    512
 
 /* Image.tpageflag */
 #define IMA_TILES                      1
 
 /* Image.tpageflag */
 #define IMA_TILES                      1
index dd0a0f308ce610295ccac89ddd0912affa86274e..2f585f91d4411748da4f6daadb76bd9e03ebbed6 100644 (file)
@@ -210,4 +210,8 @@ int RE_bake_shade_all_selected(struct Render *re, int type, struct Object *actob
 struct Image *RE_bake_shade_get_image(void);
 void RE_bake_ibuf_filter(struct ImBuf *ibuf, char *mask, const int filter);
 
 struct Image *RE_bake_shade_get_image(void);
 void RE_bake_ibuf_filter(struct ImBuf *ibuf, char *mask, const int filter);
 
+#define BAKE_RESULT_OK                 0
+#define BAKE_RESULT_NO_OBJECTS         1
+#define BAKE_RESULT_FEEDBACK_LOOP      2
+
 #endif /* RE_SHADER_EXT_H */
 #endif /* RE_SHADER_EXT_H */
index 0b6e1b8ee01c8e2f1769981e8c4985257c33556b..2d64828b6b35445f5fe5bafecd3f498baf07ef58 100644 (file)
@@ -131,6 +131,8 @@ int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResul
                        return retval;
                
                ibuf= BKE_image_get_ibuf(ima, &tex->iuser);
                        return retval;
                
                ibuf= BKE_image_get_ibuf(ima, &tex->iuser);
+
+               ima->flag|= IMA_USED_FOR_RENDER;
        }
        if(ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL))
                return retval;
        }
        if(ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL))
                return retval;
@@ -1441,6 +1443,8 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const
                        return retval;
                
                ibuf= BKE_image_get_ibuf(ima, &tex->iuser); 
                        return retval;
                
                ibuf= BKE_image_get_ibuf(ima, &tex->iuser); 
+
+               ima->flag|= IMA_USED_FOR_RENDER;
        }
        if(ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL))
                return retval;
        }
        if(ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL))
                return retval;
@@ -1812,6 +1816,8 @@ void image_sample(Image *ima, float fx, float fy, float dx, float dy, float *res
        
        if( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) )
                ibuf->rect-= (ibuf->x*ibuf->y);
        
        if( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) )
                ibuf->rect-= (ibuf->x*ibuf->y);
+
+       ima->flag|= IMA_USED_FOR_RENDER;
 }
 
 void ibuf_sample(ImBuf *ibuf, float fx, float fy, float dx, float dy, float *result)
 }
 
 void ibuf_sample(ImBuf *ibuf, float fx, float fy, float dx, float dy, float *result)
index 773af96671a8b17f61e342aef68715ed0c3b35a2..2d3837acbfabcc28cff89ba1c8a757a28d3821e6 100644 (file)
@@ -2440,6 +2440,11 @@ static int get_next_bake_face(BakeShade *bs)
                                        if(ibuf->rect_float && !(ibuf->channels==0 || ibuf->channels==4))
                                                continue;
                                        
                                        if(ibuf->rect_float && !(ibuf->channels==0 || ibuf->channels==4))
                                                continue;
                                        
+                                       if(ima->flag & IMA_USED_FOR_RENDER) {
+                                               ima->id.flag &= ~LIB_DOIT;
+                                               continue;
+                                       }
+                                       
                                        /* find the image for the first time? */
                                        if(ima->id.flag & LIB_DOIT) {
                                                ima->id.flag &= ~LIB_DOIT;
                                        /* find the image for the first time? */
                                        if(ima->id.flag & LIB_DOIT) {
                                                ima->id.flag &= ~LIB_DOIT;
@@ -2584,7 +2589,7 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_up
        BakeShade *handles;
        ListBase threads;
        Image *ima;
        BakeShade *handles;
        ListBase threads;
        Image *ima;
-       int a, vdone=0, usemask=0;
+       int a, vdone=0, usemask=0, result=BAKE_RESULT_OK;
        
        /* initialize render global */
        R= *re;
        
        /* initialize render global */
        R= *re;
@@ -2601,6 +2606,7 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_up
        for(ima= G.main->image.first; ima; ima= ima->id.next) {
                ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL);
                ima->id.flag |= LIB_DOIT;
        for(ima= G.main->image.first; ima; ima= ima->id.next) {
                ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL);
                ima->id.flag |= LIB_DOIT;
+               ima->flag&= ~IMA_USED_FOR_RENDER;
                if(ibuf) {
                        ibuf->userdata = NULL; /* use for masking if needed */
                        if(ibuf->rect_float)
                if(ibuf) {
                        ibuf->userdata = NULL; /* use for masking if needed */
                        if(ibuf->rect_float)
@@ -2659,6 +2665,9 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_up
                if((ima->id.flag & LIB_DOIT)==0) {
                        ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL);
 
                if((ima->id.flag & LIB_DOIT)==0) {
                        ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL);
 
+                       if(ima->flag & IMA_USED_FOR_RENDER)
+                               result= BAKE_RESULT_FEEDBACK_LOOP;
+
                        if(!ibuf)
                                continue;
 
                        if(!ibuf)
                                continue;
 
@@ -2679,7 +2688,10 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_up
        
        BLI_end_threads(&threads);
 
        
        BLI_end_threads(&threads);
 
-       return vdone;
+       if(vdone==0)
+               result= BAKE_RESULT_NO_OBJECTS;
+
+       return result;
 }
 
 struct Image *RE_bake_shade_get_image(void)
 }
 
 struct Image *RE_bake_shade_get_image(void)