Tweak for Speed vector calculus for Ztransp render layer; it used to mask

out moving transparent pixels by checking for alpha>0.95, now it also
checks the solid layer (if present), and if there's no solid face in a
pixel, the speed vector gets also added and used for transparent pixels.

This solves the 'ugly' hard outlines for vectorblur of moving hair.

Before:
http://www.blender.org/bf/h1.jpg
After:
http://www.blender.org/bf/h2.jpg
This commit is contained in:
Ton Roosendaal 2006-02-23 11:16:16 +00:00
parent 8ab274ee30
commit 2c1a328f58
3 changed files with 53 additions and 50 deletions

@ -3117,6 +3117,7 @@ static void calculate_speedvectors(Render *re, float *vectors, int startvert, in
}
speed= RE_vertren_get_winspeed(re, ver, 1);
/* note; in main vecblur loop speedvec is negated again */
if(step) {
speed[2]= -zco[0];
speed[3]= -zco[1];
@ -3125,10 +3126,7 @@ static void calculate_speedvectors(Render *re, float *vectors, int startvert, in
speed[0]= zco[0];
speed[1]= zco[1];
}
//printf("speed %d %f %f\n", a, speed[0], speed[1]);
}
}
/* makes copy per object of all vectors */

@ -2749,10 +2749,8 @@ static void edge_enhance_add(RenderPart *pa, float *rectf, float *arect)
static void reset_sky_speedvectors(RenderPart *pa, RenderLayer *rl)
{
/* speed vector exception... if solid render was done, sky pixels are set to zero already */
/* for all pixels with alpha zero, we re-initialize speed again then */
if(rl->layflag & SCE_LAY_SOLID) {
float *fp, *col;
int a;
@ -2769,7 +2767,6 @@ static void reset_sky_speedvectors(RenderPart *pa, RenderLayer *rl)
}
}
}
}
/* osa version */
static void add_filt_passes(RenderLayer *rl, int curmask, int rectx, int offset, ShadeResult *shr)
@ -3140,6 +3137,7 @@ void zbufshadeDA_tile(RenderPart *pa)
int x;
if(rl->passflag & SCE_PASS_VECTOR)
if(rl->layflag & SCE_LAY_SOLID)
reset_sky_speedvectors(pa, rl);
/* swap for live updates */
@ -3252,6 +3250,7 @@ void zbufshade_tile(RenderPart *pa)
int x;
if(addpassflag & SCE_PASS_VECTOR)
if(rl->layflag & SCE_LAY_SOLID)
reset_sky_speedvectors(pa, rl);
/* swap for live updates */

@ -2236,7 +2236,7 @@ void RE_zbuf_accumulate_vecblur(NodeBlurData *nbd, int xsize, int ysize, float *
dm= rectmove;
dvec1= vecbufrect;
for(x=xsize*ysize; x>0; x--, dm++, dvec1+=4) {
if(dvec1[0]!=0.0f || dvec1[1]!=0.0f)
if(dvec1[0]!=0.0f || dvec1[1]!=0.0f || dvec1[2]!=0.0f || dvec1[3]!=0.0f)
*dm= 255;
}
@ -2484,9 +2484,10 @@ static void zbuffer_abuf(RenderPart *pa, APixstr *APixbuf, ListBase *apsmbase, u
}
/* different rules for speed in transparent pass... */
/* if speed is zero or alpha small, we clear winspeed if it's initialized to max still */
static void add_transp_speed(RenderLayer *rl, int offset, float *speed, float alpha)
/* speed pointer NULL = sky, we clear */
/* else if either alpha is full or no solid was filled in: copy speed */
/* else fill in minimum speed */
static void add_transp_speed(RenderLayer *rl, int offset, float *speed, float alpha, long *rdrect)
{
RenderPass *rpass;
@ -2494,16 +2495,28 @@ static void add_transp_speed(RenderLayer *rl, int offset, float *speed, float al
if(rpass->passtype==SCE_PASS_VECTOR) {
float *fp= rpass->rect + 4*offset;
if(speed && alpha>0.95f) {
QUATCOPY(fp, speed);
}
else {
if(speed==NULL) {
/* clear */
if(fp[0]==PASS_VECTOR_MAX) fp[0]= 0.0f;
if(fp[1]==PASS_VECTOR_MAX) fp[1]= 0.0f;
if(fp[2]==PASS_VECTOR_MAX) fp[2]= 0.0f;
if(fp[3]==PASS_VECTOR_MAX) fp[3]= 0.0f;
}
else if(rdrect==NULL || rdrect[offset]==0 || alpha>0.95f) {
QUATCOPY(fp, speed);
}
else {
/* add minimum speed in pixel */
if( (ABS(speed[0]) + ABS(speed[1]))< (ABS(fp[0]) + ABS(fp[1])) ) {
fp[0]= speed[0];
fp[1]= speed[1];
}
if( (ABS(speed[2]) + ABS(speed[3]))< (ABS(fp[2]) + ABS(fp[3])) ) {
fp[2]= speed[2];
fp[3]= speed[3];
}
}
}
}
}
@ -2636,7 +2649,8 @@ void zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pass)
APixstr *ap, *aprect, *apn;
ListBase apsmbase={NULL, NULL};
ShadeResult samp_shr[16];
float fac, alpha[32], *passrect= pass;
float fac, sampalpha, *passrect= pass;
long *rdrect;
int x, y, crop=0, a, zrow[MAX_ZROW][3], totface;
int sval, addpassflag, offs= 0, od, addzbuf;
@ -2663,24 +2677,22 @@ void zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pass)
addpassflag= rl->passflag & ~(SCE_PASS_Z|SCE_PASS_COMBINED);
addzbuf= rl->passflag & SCE_PASS_Z;
/* alpha LUT */
if(R.osa) {
fac= (1.0/(float)R.osa);
for(a=0; a<=R.osa; a++) {
alpha[a]= (float)a*fac;
}
}
if(R.osa)
sampalpha= 1.0f/(float)R.osa;
else
sampalpha= 1.0f;
/* fill the Apixbuf */
zbuffer_abuf(pa, APixbuf, &apsmbase, rl->lay);
aprect= APixbuf;
rdrect= pa->rectdaps;
/* filtered render, for now we assume only 1 filter size */
if(pa->crop) {
crop= 1;
passrect+= 4*(pa->rectx + 1);
aprect+= pa->rectx + 1;
offs= pa->rectx + 1;
passrect+= 4*offs;
aprect+= offs;
}
/* init scanline updates */
@ -2701,7 +2713,7 @@ void zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pass)
if(ap->p[0]==NULL) {
if(addpassflag & SCE_PASS_VECTOR)
add_transp_speed(rl, od, NULL, 0.0f);
add_transp_speed(rl, od, NULL, 0.0f, rdrect);
}
else {
/* sort in z */
@ -2736,7 +2748,7 @@ void zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pass)
add_transp_passes(rl, od, &shpi.shr, 1.0f);
if(addpassflag & SCE_PASS_VECTOR)
add_transp_speed(rl, od, shpi.shr.winspeed, pass[3]);
add_transp_speed(rl, od, shpi.shr.winspeed, pass[3], rdrect);
if(addzbuf)
if(pa->rectz[od]>zrow[0][0])
@ -2772,7 +2784,7 @@ void zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pass)
if(pass[3]>=0.999) break;
}
if(addpassflag & SCE_PASS_VECTOR)
add_transp_speed(rl, od, shpi.shr.winspeed, pass[3]);
add_transp_speed(rl, od, shpi.shr.winspeed, pass[3], rdrect);
}
else {
/* for each mask-sample we alpha-under colors. then in end it's added using filter */
@ -2791,23 +2803,17 @@ void zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pass)
add_filt_fmask(1<<a, samp_shr[a].combined, pass, rr->rectx);
if(addpassflag)
add_transp_passes(rl, od, samp_shr+a, alpha[1]);
add_transp_passes(rl, od, samp_shr+a, sampalpha);
}
if(addpassflag & SCE_PASS_VECTOR) {
fac= 0.0f;
for(a=0; a<R.osa; a++)
fac+= samp_shr[a].combined[3];
fac*= alpha[1];
add_transp_speed(rl, od, samp_shr[0].winspeed, fac);
add_transp_speed(rl, od, samp_shr[0].winspeed, fac*sampalpha, rdrect);
}
}
}
//if(R.osa && R.do_gamma) {
// pass[0]= invGammaCorrect(pass[0]);
// pass[1]= invGammaCorrect(pass[1]);
// pass[2]= invGammaCorrect(pass[2]);
//}
}
}