Fix for unified rendering;
authorTon Roosendaal <ton@blender.org>
Sun, 28 Nov 2004 14:28:55 +0000 (14:28 +0000)
committerTon Roosendaal <ton@blender.org>
Sun, 28 Nov 2004 14:28:55 +0000 (14:28 +0000)
Gaussian sampling/rendering now supported too!
Also corrected gamma corrected adding of colors, which gives better alpha
and blending with sky than normal render does. The latter I could check
once too...

source/blender/render/intern/include/pixelblending.h
source/blender/render/intern/source/initrender.c
source/blender/render/intern/source/pixelblending.c
source/blender/render/intern/source/vanillaRenderPipe.c
source/blender/src/buttons_scene.c

index 04fc037865f1551a596f83689d19a17dd40f1c12..b413bc8b8a12907a66351c60705c21cc2b71bc31 100644 (file)
@@ -68,10 +68,16 @@ int addUnderSampColF(float *sampcol, float *dest, int mask, int osaNr);
 void addOverSampColF(float *sampcol, float *dest, int mask, int osaNr);
 
 /**
- * Convert a series of oversampled pixels into a single pixel. 
+* add 1 pixel to into filtered three lines 
  * (float vecs to float vec)
  */
-void sampleFloatColV2FloatColV(float *sample, float *dest, int osaNr);
+void add_filt_fmask(unsigned int mask, float *col, float *rb1, float *rb2, float *rb3);
+
+/**
+ * Convert a series of oversampled pixels into filtered three lines 
+ * (float vecs to float vec)
+ */
+void sampleFloatColV2FloatColVFilter(float *sample, float *dest1, float *dest2, float *dest3, int osaNr);
 
 /**
  * Convert a series of oversampled pixels into a single pixel. Uses R.osa to
index c56d3b2e26fa97847cb60113c3aa92f092846c9e..1617eb1e23d2804f9dba8aeb28b415c571e01f39 100644 (file)
 
 
 /* from render.c */
-extern float fmask[256], centLut[16];
-extern unsigned short *mask1[9], *mask2[9], /*  *igamtab1, */ *igamtab2/*,  *gamtab */;
+extern float fmask[256], centLut[16], *fmask1[9], *fmask2[9];
+extern unsigned short *mask1[9], *mask2[9], *igamtab2;
 extern char cmask[256], *centmask;
 
 Material defmaterial;
@@ -184,7 +184,7 @@ float  calc_weight(float *weight, int i, int j)
 
                weight[a]= 0.0;
 
-               /* gaussian weighting has been cancelled */
+               /* gaussian weighting */
                if(R.r.mode & R_GAUSS) {
                        if(dist<R.r.gauss) {
                                x = dist*R.r.gauss;
@@ -205,8 +205,8 @@ void RE_init_filt_mask(void)
 {
        static int firsttime=1;
        static float lastgamma= 0.0;
-       float gamma, igamma;
-       float weight[32], totw, val, *fpx1, *fpx2, *fpy1, *fpy2;
+       float gamma, igamma, flweight[32];
+       float weight[32], totw, val, *fpx1, *fpx2, *fpy1, *fpy2, *m3, *m4;
        int i, j, a;
        unsigned short *m1, *m2, shweight[32];
 
@@ -214,6 +214,8 @@ void RE_init_filt_mask(void)
                for(a=0; a<9;a++) {
                        mask1[a]= MEM_mallocN(256*sizeof(short), "initfilt");
                        mask2[a]= MEM_mallocN(256*sizeof(short), "initfilt");
+                       fmask1[a]= MEM_mallocN(256*sizeof(float), "initfilt");
+                       fmask2[a]= MEM_mallocN(256*sizeof(float), "initfilt");
                }
                for(a=0; a<256; a++) {
                        cmask[a]= 0;
@@ -290,6 +292,8 @@ void RE_init_filt_mask(void)
        for(a=0; a<9;a++) {
                memset(mask1[a], 0, 256*2);
                memset(mask2[a], 0, 256*2);
+               memset(fmask1[a], 0, 256*4);
+               memset(fmask2[a], 0, 256*4);
        }
 
        /* calculate totw */
@@ -304,46 +308,65 @@ void RE_init_filt_mask(void)
                for(i= -1; i<2; i++) {
                        /* calculate using jit, with offset the weights */
 
-                       memset(weight, 0, 32*2);
+                       memset(weight, 0, sizeof(weight));
                        calc_weight(weight, i, j);
 
                        for(a=0; a<16; a++) shweight[a]= weight[a]*(65535.0/totw);
+                       for(a=0; a<16; a++) flweight[a]= weight[a]*(1.0/totw);
 
                        m1= mask1[ 3*(j+1)+i+1 ];
                        m2= mask2[ 3*(j+1)+i+1 ];
+                       m3= fmask1[ 3*(j+1)+i+1 ];
+                       m4= fmask2[ 3*(j+1)+i+1 ];
 
                        for(a=0; a<256; a++) {
                                if(a &   1) {
                                        m1[a]+= shweight[0];
                                        m2[a]+= shweight[8];
+                                       m3[a]+= flweight[0];
+                                       m4[a]+= flweight[8];
                                }
                                if(a &   2) {
                                        m1[a]+= shweight[1];
                                        m2[a]+= shweight[9];
+                                       m3[a]+= flweight[1];
+                                       m4[a]+= flweight[9];
                                }
                                if(a &   4) {
                                        m1[a]+= shweight[2];
                                        m2[a]+= shweight[10];
+                                       m3[a]+= flweight[2];
+                                       m4[a]+= flweight[10];
                                }
                                if(a &   8) {
                                        m1[a]+= shweight[3];
                                        m2[a]+= shweight[11];
+                                       m3[a]+= flweight[3];
+                                       m4[a]+= flweight[11];
                                }
                                if(a &  16) {
                                        m1[a]+= shweight[4];
                                        m2[a]+= shweight[12];
+                                       m3[a]+= flweight[4];
+                                       m4[a]+= flweight[12];
                                }
                                if(a &  32) {
                                        m1[a]+= shweight[5];
                                        m2[a]+= shweight[13];
+                                       m3[a]+= flweight[5];
+                                       m4[a]+= flweight[13];
                                }
                                if(a &  64) {
                                        m1[a]+= shweight[6];
                                        m2[a]+= shweight[14];
+                                       m3[a]+= flweight[6];
+                                       m4[a]+= flweight[14];
                                }
                                if(a & 128) {
                                        m1[a]+= shweight[7];
                                        m2[a]+= shweight[15];
+                                       m3[a]+= flweight[7];
+                                       m4[a]+= flweight[15];
                                }
                        }
                }
@@ -432,6 +455,8 @@ void RE_free_filt_mask()
        for(a=0; a<9; a++) {
                MEM_freeN(mask1[a]);
                MEM_freeN(mask2[a]);
+               MEM_freeN(fmask1[a]);
+               MEM_freeN(fmask2[a]);
        }
        MEM_freeN(gamtab);
        MEM_freeN(igamtab1);
@@ -1176,7 +1201,7 @@ void RE_initrender(struct View3D *ogl_render_view3d)
                if(G.scene->camera==0) {
                        error("No camera");
                        /* needed because R.rectx and R.recty can be unmatching R.rectot */
-                       if(R.rectot) freeN(R.rectot);
+                       if(R.rectot) MEM_freeN(R.rectot);
                        R.rectot= NULL;
                        
                        G.afbreek=1;
index 463abf34fa7a8397aeb9202107487874bfcb596e..47c2e51ef233495eed1dd80c2cdf01af96aca446 100644 (file)
@@ -562,45 +562,89 @@ void sampleShortColV2ShortColV(unsigned short *sample, unsigned short *dest, int
 
 /* ------------------------------------------------------------------------- */
 
-void sampleFloatColV2FloatColV(float *sample, float *dest, int osaNr)
+float *fmask1[9], *fmask2[9];
+
+/* filtered adding to scanlines */
+void add_filt_fmask(unsigned int mask, float *col, float *rb1, float *rb2, float *rb3)
+{
+       /* calc the value of mask */
+       float val, r, g, b, al;
+       unsigned int a, maskand, maskshift;
+       int j;
+       
+       al= col[3];
+       r= col[0];
+       g= col[1];
+       b= col[2];
+       
+       maskand= (mask & 255);
+       maskshift= (mask >>8);
+       
+       for(j=2; j>=0; j--) {
+               
+               a= j;
+               
+               val= *(fmask1[a] +maskand) + *(fmask2[a] +maskshift);
+               if(val!=0.0) {
+                       rb1[3]+= val*al;
+                       rb1[0]+= val*r;
+                       rb1[1]+= val*g;
+                       rb1[2]+= val*b;
+               }
+               a+=3;
+               
+               val= *(fmask1[a] +maskand) + *(fmask2[a] +maskshift);
+               if(val!=0.0) {
+                       rb2[3]+= val*al;
+                       rb2[0]+= val*r;
+                       rb2[1]+= val*g;
+                       rb2[2]+= val*b;
+               }
+               a+=3;
+               
+               val= *(fmask1[a] +maskand) + *(fmask2[a] +maskshift);
+               if(val!=0.0) {
+                       rb3[3]+= val*al;
+                       rb3[0]+= val*r;
+                       rb3[1]+= val*g;
+                       rb3[2]+= val*b;
+               }
+               
+               rb1+= 4;
+               rb2+= 4;
+               rb3+= 4;
+       }
+}
+
+
+void sampleFloatColV2FloatColVFilter(float *sample, float *dest1, float *dest2, float *dest3, int osaNr)
 {
     float intcol[4] = {0};
     float *scol = sample; 
     int   a = 0;
 
-       if (doGamma()) {
-               /* use a LUT and interpolation to do the gamma correction */
-               for(a=0; a < osaNr; a++, scol+=4) {
-                       intcol[0] += gammaCorrect( (scol[0]<1.0) ? scol[0]:1.0 ); 
-                       intcol[1] += gammaCorrect( (scol[1]<1.0) ? scol[1]:1.0 ); 
-                       intcol[2] += gammaCorrect( (scol[2]<1.0) ? scol[2]:1.0 ); 
-                       intcol[3] += scol[3];
-               }
-
-               /* renormalise */
-               intcol[0] /= osaNr;
-               intcol[1] /= osaNr;
-               intcol[2] /= osaNr;
-               intcol[3] /= osaNr;
-
-       /* back to pixel values */
-               dest[0] = invGammaCorrect(intcol[0]);
-               dest[1] = invGammaCorrect(intcol[1]);
-               dest[2] = invGammaCorrect(intcol[2]);
-               dest[3] = intcol[3];
-       } else {
-               /* no gamma */
-               for(a=0; a < osaNr; a++, scol+=4) {
-                       intcol[0] += (scol[0]<1.0) ? scol[0]:1.0 ; 
-                       intcol[1] += (scol[1]<1.0) ? scol[1]:1.0 ;
-                       intcol[2] += (scol[2]<1.0) ? scol[2]:1.0 ; 
-                       intcol[3] += scol[3];
+       if(osaNr==1) {
+               dest2[4]= sample[0];
+               dest2[5]= sample[1];
+               dest2[6]= sample[2];
+               dest2[7]= sample[3];
+       }
+       else {
+               if (doGamma()) {
+                       /* use a LUT and interpolation to do the gamma correction */
+                       for(a=0; a < osaNr; a++, scol+=4) {
+                               intcol[0] = gammaCorrect( (scol[0]<1.0) ? scol[0]:1.0 ); 
+                               intcol[1] = gammaCorrect( (scol[1]<1.0) ? scol[1]:1.0 ); 
+                               intcol[2] = gammaCorrect( (scol[2]<1.0) ? scol[2]:1.0 ); 
+                               intcol[3] = scol[3];
+                               add_filt_fmask(1<<a, intcol, dest1, dest2, dest3);
+                       }
+               } 
+               else {
+                       for(a=0; a < osaNr; a++, scol+=4) {
+                               add_filt_fmask(1<<a, scol, dest1, dest2, dest3);
+                       }
                }
-    
-               dest[0]= intcol[0]/osaNr;
-               dest[1]= intcol[1]/osaNr;
-               dest[2]= intcol[2]/osaNr;
-               dest[3]= intcol[3]/osaNr;
        }
        
 } /* end void sampleFloatColVToFloatColV(unsigned short *, unsigned short *) */
index 6a384b270c9ff06ba2cf2e1f2da44cf6e9ae1394..c913b6df23c05f094e65c9bc574d88bd1ec07796 100644 (file)
@@ -131,8 +131,11 @@ extern unsigned short usegamtab, shortcol[4],
 extern RE_APixstrExt *APixbufExt;/*Zbuffer: linked list of face, halo indices*/
 
 /* Globals : --------------------------------------------------------------- */
+                                                          /* we use three lines, for gaussian sample     */
+RE_COLBUFTYPE *AColourBuffer1; /* Buffer for colours of 1 line of pixels      */
+RE_COLBUFTYPE *AColourBuffer2; /* Buffer for colours of 1 line of pixels      */
+RE_COLBUFTYPE *AColourBuffer3; /* Buffer for colours of 1 line of pixels      */
 
-RE_COLBUFTYPE *AColourBuffer; /* Buffer for colours of 1 line of pixels      */
 static int     Aminy;         /* y value of first line in the accu buffer    */
 static int     Amaxy;         /* y value of last line in the accu buffer     */
                               /* -also used to clip when zbuffering          */
@@ -174,6 +177,7 @@ void integratePerSubStack(struct RE_faceField* stack,
 
 void zBufShadeAdvanced()
 {
+       RE_COLBUFTYPE *cycle;
     int      y, keepLooping = 1;
     float xjit = 0.0, yjit = 0.0;
 
@@ -229,13 +233,24 @@ void zBufShadeAdvanced()
                calcZBufLine(y);
 
                renderZBufLine(y);
-               transferColourBufferToOutput(y);
+               if(y) {
+                       transferColourBufferToOutput(y-1);
                
-               if(y & 1) RE_local_render_display(y-1, y, imageWidth, imageHeight, R.rectot);           
+                       if((y & 1)==0) RE_local_render_display(y-2, y-1, imageWidth, imageHeight, R.rectot);            
+               }
+               
+               /* buffer cycling */
+               eraseColBuf(AColourBuffer3);
+               cycle= AColourBuffer3;
+               AColourBuffer3= AColourBuffer2;
+               AColourBuffer2= AColourBuffer1;
+               AColourBuffer1= cycle;
 
                if(RE_local_test_break()) keepLooping = 0;
                y++; 
     }
+       if(keepLooping) transferColourBufferToOutput(y-1);
+
        freeRenderBuffers();
 
        /* Edge rendering is done purely as a post-effect                        */
@@ -260,13 +275,15 @@ void zBufShadeAdvanced()
 
 void initRenderBuffers(int bwidth) 
 {
-
+       /* bwidth+4, as in rendercore.c. I think it's too much, but yah (ton) */
+    AColourBuffer1 = MEM_callocN(4 * sizeof(RE_COLBUFTYPE) * (bwidth+4), "Acolrow");
+    AColourBuffer2 = MEM_callocN(4 * sizeof(RE_COLBUFTYPE) * (bwidth+4), "Acolrow");
+    AColourBuffer3 = MEM_callocN(4 * sizeof(RE_COLBUFTYPE) * (bwidth+4), "Acolrow");
+       
     /* The +1 is needed because the fill-functions use a +1 offset when      */
     /* filling in pixels. Mind that also the buffer-clearing function needs  */
     /* this offset (done in calcZBufLine).                                   */
        /* The offset is wrong: it shouldn't be there. I need to fix this still. */
-    AColourBuffer = MEM_callocN(4 * sizeof(RE_COLBUFTYPE) * bwidth, 
-                            "Acolrow");
        zBufferWidth = bwidth + 1;
        initZbuffer(bwidth + 1);
 
@@ -291,7 +308,9 @@ void initRenderBuffers(int bwidth)
 /* ------------------------------------------------------------------------- */
 
 void freeRenderBuffers(void) { 
-    if (AColourBuffer) MEM_freeN(AColourBuffer);
+    if (AColourBuffer1) MEM_freeN(AColourBuffer1);
+    if (AColourBuffer2) MEM_freeN(AColourBuffer2);
+    if (AColourBuffer3) MEM_freeN(AColourBuffer3);
        freeZbuffer();
 } /* End of void freeZBuffers(void) */
 
@@ -791,12 +810,16 @@ void integratePerSubStack(struct RE_faceField* stack,
 /* distance, and then used for rendering pixels. zrow might be replaced by   */
 /* an RE_APixstrExt* array                                                   */
 /* - redo the numbering to something more logical                            */
-void renderZBufLine(int y) {
+
+void renderZBufLine(int y) 
+{
     int  zrow[RE_MAX_FACES_PER_PIXEL][RE_PIXELFIELDSIZE];
     RE_APixstrExt *ap;       /* iterator for the face-lists                  */
        int apteller;
     int x;                   /* pixel counter                                */
-    RE_COLBUFTYPE *colbuf;   /* pointer into the line buffer                 */
+    RE_COLBUFTYPE *colbuf1;   /* pointer into the line buffer                 */
+    RE_COLBUFTYPE *colbuf2;   /* pointer into the line buffer                 */
+    RE_COLBUFTYPE *colbuf3;   /* pointer into the line buffer                 */
     RE_COLBUFTYPE *j = NULL; /* generic pixel pointer                        */
     int i;                   /* yet another counter                          */
     int stackDepth;          /* faces-behind-this-pixel counter              */
@@ -805,13 +828,15 @@ void renderZBufLine(int y) {
                             /* field is NOT readable.                        */
        
     /* Prepare buffers and iterators */
-    colbuf    = AColourBuffer;
-    eraseColBuf(AColourBuffer);
+    colbuf1    = AColourBuffer1;
+    colbuf2    = AColourBuffer2;
+    colbuf3    = AColourBuffer3;
+       
     ap        = APixbufExt + (zBufferWidth * (y - Aminy));
        apteller  = (zBufferWidth * (y - Aminy));
        
     /* Rendering: give the right colour to this pixel (shade it) */
-       for( x = 0; x < bufferWidth; x++, ap++, colbuf+=4) {
+       for( x = 0; x < bufferWidth; x++, ap++, colbuf1+=4, colbuf2+=4, colbuf3+=4) {
                if(ap->t[0]) {
             /* reset sample collector */
             j = sampcol;
@@ -831,27 +856,35 @@ void renderZBufLine(int y) {
                        integratePerSubStack(RE_OSAstack, RE_OSAstack_ptr, 
                                                                 x, y, osaNr); 
                        
-                       /* d. Gamma corrected blending                                   */
-                       sampleFloatColV2FloatColV(sampcol, colbuf, osaNr);
+                       /* d. Gamma corrected blending and Gaussian                      */
+                       sampleFloatColV2FloatColVFilter(sampcol, colbuf1, colbuf2, colbuf3, osaNr);
+                       
                } else {
                        /* Remember to do things back-to-front!                          */
                        
                        /* This is a bit dirty. Depending on sky-mode, the pixel is      */
                        /* blended in differently.                                       */
                        renderSkyPixelFloat(x, y);
-                       cpFloatColV(collector, colbuf);
-
+                       
+                       j = sampcol;
+                       for(i = 0; i < osaNr; i++, j+=4) { 
+                               j[0]= collector[0]; j[1]= collector[1];
+                               j[2]= collector[2]; j[3]= collector[3];
+                       }
+                       
+                       sampleFloatColV2FloatColVFilter(sampcol, colbuf1, colbuf2, colbuf3, osaNr);
+                       
+                       
                        /* Spothalos are part of the normal pixelshader, so for covered  */
                        /* pixels they are handled ok. They are 'normally' alpha blended */
                        /* onto the existing colour in the collector.                    */
                        if(R.flag & R_LAMPHALO) {
                                renderSpotHaloPixel(x, y, collector);
-                               addAlphaOverFloat(colbuf, collector);
+                               addAlphaOverFloat(colbuf2+4, collector);
                        }
-                       
                }
     } /* End of pixel loop */
-    
+
 } /* End of void renderZBufLine(int y) */
 
 
@@ -1420,24 +1453,32 @@ void std_transFloatColV2CharColV( RE_COLBUFTYPE *buf, char *target)
   - key-alpha correction
     Key alpha means 'un-applying' the alpha. For fully covered pixels, this
        operation has no effect.
+  
+  - XXX WARNING! Added the inverse render gamma here, so this cannot be used external
+       without setting Osa or Gamme flags off (ton)
 
 ---------------------------------------------------------------------------- */
 void transferColourBufferToOutput(int y)
 {
-    /* Copy the contents of AColourBuffer to R.rectot + y * R.rectx */
+    /* Copy the contents of AColourBuffer3 to R.rectot + y * R.rectx */
     int x = 0;
-    RE_COLBUFTYPE *buf = AColourBuffer;
+    RE_COLBUFTYPE *buf = AColourBuffer3+4;
     char *target = (char*) (R.rectot + (y * imageWidth));
 
        /* Copy the first <imageWidth> pixels. We can do some more clipping on    */
        /* the z buffer, I think.                                                 */
        while (x < imageWidth) {
 
+               
+               /* invert gamma corrected additions */
+               if(osaNr!=1 && doGamma()) {
+                       buf[0] = invGammaCorrect(buf[0]);
+                       buf[1] = invGammaCorrect(buf[1]);
+                       buf[2] = invGammaCorrect(buf[2]);
+               }                       
+                       
                std_transFloatColV2CharColV(buf, target);
                
-               /* old function was: leave it for test */
-/*             cpFloatColV2CharColV(buf, target); */
-
                /*
                  Key-alpha mode:
                  Need to un-apply alpha if alpha is non-full. For full alpha,
@@ -1458,11 +1499,12 @@ void transferColourBufferToOutput(int y)
 
 /* ------------------------------------------------------------------------- */
 
-void eraseColBuf(RE_COLBUFTYPE *buf) {
+void eraseColBuf(RE_COLBUFTYPE *buf) 
+{
     /* By definition, the buffer's length is 4 * R.rectx items */
     int i = 0;
-/*      while (i < 4 * R.rectx) { */
-    while (i < 4 * bufferWidth) {
+
+    while (i < 4 * (bufferWidth+3)) {
         *buf = RE_ZERO_COLOUR_FLOAT;
         buf++; i++;
     }
index e804484a01d32aa3cffc73790a519dd3e4ac9f12..f2a4e20ced1849ec433c2c74b10a498368b0b496 100644 (file)
@@ -1130,11 +1130,8 @@ static void render_panel_render(void)
        uiDefButI(block, TOG|BIT|13,0,"Odd",    627,55,39,20,&G.scene->r.mode, 0, 0, 0, 0, "Enables Odd field first rendering (Default: Even field)");
        uiDefButI(block, TOG|BIT|7,0,"X",               668,55,19,20,&G.scene->r.mode, 0, 0, 0, 0, "Disables time difference in field calculations");
        
-       if(G.scene->r.mode & R_UNIFIED) uiBlockBeginAlign(block);
-       else {
-               uiDefButI(block, TOG|BIT|17,0,"Gauss",  565,34,60,20, &G.scene->r.mode, 0, 0, 0, 0, "Enable Gaussian sampling filter for antialiasing");
-               uiDefButF(block, NUM,B_DIFF,"",                 627,34,60,20,&G.scene->r.gauss,0.5, 1.5, 100, 2, "Sets the Gaussian filter size");
-       }
+       uiDefButI(block, TOG|BIT|17,0,"Gauss",  565,34,60,20, &G.scene->r.mode, 0, 0, 0, 0, "Enable Gaussian sampling filter for antialiasing");
+       uiDefButF(block, NUM,B_DIFF,"",                 627,34,60,20,&G.scene->r.gauss,0.5, 1.5, 100, 2, "Sets the Gaussian filter size");
        
        uiDefButI(block, TOG|BIT|9,REDRAWVIEWCAM, "Border",     565,13,60,20, &G.scene->r.mode, 0, 0, 0, 0, "Render a small cut-out of the image");
        uiDefButI(block, TOG|BIT|2, B_REDR, "Gamma",    627,13,60,20, &G.scene->r.mode, 0, 0, 0, 0, "Enable gamma correction");