Vector Blur now has option to be curved!

Especially for fast moving objects (as we have here in Peach) the
art department demanded nice curved vector blur. This formula uses
a quadratic bezier function, which is not giving perfect circles, but
certainly useful results.

Also on todo: get this blur code to do nicer accumulation...
This commit is contained in:
2008-01-21 18:08:57 +00:00
parent 14241f8349
commit 1357f1b09f
3 changed files with 65 additions and 12 deletions

View File

@@ -2762,6 +2762,37 @@ void antialias_tagbuf(int xsize, int ysize, char *rectmove)
}
}
/* in: two vectors, first vector points from origin back in time, 2nd vector points to future */
/* we make this into 3 points, center point is (0,0) */
/* and offset the center point just enough to make curve go through midpoint */
static void quad_bezier_2d(float *result, float *v1, float *v2, float *ipodata)
{
float p1[2], p2[2], p3[2];
p3[0]= -v2[0];
p3[1]= -v2[1];
p1[0]= v1[0];
p1[1]= v1[1];
/* official formula 2*p2 - .5*p1 - .5*p3 */
p2[0]= -0.5*p1[0] - 0.5*p3[0];
p2[1]= -0.5*p1[1] - 0.5*p3[1];
result[0]= ipodata[0]*p1[0] + ipodata[1]*p2[0] + ipodata[2]*p3[0];
result[1]= ipodata[0]*p1[1] + ipodata[1]*p2[1] + ipodata[2]*p3[1];
}
static void set_quad_bezier_ipo(float fac, float *data)
{
float mfac= (1.0f-fac);
data[0]= mfac*mfac;
data[1]= 2.0f*mfac*fac;
data[2]= fac*fac;
}
void RE_zbuf_accumulate_vecblur(NodeBlurData *nbd, int xsize, int ysize, float *newrect, float *imgrect, float *vecbufrect, float *zbufrect)
{
ZSpan zspan;
@@ -2960,7 +2991,7 @@ void RE_zbuf_accumulate_vecblur(NodeBlurData *nbd, int xsize, int ysize, float *
samples/= 2;
for(step= 1; step<=samples; step++) {
float speedfac= 0.5f*nbd->fac*(float)step/(float)(samples+1);
float blendfac= 1.0f/(ABS(step)+1);
float blendfac= 1.0f/(ABS(step)+1), ipodata[4];
int side, z= 4;
for(side=0; side<2; side++) {
@@ -2985,23 +3016,41 @@ void RE_zbuf_accumulate_vecblur(NodeBlurData *nbd, int xsize, int ysize, float *
dz2= rectvz + 5*(xsize + 1);
if(side) {
dz1+= 2;
dz2+= 2;
z= 2;
if(nbd->curved==0) {
dz1+= 2;
dz2+= 2;
z= 2;
}
speedfac= -speedfac;
}
set_quad_bezier_ipo(0.5f + 0.5f*speedfac, ipodata);
for(fy= -0.5f+jit[step & 15][0], y=0; y<ysize; y++, fy+=1.0f) {
for(fx= -0.5f+jit[step & 15][1], x=0; x<xsize; x++, fx+=1.0f, dimg+=4, dz1+=5, dz2+=5, dm++) {
if(*dm>1) {
DrawBufPixel col;
/* make vertices */
v1[0]= speedfac*dz1[0]+fx; v1[1]= speedfac*dz1[1]+fy; v1[2]= dz1[z];
v2[0]= speedfac*dz1[5]+fx+1.0f; v2[1]= speedfac*dz1[6]+fy; v2[2]= dz1[z+5];
v3[0]= speedfac*dz2[5]+fx+1.0f; v3[1]= speedfac*dz2[6]+fy+1.0f; v3[2]= dz2[z+5];
v4[0]= speedfac*dz2[0]+fx; v4[1]= speedfac*dz2[1]+fy+1.0f; v4[2]= dz2[z];
if(nbd->curved) { /* curved */
quad_bezier_2d(v1, dz1, dz1+2, ipodata);
v1[0]+= fx; v1[1]+= fy; v1[2]= dz1[4];
quad_bezier_2d(v2, dz1+5, dz1+5+2, ipodata);
v2[0]+= fx+1.0f; v2[1]+= fy; v2[2]= dz1[4+5];
quad_bezier_2d(v3, dz2+5, dz2+5+2, ipodata);
v3[0]+= fx+1.0f; v3[1]+= fy+1.0f; v3[2]= dz1[4+5];
quad_bezier_2d(v4, dz2, dz2+2, ipodata);
v4[0]+= fx; v4[1]+= fy+1.0f; v4[2]= dz2[4];
}
else {
v1[0]= speedfac*dz1[0]+fx; v1[1]= speedfac*dz1[1]+fy; v1[2]= dz1[z];
v2[0]= speedfac*dz1[5]+fx+1.0f; v2[1]= speedfac*dz1[6]+fy; v2[2]= dz1[z+5];
v3[0]= speedfac*dz2[5]+fx+1.0f; v3[1]= speedfac*dz2[6]+fy+1.0f; v3[2]= dz2[z+5];
v4[0]= speedfac*dz2[0]+fx; v4[1]= speedfac*dz2[1]+fy+1.0f; v4[2]= dz2[z];
}
if(*dm==255) col.alpha= 1.0f;
else if(*dm<2) col.alpha= 0.0f;
else col.alpha= ((float)*dm)/255.0f;