Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Sharybin <sergey.vfx@gmail.com>2011-07-24 14:26:22 +0400
committerSergey Sharybin <sergey.vfx@gmail.com>2011-07-24 14:26:22 +0400
commitb154b5993829f92e03233a04410b3667f2976556 (patch)
treec947d163e45ef0eab6c97699e13aad8ced20f40f /source/blender
parentcb2423e849d03cf1d288df94401cfd8d49c8ff56 (diff)
New dilation function from Morten Mikkelsen (aka sparky).
This commit fixes very noticeable seams caused by margins calculated incorrectly. This commit changes way margin is calculated in and makes textures really seamless. Also margin limited to 32 isn't good now -- artists are baking really large textures nowadays so margin is now limited to 64px. Thank you, Morten!
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/imbuf/IMB_imbuf.h2
-rw-r--r--source/blender/imbuf/intern/filter.c219
-rw-r--r--source/blender/makesrna/intern/rna_scene.c2
-rw-r--r--source/blender/render/intern/source/rendercore.c22
4 files changed, 118 insertions, 127 deletions
diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h
index ff01e3a8a1e..36123592c54 100644
--- a/source/blender/imbuf/IMB_imbuf.h
+++ b/source/blender/imbuf/IMB_imbuf.h
@@ -252,7 +252,7 @@ void IMB_filter(struct ImBuf *ibuf);
void IMB_filterN(struct ImBuf *out, struct ImBuf *in);
void IMB_mask_filter_extend(char *mask, int width, int height);
void IMB_mask_clear(struct ImBuf *ibuf, char *mask, int val);
-void IMB_filter_extend(struct ImBuf *ibuf, char *mask);
+void IMB_filter_extend(struct ImBuf *ibuf, char *mask, int filter);
void IMB_makemipmap(struct ImBuf *ibuf, int use_filter);
void IMB_remakemipmap(struct ImBuf *ibuf, int use_filter);
struct ImBuf *IMB_getmipmap(struct ImBuf *ibuf, int level);
diff --git a/source/blender/imbuf/intern/filter.c b/source/blender/imbuf/intern/filter.c
index d12360e5a7e..1644e653df4 100644
--- a/source/blender/imbuf/intern/filter.c
+++ b/source/blender/imbuf/intern/filter.c
@@ -21,7 +21,7 @@
*
* The Original Code is: all of this file.
*
- * Contributor(s): none yet.
+ * Contributor(s): Morten Mikkelsen.
*
* ***** END GPL LICENSE BLOCK *****
* filter.c
@@ -326,121 +326,132 @@ void IMB_mask_clear(ImBuf *ibuf, char *mask, int val)
}
}
-#define EXTEND_PIXEL(color, w) if((color)[3]) {r+= w*(color)[0]; g+= w*(color)[1]; b+= w*(color)[2]; a+= w*(color)[3]; tot+=w;}
+static int filter_make_index(const int x, const int y, const int w, const int h)
+{
+ if(x<0 || x>=w || y<0 || y>=h) return -1; /* return bad index */
+ else return y*w+x;
+}
+
+static int check_pixel_assigned(const void *buffer, const char *mask, const int index, const int depth, const int is_float)
+{
+ int res = 0;
+
+ if(index>=0) {
+ const int alpha_index = depth*index+(depth-1);
+
+ if(mask!=NULL) {
+ res = mask[index]!=0 ? 1 : 0;
+ }
+ else if( (is_float && ((const float *) buffer)[alpha_index]!=0.0f) ||
+ (!is_float && ((const unsigned char *) buffer)[alpha_index]!=0) ) {
+ res=1;
+ }
+ }
+
+ return res;
+}
/* if alpha is zero, it checks surrounding pixels and averages color. sets new alphas to 1.0
*
* When a mask is given, only effect pixels with a mask value of 1, defined as BAKE_MASK_MARGIN in rendercore.c
* */
-void IMB_filter_extend(struct ImBuf *ibuf, char *mask)
+void IMB_filter_extend(struct ImBuf *ibuf, char *mask, int filter)
{
- register char *row1, *row2, *row3;
- register char *cp;
- int rowlen, x, y;
-
- rowlen= ibuf->x;
-
-
- if (ibuf->rect_float) {
- float *temprect;
- float *row1f, *row2f, *row3f;
- float *fp;
- temprect= MEM_dupallocN(ibuf->rect_float);
-
- for(y=1; y<=ibuf->y; y++) {
- /* setup rows */
- row1f= (float *)(temprect + (y-2)*rowlen*4);
- row2f= row1f + 4*rowlen;
- row3f= row2f + 4*rowlen;
- if(y==1)
- row1f= row2f;
- else if(y==ibuf->y)
- row3f= row2f;
-
- fp= (float *)(ibuf->rect_float + (y-1)*rowlen*4);
-
- for(x=0; x<rowlen; x++) {
- if((mask==NULL && fp[3]==0.0f) || (mask && mask[((y-1)*rowlen)+x]==1)) {
- int tot= 0;
- float r=0.0f, g=0.0f, b=0.0f, a=0.0f;
-
- EXTEND_PIXEL(row1f, 1);
- EXTEND_PIXEL(row2f, 2);
- EXTEND_PIXEL(row3f, 1);
- EXTEND_PIXEL(row1f+4, 2);
- EXTEND_PIXEL(row3f+4, 2);
- if(x!=rowlen-1) {
- EXTEND_PIXEL(row1f+8, 1);
- EXTEND_PIXEL(row2f+8, 2);
- EXTEND_PIXEL(row3f+8, 1);
- }
- if(tot) {
- fp[0]= r/tot;
- fp[1]= g/tot;
- fp[2]= b/tot;
- fp[3]= a/tot;
+ const int width= ibuf->x;
+ const int height= ibuf->y;
+ const int depth= 4; /* always 4 channels */
+ const int chsize= ibuf->rect_float ? sizeof(float) : sizeof(unsigned char);
+ const int bsize= width*height*depth*chsize;
+ const int is_float= ibuf->rect_float!=NULL;
+ void *dstbuf= (void *) MEM_dupallocN(ibuf->rect_float ? (void *) ibuf->rect_float : (void *) ibuf->rect);
+ char *dstmask= mask==NULL ? NULL : (char *) MEM_dupallocN(mask);
+ void *srcbuf= ibuf->rect_float ? (void *) ibuf->rect_float : (void *) ibuf->rect;
+ char *srcmask= mask;
+ int cannot_early_out= 1, r, n, k, i, j, c;
+ float weight[25];
+
+ /* build a weights buffer */
+ n= 2;
+ k= 0;
+ for(i = -n; i <= n; i++)
+ for(j = -n; j <= n; j++)
+ weight[k++] = sqrt((float) i * i + j * j);
+
+ /* run passes */
+ for(r = 0; cannot_early_out == 1 && r < filter; r++) {
+ int x, y;
+ cannot_early_out = 0;
+
+ for(y= 0; y<height; y++) {
+ for(x= 0; x<width; x++) {
+ const int index= filter_make_index(x, y, width, height);
+
+ /* only update unassigned pixels */
+ if(!check_pixel_assigned(srcbuf, srcmask, index, depth, is_float)) {
+ float tmp[4];
+ float wsum=0;
+ float acc[4]={0,0,0,0};
+ k = 0;
+
+ if (check_pixel_assigned(srcbuf, srcmask, filter_make_index(x-1, y, width, height), depth, is_float) ||
+ check_pixel_assigned(srcbuf, srcmask, filter_make_index(x+1, y, width, height), depth, is_float) ||
+ check_pixel_assigned(srcbuf, srcmask, filter_make_index(x, y-1, width, height), depth, is_float) ||
+ check_pixel_assigned(srcbuf, srcmask, filter_make_index(x, y+1, width, height), depth, is_float)) {
+ for(i= -n; i<=n; i++) {
+ for(j=-n; j<=n; j++) {
+ if(i != 0 || j != 0) {
+ const int tmpindex= filter_make_index(x+i, y+j, width, height);
+
+ if(check_pixel_assigned(srcbuf, srcmask, tmpindex, depth, is_float)) {
+ if(is_float) {
+ for(c=0; c<depth; c++)
+ tmp[c] = ((const float *) srcbuf)[depth*tmpindex+c];
+ }
+ else {
+ for(c=0; c<depth; c++)
+ tmp[c] = (float) ((const unsigned char *) srcbuf)[depth*tmpindex+c];
+ }
+
+ wsum+= weight[k];
+
+ for(c=0; c<depth; c++)
+ acc[c]+= weight[k] * tmp[c];
+ }
+ }
+ k++;
+ }
+ }
+
+ if(wsum!=0) {
+ for(c=0; c<depth; c++)
+ acc[c]/= wsum;
+
+ if(is_float) {
+ for(c=0; c<depth; c++)
+ ((float *) dstbuf)[depth*index+c] = acc[c];
+ }
+ else {
+ for(c=0; c<depth; c++) {
+ ((unsigned char *) dstbuf)[depth*index+c]= acc[c] > 255 ? 255 : (acc[c] < 0 ? 0 : ((unsigned char) (acc[c]+0.5f)));
+ }
+ }
+
+ if(dstmask!=NULL) dstmask[index]=FILTER_MASK_MARGIN; /* assigned */
+ cannot_early_out = 1;
+ }
}
}
- fp+=4;
-
- if(x!=0) {
- row1f+=4; row2f+=4; row3f+=4;
- }
}
}
- MEM_freeN(temprect);
- }
- else if(ibuf->rect) {
- int *temprect;
-
- /* make a copy, to prevent flooding */
- temprect= MEM_dupallocN(ibuf->rect);
-
- for(y=1; y<=ibuf->y; y++) {
- /* setup rows */
- row1= (char *)(temprect + (y-2)*rowlen);
- row2= row1 + 4*rowlen;
- row3= row2 + 4*rowlen;
- if(y==1)
- row1= row2;
- else if(y==ibuf->y)
- row3= row2;
-
- cp= (char *)(ibuf->rect + (y-1)*rowlen);
-
- for(x=0; x<rowlen; x++) {
- /*if(cp[3]==0) {*/
- if((mask==NULL && cp[3]==0) || (mask && mask[((y-1)*rowlen)+x]==1)) {
- int tot= 0, r=0, g=0, b=0, a=0;
-
- EXTEND_PIXEL(row1, 1);
- EXTEND_PIXEL(row2, 2);
- EXTEND_PIXEL(row3, 1);
- EXTEND_PIXEL(row1+4, 2);
- EXTEND_PIXEL(row3+4, 2);
- if(x!=rowlen-1) {
- EXTEND_PIXEL(row1+8, 1);
- EXTEND_PIXEL(row2+8, 2);
- EXTEND_PIXEL(row3+8, 1);
- }
- if(tot) {
- cp[0]= r/tot;
- cp[1]= g/tot;
- cp[2]= b/tot;
- cp[3]= a/tot;
- }
- }
- cp+=4;
-
- if(x!=0) {
- row1+=4; row2+=4; row3+=4;
- }
- }
- }
-
- MEM_freeN(temprect);
+ /* keep the original buffer up to date. */
+ memcpy(srcbuf, dstbuf, bsize);
+ if(dstmask!=NULL) memcpy(srcmask, dstmask, width*height);
}
+
+ /* free memory */
+ MEM_freeN(dstbuf);
+ if(dstmask!=NULL) MEM_freeN(dstmask);
}
/* threadsafe version, only recreates existing maps */
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 9f751da484e..d9475eaa683 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -2815,7 +2815,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
prop= RNA_def_property(srna, "bake_margin", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "bake_filter");
- RNA_def_property_range(prop, 0, 32);
+ RNA_def_property_range(prop, 0, 64);
RNA_def_property_ui_text(prop, "Margin", "Amount of pixels to extend the baked result with, as post process filter");
prop= RNA_def_property(srna, "bake_distance", PROP_FLOAT, PROP_NONE);
diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c
index 3aca334cffe..a7e19c8db4f 100644
--- a/source/blender/render/intern/source/rendercore.c
+++ b/source/blender/render/intern/source/rendercore.c
@@ -2577,27 +2577,7 @@ void RE_bake_ibuf_filter(ImBuf *ibuf, char *mask, const int filter)
/* Margin */
if(filter) {
- char *temprect;
- int i;
-
- /* extend the mask +2 pixels from the image,
- * this is so colors dont blend in from outside */
-
- for(i=0; i< filter; i++)
- IMB_mask_filter_extend(mask, ibuf->x, ibuf->y);
-
- temprect = MEM_dupallocN(mask);
-
- /* expand twice to clear this many pixels, so they blend back in */
- IMB_mask_filter_extend(temprect, ibuf->x, ibuf->y);
- IMB_mask_filter_extend(temprect, ibuf->x, ibuf->y);
-
- /* clear all pixels in the margin */
- IMB_mask_clear(ibuf, temprect, FILTER_MASK_MARGIN);
- MEM_freeN(temprect);
-
- for(i= 0; i < filter; i++)
- IMB_filter_extend(ibuf, mask);
+ IMB_filter_extend(ibuf, mask, filter);
}
/* if the bake results in new alpha then change the image setting */