Fix #32598: clamp blender internal alpha channel to 0..1, and RGB to 0..inf,
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Thu, 20 Sep 2012 00:39:27 +0000 (00:39 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Thu, 20 Sep 2012 00:39:27 +0000 (00:39 +0000)
to avoid compositing issues. The values can go out of bounds due to sharp
pixel filters.

In Cycles the alpha channel is already clamped, and there are no pixel filters
that could cause negative RGB values.

source/blender/render/intern/source/pipeline.c
source/blender/render/intern/source/rendercore.c

index e9ff74bd1accc8910c800fa9d629a273a767ed09..4a1674b8bcadb77a4e21a16acdc5f00a6ee98037 100644 (file)
@@ -1387,7 +1387,7 @@ static void render_composit_stats(void *UNUSED(arg), char *str)
 static void do_merge_fullsample(Render *re, bNodeTree *ntree)
 {
        float *rectf, filt[3][3];
-       int sample;
+       int x, y, sample;
        
        /* interaction callbacks */
        if (ntree) {
@@ -1408,7 +1408,7 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree)
        for (sample = 0; sample < re->r.osa; sample++) {
                Render *re1;
                RenderResult rres;
-               int x, y, mask;
+               int mask;
                
                /* enable full sample print */
                R.i.curfsa = sample + 1;
@@ -1471,6 +1471,18 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree)
                if (re->test_break(re->tbh))
                        break;
        }
+
+       /* clamp alpha and RGB to 0..1 and 0..inf, can go outside due to filter */
+       for (y = 0; y < re->recty; y++) {
+               float *rf = rectf + 4 * y * re->rectx;
+                       
+               for (x = 0; x < re->rectx; x++, rf += 4) {
+                       rf[0] = MAX2(rf[0], 0.0f);
+                       rf[1] = MAX2(rf[1], 0.0f);
+                       rf[2] = MAX2(rf[2], 0.0f);
+                       CLAMP(rf[3], 0.0f, 1.0f);
+               }
+       }
        
        /* clear interaction callbacks */
        if (ntree) {
index 2161449c2d1355635afc4950f19ca1a1a32cbb41..0d894073cee4761ca55e223ce3ca4255ad0c58c7 100644 (file)
@@ -990,6 +990,30 @@ static void convert_to_key_alpha(RenderPart *pa, RenderLayer *rl)
        }
 }
 
+/* clamp alpha and RGB to 0..1 and 0..inf, can go outside due to filter */
+static void clamp_alpha_rgb_range(RenderPart *pa, RenderLayer *rl)
+{
+       RenderLayer *rlpp[RE_MAX_OSA];
+       int y, sample, totsample;
+       
+       totsample= get_sample_layers(pa, rl, rlpp);
+
+       /* not for full sample, there we clamp after compositing */
+       if (totsample > 1)
+               return;
+       
+       for (sample= 0; sample<totsample; sample++) {
+               float *rectf= rlpp[sample]->rectf;
+               
+               for (y= pa->rectx*pa->recty; y>0; y--, rectf+=4) {
+                       rectf[0] = MAX2(rectf[0], 0.0f);
+                       rectf[1] = MAX2(rectf[1], 0.0f);
+                       rectf[2] = MAX2(rectf[2], 0.0f);
+                       CLAMP(rectf[3], 0.0f, 1.0f);
+               }
+       }
+}
+
 /* adds only alpha values */
 static void edge_enhance_tile(RenderPart *pa, float *rectf, int *rectz)
 {
@@ -1270,6 +1294,9 @@ void zbufshadeDA_tile(RenderPart *pa)
                
                if (rl->passflag & SCE_PASS_VECTOR)
                        reset_sky_speed(pa, rl);
+
+               /* clamp alpha to 0..1 range, can go outside due to filter */
+               clamp_alpha_rgb_range(pa, rl);
                
                /* de-premul alpha */
                if (R.r.alphamode & R_ALPHAKEY)