rasterize: continue formulating new triangle engine into a form that will be easier to extend to quads

This commit is contained in:
zeromus 2009-02-27 04:01:26 +00:00
parent e7c46f12a0
commit a1ea7c6c62
1 changed files with 90 additions and 108 deletions

View File

@ -567,6 +567,25 @@ void scanline(int y, int xstart, int xend,
typedef int fixed28_4; typedef int fixed28_4;
// handle floor divides and mods correctly
inline void FloorDivMod( long Numerator, long Denominator, long &Floor, long &Mod )
{
assert(Denominator > 0); // we assume it's positive
if(Numerator >= 0) {
// positive case, C is okay
Floor = Numerator / Denominator;
Mod = Numerator % Denominator;
} else {
// Numerator is negative, do the right thing
Floor = -((-Numerator) / Denominator);
Mod = (-Numerator) % Denominator;
if(Mod) {
// there is a remainder
Floor--; Mod = Denominator - Mod;
}
}
}
inline fixed28_4 FloatToFixed28_4( float Value ) { inline fixed28_4 FloatToFixed28_4( float Value ) {
return Value * 16; return Value * 16;
} }
@ -613,17 +632,9 @@ struct Derivatives {
} }
}; };
struct gradients_fx_fl {
gradients_fx_fl( const VERT **pVertices );
float invw[3];
struct GradientDerivatives {
Derivatives invw, z, u, v, color[3];
} d;
};
struct edge_fx_fl { struct edge_fx_fl {
edge_fx_fl(gradients_fx_fl const &Gradients, VERT **pVertices, int Top, edge_fx_fl(VERT **pVertices, int Top, int Bottom );
int Bottom );
inline int Step( void ); inline int Step( void );
long X, XStep, Numerator, Denominator; // DDA info for x long X, XStep, Numerator, Denominator; // DDA info for x
@ -634,7 +645,14 @@ struct edge_fx_fl {
float curr, step, stepExtra; float curr, step, stepExtra;
void doStep() { curr += step; } void doStep() { curr += step; }
void doStepExtra() { curr += stepExtra; } void doStepExtra() { curr += stepExtra; }
void initialize(float val, long XStep, float XPrestep, float YPrestep, const Derivatives& gradient) { void initialize(float top, float bottom, float dx, float dy, long XStep, float XPrestep, float YPrestep) {
dx = 0;
dy *= (bottom-top);
curr = top + YPrestep * dy + XPrestep * dx;
step = XStep * dx + dy;
stepExtra = dx;
}
void old_initialize(float val, long XStep, float XPrestep, float YPrestep, const Derivatives& gradient) {
curr = val + YPrestep * gradient.dy curr = val + YPrestep * gradient.dy
+ XPrestep * gradient.dx; + XPrestep * gradient.dx;
step = XStep * gradient.dx + gradient.dy; step = XStep * gradient.dx + gradient.dy;
@ -653,69 +671,7 @@ struct edge_fx_fl {
void doStepExtraInterpolants() { for(int i=0;i<NUM_INTERPOLANTS;i++) interpolants[i].doStepExtra(); } void doStepExtraInterpolants() { for(int i=0;i<NUM_INTERPOLANTS;i++) interpolants[i].doStepExtra(); }
}; };
inline int edge_fx_fl::Step( void ) { edge_fx_fl::edge_fx_fl( VERT **verts, int Top, int Bottom )
X += XStep; Y++; Height--;
doStepInterpolants();
ErrorTerm += Numerator;
if(ErrorTerm >= Denominator) {
X++;
ErrorTerm -= Denominator;
doStepExtraInterpolants();
}
return Height;
}
gradients_fx_fl::gradients_fx_fl( const VERT **verts )
{
int Counter;
fixed28_4 X1Y0 = Fixed28_4Mul(verts[1]->x - verts[2]->x,
verts[0]->y - verts[2]->y);
fixed28_4 X0Y1 = Fixed28_4Mul(verts[0]->x - verts[2]->x,
verts[1]->y - verts[2]->y);
float invdx = 1.0 / Fixed28_4ToFloat(X1Y0 - X0Y1);
float invdy = -invdx;
for(int i=0;i<3;i++) invw[i] = 1/verts[i]->w;
d.invw.calculate(invw[0],invw[1],invw[2],invdx,invdy,verts);
d.u.calculate(verts[0]->u,verts[1]->u,verts[2]->u,invdx,invdy,verts);
d.v.calculate(verts[0]->v,verts[1]->v,verts[2]->v,invdx,invdy,verts);
d.z.calculate(verts[0]->z,verts[1]->z,verts[2]->z,invdx,invdy,verts);
for(int i=0;i<3;i++)
d.color[i].calculate(verts[0]->fcolor[i],verts[1]->fcolor[i],verts[2]->fcolor[i],invdx,invdy,verts);
}
/********** handle floor divides and mods correctly ***********/
inline void FloorDivMod( long Numerator, long Denominator, long &Floor,
long &Mod )
{
assert(Denominator > 0); // we assume it's positive
if(Numerator >= 0) {
// positive case, C is okay
Floor = Numerator / Denominator;
Mod = Numerator % Denominator;
} else {
// Numerator is negative, do the right thing
Floor = -((-Numerator) / Denominator);
Mod = (-Numerator) % Denominator;
if(Mod) {
// there is a remainder
Floor--; Mod = Denominator - Mod;
}
}
}
/********** edge_fx_fl constructor ***********/
edge_fx_fl::edge_fx_fl( gradients_fx_fl const &Gradients, VERT **verts, int Top,
int Bottom )
{ {
Y = Ceil28_4(verts[Top]->y); Y = Ceil28_4(verts[Top]->y);
int YEnd = Ceil28_4(verts[Bottom]->y); int YEnd = Ceil28_4(verts[Bottom]->y);
@ -733,18 +689,36 @@ edge_fx_fl::edge_fx_fl( gradients_fx_fl const &Gradients, VERT **verts, int Top,
float YPrestep = Fixed28_4ToFloat(Y*16 - verts[Top]->y); float YPrestep = Fixed28_4ToFloat(Y*16 - verts[Top]->y);
float XPrestep = Fixed28_4ToFloat(X*16 - verts[Top]->x); float XPrestep = Fixed28_4ToFloat(X*16 - verts[Top]->x);
invw.initialize(Gradients.invw[Top],XStep,XPrestep,YPrestep,Gradients.d.invw); float dy = 1/Fixed28_4ToFloat(dN);
u.initialize(verts[Top]->u,XStep,XPrestep,YPrestep,Gradients.d.u); float dx = 1/Fixed28_4ToFloat(dM);
v.initialize(verts[Top]->v,XStep,XPrestep,YPrestep,Gradients.d.v);
z.initialize(verts[Top]->z,XStep,XPrestep,YPrestep,Gradients.d.z); invw.initialize(1/verts[Top]->w,1/verts[Bottom]->w,dx,dy,XStep,XPrestep,YPrestep);
u.initialize(verts[Top]->u,verts[Bottom]->u,dx,dy,XStep,XPrestep,YPrestep);
v.initialize(verts[Top]->v,verts[Bottom]->v,dx,dy,XStep,XPrestep,YPrestep);
z.initialize(verts[Top]->z,verts[Bottom]->z,dx,dy,XStep,XPrestep,YPrestep);
for(int i=0;i<3;i++) for(int i=0;i<3;i++)
color[i].initialize(verts[Top]->fcolor[i],XStep,XPrestep,YPrestep,Gradients.d.color[i]); color[i].initialize(verts[Top]->fcolor[i],verts[Bottom]->fcolor[i],dx,dy,XStep,XPrestep,YPrestep);
} }
} }
inline int edge_fx_fl::Step( void ) {
X += XStep; Y++; Height--;
doStepInterpolants();
void hecker_DrawScanLine( gradients_fx_fl const &Gradients,edge_fx_fl *pLeft, edge_fx_fl *pRight ) ErrorTerm += Numerator;
if(ErrorTerm >= Denominator) {
X++;
ErrorTerm -= Denominator;
doStepExtraInterpolants();
}
return Height;
}
void hecker_DrawScanLine( edge_fx_fl *pLeft, edge_fx_fl *pRight )
{ {
int XStart = pLeft->X; int XStart = pLeft->X;
int Width = pRight->X - XStart; int Width = pRight->X - XStart;
@ -763,31 +737,41 @@ void hecker_DrawScanLine( gradients_fx_fl const &Gradients,edge_fx_fl *pLeft, ed
pLeft->color[1].curr, pLeft->color[1].curr,
pLeft->color[2].curr }; pLeft->color[2].curr };
float invWidth = 1.0f / Width;
float dinvw_dx = (pRight->invw.curr - invw) * invWidth;
float du_dx = (pRight->u.curr - u) * invWidth;
float dv_dx = (pRight->v.curr - v) * invWidth;
float dz_dx = (pRight->z.curr - z) * invWidth;
float dc_dx[3] = {
(pRight->color[0].curr - color[0]) * invWidth,
(pRight->color[1].curr - color[1]) * invWidth,
(pRight->color[2].curr - color[2]) * invWidth };
//scanline(pLeft->Y,pLeft->X,pRight->X,31,31,31,0,0,0,1/pLeft->OneOverZ,31,31,31,0,0, //scanline(pLeft->Y,pLeft->X,pRight->X,31,31,31,0,0,0,1/pLeft->OneOverZ,31,31,31,0,0,
int adr = (pLeft->Y<<8)+XStart; int adr = (pLeft->Y<<8)+XStart;
while(Width-- > 0) while(Width-- > 0)
{ {
float W = 1/invw;
pixel(adr,color[0],color[1],color[2],u,v,invw,z); pixel(adr,color[0],color[1],color[2],u,v,invw,z);
adr++; adr++;
invw += Gradients.d.invw.dx; invw += dinvw_dx;
u += Gradients.d.u.dx; u += du_dx;
v += Gradients.d.v.dx; v += dv_dx;
z += Gradients.d.z.dx; z += dz_dx;
for(int i=0;i<3;i++) color[i] += Gradients.d.color[i].dx; for(int i=0;i<3;i++) color[i] += dc_dx[i];
} }
} }
static void runscanline(gradients_fx_fl & gradients, edge_fx_fl *left, edge_fx_fl *right) static void runscanline(edge_fx_fl *left, edge_fx_fl *right)
{ {
int Height = min(left->Height,right->Height); int Height = min(left->Height,right->Height);
while(Height--) { while(Height--) {
hecker_DrawScanLine(gradients,left,right); hecker_DrawScanLine(left,right);
left->Step(); right->Step(); left->Step();
right->Step();
} }
} }
@ -811,21 +795,19 @@ static void triangle_from_hecker()
fixed28_4 Y0 = v[0]->y, Y1 = v[1]->y, Y2 = v[2]->y; fixed28_4 Y0 = v[0]->y, Y1 = v[1]->y, Y2 = v[2]->y;
gradients_fx_fl Gradients((const VERT**)v);
if(Y0 == Y1) if(Y0 == Y1)
{ {
//if the first two points have the same y-coord, then there is only one pair of edges //if the first two points have the same y-coord, then there is only one pair of edges
edge_fx_fl edge1 = edge_fx_fl(Gradients,v,0,2); edge_fx_fl edge1 = edge_fx_fl(v,0,2);
edge_fx_fl edge2 = edge_fx_fl(Gradients,v,1,2); edge_fx_fl edge2 = edge_fx_fl(v,1,2);
runscanline(Gradients,&edge1,&edge2); runscanline(&edge1,&edge2);
} }
else if(Y1 == Y2) else if(Y1 == Y2)
{ {
//if the last two points have the same y-coord then there is only one pair of edges //if the last two points have the same y-coord then there is only one pair of edges
edge_fx_fl edge1 = edge_fx_fl(Gradients,v,0,2); edge_fx_fl edge1 = edge_fx_fl(v,0,2);
edge_fx_fl edge2 = edge_fx_fl(Gradients,v,0,1); edge_fx_fl edge2 = edge_fx_fl(v,0,1);
runscanline(Gradients,&edge1,&edge2); runscanline(&edge1,&edge2);
} }
else else
{ {
@ -836,11 +818,11 @@ static void triangle_from_hecker()
// 0 // 0
// 1 // 1
//2 //2
edge_fx_fl edge1 = edge_fx_fl(Gradients,v,0,2); edge_fx_fl edge1 = edge_fx_fl(v,0,2);
edge_fx_fl edge2 = edge_fx_fl(Gradients,v,0,1); edge_fx_fl edge2 = edge_fx_fl(v,0,1);
runscanline(Gradients,&edge1,&edge2); runscanline(&edge1,&edge2);
edge2 = edge_fx_fl(Gradients,v,1,2); edge2 = edge_fx_fl(v,1,2);
runscanline(Gradients,&edge1,&edge2); runscanline(&edge1,&edge2);
} }
else else
{ {
@ -848,11 +830,11 @@ static void triangle_from_hecker()
// 0 // 0
//2 //2
// 1 // 1
edge_fx_fl edge1 = edge_fx_fl(Gradients,v,0,2); edge_fx_fl edge1 = edge_fx_fl(v,0,2);
edge_fx_fl edge2 = edge_fx_fl(Gradients,v,0,1); edge_fx_fl edge2 = edge_fx_fl(v,0,1);
runscanline(Gradients,&edge1,&edge2); runscanline(&edge1,&edge2);
edge1 = edge_fx_fl(Gradients,v,2,1); edge1 = edge_fx_fl(v,2,1);
runscanline(Gradients,&edge1,&edge2); runscanline(&edge1,&edge2);
} }
} }