Redoing the blur filters for composit;
http://www.blender.org/bf/filters/ I found out current blur actually doesn't do gauss, but more did regular quadratic. Now you can choose common filter types, but more specifically; - set gamma on, to emphasize bright parts in blur more than darker parts - use the bokeh option for (current circlular only) blur based on true area filters (meaning, for each pixel it samples the entire surrounding). This enables more effects, but is also much slower. Have to check on optimization for this still... use with care!
This commit is contained in:
@@ -218,4 +218,4 @@ int multitex(struct Tex *tex, float *texvec, float *dxt, float *dyt, int osatex
|
|||||||
struct Render *RE_GetRender(const char *name) {return (struct Render *)NULL;}
|
struct Render *RE_GetRender(const char *name) {return (struct Render *)NULL;}
|
||||||
struct RenderResult *RE_GetResult(Render *re) {return (struct RenderResult *)NULL;}
|
struct RenderResult *RE_GetResult(Render *re) {return (struct RenderResult *)NULL;}
|
||||||
float *RE_RenderLayerGetPass(RenderLayer *rl, int passtype) {return NULL;}
|
float *RE_RenderLayerGetPass(RenderLayer *rl, int passtype) {return NULL;}
|
||||||
|
float RE_filter_value(int type, float x) {return 0.0f;}
|
||||||
|
|||||||
@@ -771,6 +771,8 @@ bNode *nodeAddNodeType(bNodeTree *ntree, int type, bNodeTree *ngroup)
|
|||||||
node->storage= curvemapping_add(4, 0.0f, 0.0f, 1.0f, 1.0f);
|
node->storage= curvemapping_add(4, 0.0f, 0.0f, 1.0f, 1.0f);
|
||||||
else if(type==CMP_NODE_MAP_VALUE)
|
else if(type==CMP_NODE_MAP_VALUE)
|
||||||
node->storage= add_mapping();
|
node->storage= add_mapping();
|
||||||
|
else if(type==CMP_NODE_BLUR)
|
||||||
|
node->storage= MEM_callocN(sizeof(NodeBlurData), "node blur data");
|
||||||
}
|
}
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
|
|||||||
@@ -85,9 +85,9 @@ static CompBuf *alloc_compbuf(int sizex, int sizey, int type, int alloc)
|
|||||||
if(cbuf->type==CB_RGBA)
|
if(cbuf->type==CB_RGBA)
|
||||||
cbuf->rect= MEM_mallocT(4*sizeof(float)*sizex*sizey, "compbuf RGBA rect");
|
cbuf->rect= MEM_mallocT(4*sizeof(float)*sizex*sizey, "compbuf RGBA rect");
|
||||||
else if(cbuf->type==CB_VEC3)
|
else if(cbuf->type==CB_VEC3)
|
||||||
cbuf->rect= MEM_mallocT(4*sizeof(float)*sizex*sizey, "compbuf Vector3 rect");
|
cbuf->rect= MEM_mallocT(3*sizeof(float)*sizex*sizey, "compbuf Vector3 rect");
|
||||||
else if(cbuf->type==CB_VEC2)
|
else if(cbuf->type==CB_VEC2)
|
||||||
cbuf->rect= MEM_mallocT(4*sizeof(float)*sizex*sizey, "compbuf Vector2 rect");
|
cbuf->rect= MEM_mallocT(2*sizeof(float)*sizex*sizey, "compbuf Vector2 rect");
|
||||||
else
|
else
|
||||||
cbuf->rect= MEM_mallocT(sizeof(float)*sizex*sizey, "compbuf Fac rect");
|
cbuf->rect= MEM_mallocT(sizeof(float)*sizex*sizey, "compbuf Fac rect");
|
||||||
cbuf->malloc= 1;
|
cbuf->malloc= 1;
|
||||||
@@ -100,6 +100,13 @@ static CompBuf *alloc_compbuf(int sizex, int sizey, int type, int alloc)
|
|||||||
return cbuf;
|
return cbuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static CompBuf *dupalloc_compbuf(CompBuf *cbuf)
|
||||||
|
{
|
||||||
|
CompBuf *dupbuf= alloc_compbuf(cbuf->x, cbuf->y, cbuf->type, 1);
|
||||||
|
memcpy(dupbuf->rect, cbuf->rect, cbuf->type*sizeof(float)*cbuf->x*cbuf->y);
|
||||||
|
return dupbuf;
|
||||||
|
}
|
||||||
|
|
||||||
void free_compbuf(CompBuf *cbuf)
|
void free_compbuf(CompBuf *cbuf)
|
||||||
{
|
{
|
||||||
if(cbuf->malloc && cbuf->rect)
|
if(cbuf->malloc && cbuf->rect)
|
||||||
@@ -1501,7 +1508,7 @@ static bNodeType cmp_node_map_value= {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* **************** GAUSS BLUR ******************** */
|
/* **************** BLUR ******************** */
|
||||||
static bNodeSocketType cmp_node_blur_in[]= {
|
static bNodeSocketType cmp_node_blur_in[]= {
|
||||||
{ SOCK_RGBA, 1, "Image", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
|
{ 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},
|
{ SOCK_VALUE, 1, "Size", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
|
||||||
@@ -1512,7 +1519,7 @@ static bNodeSocketType cmp_node_blur_out[]= {
|
|||||||
{ -1, 0, "" }
|
{ -1, 0, "" }
|
||||||
};
|
};
|
||||||
|
|
||||||
static float *make_gausstab(int rad)
|
static float *make_gausstab(int filtertype, int rad)
|
||||||
{
|
{
|
||||||
float *gausstab, sum, val;
|
float *gausstab, sum, val;
|
||||||
int i, n;
|
int i, n;
|
||||||
@@ -1523,7 +1530,7 @@ static float *make_gausstab(int rad)
|
|||||||
|
|
||||||
sum = 0.0f;
|
sum = 0.0f;
|
||||||
for (i = -rad; i <= rad; i++) {
|
for (i = -rad; i <= rad; i++) {
|
||||||
val = exp(-4.0*((float)i*i) / (float) (rad*rad));
|
val= RE_filter_value(filtertype, (float)i/(float)rad);
|
||||||
sum += val;
|
sum += val;
|
||||||
gausstab[i+rad] = val;
|
gausstab[i+rad] = val;
|
||||||
}
|
}
|
||||||
@@ -1552,7 +1559,7 @@ static float *make_bloomtab(int rad)
|
|||||||
return bloomtab;
|
return bloomtab;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void blur_single_image(CompBuf *new, CompBuf *img, float blurx, float blury)
|
static void blur_single_image(CompBuf *new, CompBuf *img, float scale, NodeBlurData *nbd)
|
||||||
{
|
{
|
||||||
CompBuf *work;
|
CompBuf *work;
|
||||||
register float sum, val;
|
register float sum, val;
|
||||||
@@ -1567,13 +1574,13 @@ static void blur_single_image(CompBuf *new, CompBuf *img, float blurx, float blu
|
|||||||
work= alloc_compbuf(imgx, imgy, img->type, 1); // allocs
|
work= alloc_compbuf(imgx, imgy, img->type, 1); // allocs
|
||||||
|
|
||||||
/* horizontal */
|
/* horizontal */
|
||||||
rad = ceil(blurx);
|
rad = scale*(float)nbd->sizex;
|
||||||
if(rad>imgx/2)
|
if(rad>imgx/2)
|
||||||
rad= imgx/2;
|
rad= imgx/2;
|
||||||
else if(rad<1)
|
else if(rad<1)
|
||||||
rad= 1;
|
rad= 1;
|
||||||
|
|
||||||
gausstab= make_gausstab(rad);
|
gausstab= make_gausstab(nbd->filtertype, rad);
|
||||||
gausstabcent= gausstab+rad;
|
gausstabcent= gausstab+rad;
|
||||||
|
|
||||||
for (y = 0; y < imgy; y++) {
|
for (y = 0; y < imgy; y++) {
|
||||||
@@ -1611,13 +1618,13 @@ static void blur_single_image(CompBuf *new, CompBuf *img, float blurx, float blu
|
|||||||
/* vertical */
|
/* vertical */
|
||||||
MEM_freeT(gausstab);
|
MEM_freeT(gausstab);
|
||||||
|
|
||||||
rad = ceil(blury);
|
rad = scale*(float)nbd->sizey;
|
||||||
if(rad>imgy/2)
|
if(rad>imgy/2)
|
||||||
rad= imgy/2;
|
rad= imgy/2;
|
||||||
else if(rad<1)
|
else if(rad<1)
|
||||||
rad= 1;
|
rad= 1;
|
||||||
|
|
||||||
gausstab= make_gausstab(rad);
|
gausstab= make_gausstab(nbd->filtertype, rad);
|
||||||
gausstabcent= gausstab+rad;
|
gausstabcent= gausstab+rad;
|
||||||
|
|
||||||
bigstep = pix*imgx;
|
bigstep = pix*imgx;
|
||||||
@@ -1660,7 +1667,7 @@ static void blur_single_image(CompBuf *new, CompBuf *img, float blurx, float blu
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* reference has to be mapped 0-1, and equal in size */
|
/* 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)
|
static void bloom_with_reference(CompBuf *new, CompBuf *img, CompBuf *ref, float fac, NodeBlurData *nbd)
|
||||||
{
|
{
|
||||||
CompBuf *wbuf;
|
CompBuf *wbuf;
|
||||||
register float val;
|
register float val;
|
||||||
@@ -1677,14 +1684,14 @@ static void bloom_with_reference(CompBuf *new, CompBuf *img, CompBuf *ref, float
|
|||||||
memset(wbuf->rect, sizeof(float)*imgx*imgy, 0);
|
memset(wbuf->rect, sizeof(float)*imgx*imgy, 0);
|
||||||
|
|
||||||
/* horizontal */
|
/* horizontal */
|
||||||
radx = ceil(blurx);
|
radx = (float)nbd->sizex;
|
||||||
if(radx>imgx/2)
|
if(radx>imgx/2)
|
||||||
radx= imgx/2;
|
radx= imgx/2;
|
||||||
else if(radx<1)
|
else if(radx<1)
|
||||||
radx= 1;
|
radx= 1;
|
||||||
|
|
||||||
/* vertical */
|
/* vertical */
|
||||||
rady = ceil(blury);
|
rady = (float)nbd->sizey;
|
||||||
if(rady>imgy/2)
|
if(rady>imgy/2)
|
||||||
rady= imgy/2;
|
rady= imgy/2;
|
||||||
else if(rady<1)
|
else if(rady<1)
|
||||||
@@ -1780,8 +1787,130 @@ static void bloom_with_reference(CompBuf *new, CompBuf *img, CompBuf *ref, float
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void gamma_correct_compbuf(CompBuf *img, int inversed)
|
||||||
|
{
|
||||||
|
float *drect;
|
||||||
|
int x;
|
||||||
|
|
||||||
|
drect= img->rect;
|
||||||
|
if(inversed) {
|
||||||
|
for(x=img->x*img->y; x>0; x--, drect+=4) {
|
||||||
|
if(drect[0]>0.0f) drect[0]= sqrt(drect[0]); else drect[0]= 0.0f;
|
||||||
|
if(drect[1]>0.0f) drect[1]= sqrt(drect[1]); else drect[1]= 0.0f;
|
||||||
|
if(drect[2]>0.0f) drect[2]= sqrt(drect[2]); else drect[2]= 0.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for(x=img->x*img->y; x>0; x--, drect+=4) {
|
||||||
|
if(drect[0]>0.0f) drect[0]*= drect[0]; else drect[0]= 0.0f;
|
||||||
|
if(drect[1]>0.0f) drect[1]*= drect[1]; else drect[1]= 0.0f;
|
||||||
|
if(drect[2]>0.0f) drect[2]*= drect[2]; else drect[2]= 0.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
|
static float hexagon_filter(float fi, float fj)
|
||||||
|
{
|
||||||
|
fi= fabs(fi);
|
||||||
|
fj= fabs(fj);
|
||||||
|
|
||||||
|
if(fj>0.33f) {
|
||||||
|
fj= (fj-0.33f)/0.66f;
|
||||||
|
if(fi+fj>1.0f)
|
||||||
|
return 0.0f;
|
||||||
|
else
|
||||||
|
return 1.0f;
|
||||||
|
}
|
||||||
|
else return 1.0f;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* uses full filter, no horizontal/vertical optimize possible */
|
||||||
|
static void bokeh_single_image(CompBuf *new, CompBuf *img, float fac, NodeBlurData *nbd)
|
||||||
|
{
|
||||||
|
register float val;
|
||||||
|
float radxf, radyf;
|
||||||
|
float *gausstab, *dgauss;
|
||||||
|
int radx, rady, imgx= img->x, imgy= img->y;
|
||||||
|
int x, y;
|
||||||
|
int i, j;
|
||||||
|
float *src, *dest;
|
||||||
|
|
||||||
|
/* horizontal */
|
||||||
|
radx = fac*(float)nbd->sizex;
|
||||||
|
if(radx>imgx/2)
|
||||||
|
radx= imgx/2;
|
||||||
|
else if(radx<1)
|
||||||
|
radx= 1;
|
||||||
|
|
||||||
|
/* vertical */
|
||||||
|
rady = fac*(float)nbd->sizey;
|
||||||
|
if(rady>imgy/2)
|
||||||
|
rady= imgy/2;
|
||||||
|
else if(rady<1)
|
||||||
|
rady= 1;
|
||||||
|
|
||||||
|
radxf= (float)radx;
|
||||||
|
radyf= (float)rady;
|
||||||
|
|
||||||
|
/* create a full filter image */
|
||||||
|
gausstab= MEM_mallocT(sizeof(float)*radx*rady*4, "filter tab");
|
||||||
|
dgauss= gausstab;
|
||||||
|
val= 0.0f;
|
||||||
|
for(j=-rady; j<rady; j++) {
|
||||||
|
for(i=-radx; i<radx; i++, dgauss++) {
|
||||||
|
float fj= (float)j/radyf;
|
||||||
|
float fi= (float)i/radxf;
|
||||||
|
float dist= sqrt(fj*fj + fi*fi);
|
||||||
|
|
||||||
|
// *dgauss= hexagon_filter(fi, fj);
|
||||||
|
*dgauss= RE_filter_value(nbd->filtertype, 2.0f*dist - 1.0f);
|
||||||
|
|
||||||
|
val+= *dgauss;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val= 1.0f/val;
|
||||||
|
for(j= 4*radx*rady -1; j>=0; j--)
|
||||||
|
gausstab[j]*= val;
|
||||||
|
|
||||||
|
|
||||||
|
/* vars to store before we go */
|
||||||
|
// refd= ref->rect;
|
||||||
|
src= img->rect;
|
||||||
|
|
||||||
|
memset(new->rect, 4*imgx*imgy, 0);
|
||||||
|
|
||||||
|
for (y = 0; y < imgy; y++) {
|
||||||
|
for (x = 0; x < imgx ; x++, src+=4) {//, refd++) {
|
||||||
|
int minxr= x-radx<0?-x:-radx;
|
||||||
|
int maxxr= x+radx>imgx?imgx-x:radx;
|
||||||
|
int minyr= y-rady<0?-y:-rady;
|
||||||
|
int maxyr= y+rady>imgy?imgy-y:rady;
|
||||||
|
|
||||||
|
float *destd= new->rect + 4*( (y + minyr)*imgx + x + minxr);
|
||||||
|
|
||||||
|
float *dgausd= gausstab + (minyr+rady)*2*radx + minxr+radx;
|
||||||
|
|
||||||
|
for (i= minyr; i < maxyr; i++, destd+= 4*imgx, dgausd+= 2*radx) {
|
||||||
|
dest= destd;
|
||||||
|
dgauss= dgausd;
|
||||||
|
for (j= minxr; j < maxxr; j++, dest+=4, dgauss++) {
|
||||||
|
|
||||||
|
val= *dgauss;
|
||||||
|
dest[0] += val * src[0];
|
||||||
|
dest[1] += val * src[1];
|
||||||
|
dest[2] += val * src[2];
|
||||||
|
dest[3] += val * src[3];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_freeT(gausstab);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* reference has to be mapped 0-1, and equal in size */
|
/* 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)
|
static void blur_with_reference(CompBuf *new, CompBuf *img, CompBuf *ref, NodeBlurData *nbd)
|
||||||
{
|
{
|
||||||
CompBuf *blurbuf;
|
CompBuf *blurbuf;
|
||||||
register float sum, val;
|
register float sum, val;
|
||||||
@@ -1804,17 +1933,17 @@ static void blur_with_reference(CompBuf *new, CompBuf *img, CompBuf *ref, float
|
|||||||
else blurd[0]= refd[0];
|
else blurd[0]= refd[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
blur_single_image(blurbuf, blurbuf, blurx, blury);
|
blur_single_image(blurbuf, blurbuf, 1.0f, nbd);
|
||||||
|
|
||||||
/* horizontal */
|
/* horizontal */
|
||||||
radx = ceil(blurx);
|
radx = (float)nbd->sizex;
|
||||||
if(radx>imgx/2)
|
if(radx>imgx/2)
|
||||||
radx= imgx/2;
|
radx= imgx/2;
|
||||||
else if(radx<1)
|
else if(radx<1)
|
||||||
radx= 1;
|
radx= 1;
|
||||||
|
|
||||||
/* vertical */
|
/* vertical */
|
||||||
rady = ceil(blury);
|
rady = (float)nbd->sizey;
|
||||||
if(rady>imgy/2)
|
if(rady>imgy/2)
|
||||||
rady= imgy/2;
|
rady= imgy/2;
|
||||||
else if(rady<1)
|
else if(rady<1)
|
||||||
@@ -1823,7 +1952,7 @@ static void blur_with_reference(CompBuf *new, CompBuf *img, CompBuf *ref, float
|
|||||||
x= MAX2(radx, rady);
|
x= MAX2(radx, rady);
|
||||||
maintabs= MEM_mallocT(x*sizeof(void *), "gauss array");
|
maintabs= MEM_mallocT(x*sizeof(void *), "gauss array");
|
||||||
for(i= 0; i<x; i++)
|
for(i= 0; i<x; i++)
|
||||||
maintabs[i]= make_gausstab(i+1);
|
maintabs[i]= make_gausstab(nbd->filtertype, i+1);
|
||||||
|
|
||||||
refd= blurbuf->rect;
|
refd= blurbuf->rect;
|
||||||
dest= new->rect;
|
dest= new->rect;
|
||||||
@@ -1906,7 +2035,7 @@ static void node_composit_exec_blur(void *data, bNode *node, bNodeStack **in, bN
|
|||||||
/* make output size of input image */
|
/* make output size of input image */
|
||||||
new= alloc_compbuf(img->x, img->y, CB_RGBA, 1); // allocs
|
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);
|
blur_with_reference(new, img, in[1]->data, node->storage);
|
||||||
|
|
||||||
out[0]->data= new;
|
out[0]->data= new;
|
||||||
}
|
}
|
||||||
@@ -1917,19 +2046,35 @@ static void node_composit_exec_blur(void *data, bNode *node, bNodeStack **in, bN
|
|||||||
new->rect= img->rect;
|
new->rect= img->rect;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
NodeBlurData *nbd= node->storage;
|
||||||
|
CompBuf *gammabuf;
|
||||||
|
|
||||||
/* make output size of input image */
|
/* make output size of input image */
|
||||||
new= alloc_compbuf(img->x, img->y, img->type, 1); // allocs
|
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);
|
if(nbd->gamma) {
|
||||||
|
gammabuf= dupalloc_compbuf(img);
|
||||||
|
gamma_correct_compbuf(gammabuf, 0);
|
||||||
|
}
|
||||||
|
else gammabuf= img;
|
||||||
|
|
||||||
|
if(nbd->bokeh)
|
||||||
|
bokeh_single_image(new, gammabuf, in[1]->vec[0], nbd);
|
||||||
|
else if(1)
|
||||||
|
blur_single_image(new, gammabuf, in[1]->vec[0], nbd);
|
||||||
else /* bloom experimental... */
|
else /* bloom experimental... */
|
||||||
bloom_with_reference(new, img, NULL, in[1]->vec[0]*(float)node->custom1, in[1]->vec[0]*(float)node->custom2);
|
bloom_with_reference(new, gammabuf, NULL, in[1]->vec[0], nbd);
|
||||||
|
|
||||||
|
if(nbd->gamma) {
|
||||||
|
gamma_correct_compbuf(new, 1);
|
||||||
|
free_compbuf(gammabuf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
out[0]->data= new;
|
out[0]->data= new;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* custom1 custom2 = blur filter size */
|
|
||||||
static bNodeType cmp_node_blur= {
|
static bNodeType cmp_node_blur= {
|
||||||
/* type code */ CMP_NODE_BLUR,
|
/* type code */ CMP_NODE_BLUR,
|
||||||
/* name */ "Blur",
|
/* name */ "Blur",
|
||||||
@@ -1937,7 +2082,7 @@ static bNodeType cmp_node_blur= {
|
|||||||
/* class+opts */ NODE_CLASS_OPERATOR, NODE_OPTIONS,
|
/* class+opts */ NODE_CLASS_OPERATOR, NODE_OPTIONS,
|
||||||
/* input sock */ cmp_node_blur_in,
|
/* input sock */ cmp_node_blur_in,
|
||||||
/* output sock */ cmp_node_blur_out,
|
/* output sock */ cmp_node_blur_out,
|
||||||
/* storage */ "",
|
/* storage */ "NodeBlurData",
|
||||||
/* execfunc */ node_composit_exec_blur
|
/* execfunc */ node_composit_exec_blur
|
||||||
|
|
||||||
};
|
};
|
||||||
@@ -1955,6 +2100,7 @@ static bNodeSocketType cmp_node_vecblur_out[]= {
|
|||||||
|
|
||||||
static void node_composit_exec_vecblur(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
|
static void node_composit_exec_vecblur(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
|
||||||
{
|
{
|
||||||
|
NodeBlurData nbd;
|
||||||
CompBuf *new, *img= in[0]->data, *vecbuf= in[1]->data, *wbuf;
|
CompBuf *new, *img= in[0]->data, *vecbuf= in[1]->data, *wbuf;
|
||||||
float *vect, *dest;
|
float *vect, *dest;
|
||||||
int x, y;
|
int x, y;
|
||||||
@@ -1984,7 +2130,8 @@ static void node_composit_exec_vecblur(void *data, bNode *node, bNodeStack **in,
|
|||||||
/* make output size of input image */
|
/* make output size of input image */
|
||||||
new= alloc_compbuf(img->x, img->y, CB_RGBA, 1); // allocs
|
new= alloc_compbuf(img->x, img->y, CB_RGBA, 1); // allocs
|
||||||
|
|
||||||
blur_with_reference(new, img, wbuf, 100.0f, 100.0f);
|
nbd.sizex= 100; nbd.sizey= 100; nbd.filtertype= R_FILTER_GAUSS;
|
||||||
|
blur_with_reference(new, img, wbuf, &nbd);
|
||||||
|
|
||||||
free_compbuf(wbuf);
|
free_compbuf(wbuf);
|
||||||
out[0]->data= new;
|
out[0]->data= new;
|
||||||
|
|||||||
@@ -3593,6 +3593,25 @@ static void bone_version_239(ListBase *lb)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ntree_version_241(bNodeTree *ntree)
|
||||||
|
{
|
||||||
|
bNode *node;
|
||||||
|
|
||||||
|
if(ntree->type==NTREE_COMPOSIT) {
|
||||||
|
for(node= ntree->nodes.first; node; node= node->next) {
|
||||||
|
if(node->type==CMP_NODE_BLUR) {
|
||||||
|
if(node->storage==NULL) {
|
||||||
|
NodeBlurData *nbd= MEM_callocN(sizeof(NodeBlurData), "node blur patch");
|
||||||
|
nbd->sizex= node->custom1;
|
||||||
|
nbd->sizey= node->custom2;
|
||||||
|
nbd->filtertype= R_FILTER_QUAD;
|
||||||
|
node->storage= nbd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void do_versions(FileData *fd, Library *lib, Main *main)
|
static void do_versions(FileData *fd, Library *lib, Main *main)
|
||||||
{
|
{
|
||||||
/* WATCH IT!!!: pointers from libdata have not been converted */
|
/* WATCH IT!!!: pointers from libdata have not been converted */
|
||||||
@@ -5253,6 +5272,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
|
|||||||
if(main->versionfile <= 241) {
|
if(main->versionfile <= 241) {
|
||||||
Scene *sce;
|
Scene *sce;
|
||||||
bArmature *arm;
|
bArmature *arm;
|
||||||
|
bNodeTree *ntree;
|
||||||
|
|
||||||
/* updating layers still */
|
/* updating layers still */
|
||||||
for(arm= main->armature.first; arm; arm= arm->id.next) {
|
for(arm= main->armature.first; arm; arm= arm->id.next) {
|
||||||
@@ -5265,7 +5285,14 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
|
|||||||
/* adds default layer */
|
/* adds default layer */
|
||||||
if(sce->r.layers.first==NULL)
|
if(sce->r.layers.first==NULL)
|
||||||
scene_add_render_layer(sce);
|
scene_add_render_layer(sce);
|
||||||
|
/* node version changes */
|
||||||
|
if(sce->nodetree)
|
||||||
|
ntree_version_241(sce->nodetree);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for(ntree= main->nodetree.first; ntree; ntree= ntree->id.next)
|
||||||
|
ntree_version_241(ntree);
|
||||||
|
|
||||||
//Object *ob;
|
//Object *ob;
|
||||||
|
|
||||||
/* for empty drawsize and drawtype */
|
/* for empty drawsize and drawtype */
|
||||||
|
|||||||
@@ -185,5 +185,11 @@ typedef struct NodeImageAnim {
|
|||||||
char cyclic, movie;
|
char cyclic, movie;
|
||||||
} NodeImageAnim;
|
} NodeImageAnim;
|
||||||
|
|
||||||
|
typedef struct NodeBlurData {
|
||||||
|
short sizex, sizey;
|
||||||
|
short filtertype;
|
||||||
|
char bokeh, gamma;
|
||||||
|
} NodeBlurData;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -171,8 +171,8 @@ void RE_test_break_cb (struct Render *re, int (*f)(void));
|
|||||||
void RE_test_return_cb (struct Render *re, int (*f)(void));
|
void RE_test_return_cb (struct Render *re, int (*f)(void));
|
||||||
void RE_error_cb (struct Render *re, void (*f)(const char *str));
|
void RE_error_cb (struct Render *re, void (*f)(const char *str));
|
||||||
|
|
||||||
|
/* should move to kernel once... still unsure on how/where */
|
||||||
|
float RE_filter_value(int type, float x);
|
||||||
|
|
||||||
#endif /* RE_PIPELINE_H */
|
#endif /* RE_PIPELINE_H */
|
||||||
|
|
||||||
|
|||||||
@@ -153,6 +153,41 @@ static float filt_mitchell(float x) /* Mitchell & Netravali's two-param cubic */
|
|||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* x ranges from -1 to 1 */
|
||||||
|
float RE_filter_value(int type, float x)
|
||||||
|
{
|
||||||
|
float gaussfac= 1.6f;
|
||||||
|
|
||||||
|
x= ABS(x);
|
||||||
|
|
||||||
|
switch(type) {
|
||||||
|
case R_FILTER_BOX:
|
||||||
|
if(x>1.0) return 0.0f;
|
||||||
|
return 1.0;
|
||||||
|
|
||||||
|
case R_FILTER_TENT:
|
||||||
|
if(x>1.0) return 0.0f;
|
||||||
|
return 1.0f-x;
|
||||||
|
|
||||||
|
case R_FILTER_GAUSS:
|
||||||
|
x*= gaussfac;
|
||||||
|
return (1.0/exp(x*x) - 1.0/exp(gaussfac*gaussfac*2.25));
|
||||||
|
|
||||||
|
case R_FILTER_MITCH:
|
||||||
|
return filt_mitchell(x*gaussfac);
|
||||||
|
|
||||||
|
case R_FILTER_QUAD:
|
||||||
|
return filt_quadratic(x*gaussfac);
|
||||||
|
|
||||||
|
case R_FILTER_CUBIC:
|
||||||
|
return filt_cubic(x*gaussfac);
|
||||||
|
|
||||||
|
case R_FILTER_CATROM:
|
||||||
|
return filt_catrom(x*gaussfac);
|
||||||
|
}
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
static float calc_weight(Render *re, float *weight, int i, int j)
|
static float calc_weight(Render *re, float *weight, int i, int j)
|
||||||
{
|
{
|
||||||
float x, y, dist, totw= 0.0;
|
float x, y, dist, totw= 0.0;
|
||||||
|
|||||||
@@ -699,17 +699,34 @@ static int node_composit_buts_renderresult(uiBlock *block, bNodeTree *ntree, bNo
|
|||||||
static int node_composit_buts_blur(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
|
static int node_composit_buts_blur(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
|
||||||
{
|
{
|
||||||
if(block) {
|
if(block) {
|
||||||
|
NodeBlurData *nbd= node->storage;
|
||||||
uiBut *bt;
|
uiBut *bt;
|
||||||
|
short dy= butr->ymin+19;
|
||||||
|
short dx= (butr->xmax-butr->xmin)/2;
|
||||||
|
short dx3=(butr->xmax-butr->xmin)/3;
|
||||||
|
char str[256];
|
||||||
|
|
||||||
uiBlockBeginAlign(block);
|
uiBlockBeginAlign(block);
|
||||||
|
sprintf(str, "Filter Type%%t|Flat %%x%d|Tent %%x%d|Quad %%x%d|Cubic %%x%d|Gauss %%x%d|CatRom %%x%d|Mitch %%x%d", R_FILTER_BOX, R_FILTER_TENT, R_FILTER_QUAD, R_FILTER_CUBIC, R_FILTER_GAUSS, R_FILTER_CATROM, R_FILTER_MITCH);
|
||||||
|
uiDefButS(block, MENU, B_NODE_EXEC,str,
|
||||||
|
butr->xmin, dy, dx3, 19,
|
||||||
|
&nbd->filtertype, 0, 0, 0, 0, "Set sampling filter for blur");
|
||||||
|
uiDefButC(block, TOG, B_NODE_EXEC, "Bokeh",
|
||||||
|
butr->xmin+dx3, dy, dx3, 19,
|
||||||
|
&nbd->bokeh, 0, 0, 0, 0, "Uses circular filter, warning it's slow!");
|
||||||
|
uiDefButC(block, TOG, B_NODE_EXEC, "Gamma",
|
||||||
|
butr->xmin+2*dx3, dy, dx3, 19,
|
||||||
|
&nbd->gamma, 0, 0, 0, 0, "Applies filter on gamma corrected values");
|
||||||
|
|
||||||
|
dy-=19;
|
||||||
bt=uiDefButS(block, NUM, B_NODE_EXEC+node->nr, "X:",
|
bt=uiDefButS(block, NUM, B_NODE_EXEC+node->nr, "X:",
|
||||||
butr->xmin, butr->ymin, (butr->xmax-butr->xmin)/2, 19,
|
butr->xmin, dy, dx, 19,
|
||||||
&node->custom1, 0, 256, 0, 0, "");
|
&nbd->sizex, 0, 256, 0, 0, "");
|
||||||
bt=uiDefButS(block, NUM, B_NODE_EXEC+node->nr, "Y:",
|
bt=uiDefButS(block, NUM, B_NODE_EXEC+node->nr, "Y:",
|
||||||
butr->xmin+(butr->xmax-butr->xmin)/2, butr->ymin, (butr->xmax-butr->xmin)/2, 19,
|
butr->xmin+dx, dy, dx, 19,
|
||||||
&node->custom2, 0, 256, 0, 0, "");
|
&nbd->sizey, 0, 256, 0, 0, "");
|
||||||
}
|
}
|
||||||
return 19;
|
return 38;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int node_composit_buts_filter(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
|
static int node_composit_buts_filter(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
|
||||||
|
|||||||
Reference in New Issue
Block a user