rasterize: continue formulating new triangle engine into a form that will be easier to extend to quads
This commit is contained in:
parent
e7c46f12a0
commit
a1ea7c6c62
|
@ -567,6 +567,25 @@ void scanline(int y, int xstart, int xend,
|
|||
|
||||
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 ) {
|
||||
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 {
|
||||
edge_fx_fl(gradients_fx_fl const &Gradients, VERT **pVertices, int Top,
|
||||
int Bottom );
|
||||
edge_fx_fl(VERT **pVertices, int Top, int Bottom );
|
||||
inline int Step( void );
|
||||
|
||||
long X, XStep, Numerator, Denominator; // DDA info for x
|
||||
|
@ -634,7 +645,14 @@ struct edge_fx_fl {
|
|||
float curr, step, stepExtra;
|
||||
void doStep() { curr += step; }
|
||||
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
|
||||
+ XPrestep * gradient.dx;
|
||||
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(); }
|
||||
};
|
||||
|
||||
inline int edge_fx_fl::Step( void ) {
|
||||
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 )
|
||||
edge_fx_fl::edge_fx_fl( VERT **verts, int Top, int Bottom )
|
||||
{
|
||||
Y = Ceil28_4(verts[Top]->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 XPrestep = Fixed28_4ToFloat(X*16 - verts[Top]->x);
|
||||
|
||||
invw.initialize(Gradients.invw[Top],XStep,XPrestep,YPrestep,Gradients.d.invw);
|
||||
u.initialize(verts[Top]->u,XStep,XPrestep,YPrestep,Gradients.d.u);
|
||||
v.initialize(verts[Top]->v,XStep,XPrestep,YPrestep,Gradients.d.v);
|
||||
z.initialize(verts[Top]->z,XStep,XPrestep,YPrestep,Gradients.d.z);
|
||||
|
||||
float dy = 1/Fixed28_4ToFloat(dN);
|
||||
float dx = 1/Fixed28_4ToFloat(dM);
|
||||
|
||||
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++)
|
||||
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 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[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,
|
||||
|
||||
int adr = (pLeft->Y<<8)+XStart;
|
||||
|
||||
while(Width-- > 0)
|
||||
{
|
||||
float W = 1/invw;
|
||||
|
||||
pixel(adr,color[0],color[1],color[2],u,v,invw,z);
|
||||
adr++;
|
||||
|
||||
invw += Gradients.d.invw.dx;
|
||||
u += Gradients.d.u.dx;
|
||||
v += Gradients.d.v.dx;
|
||||
z += Gradients.d.z.dx;
|
||||
for(int i=0;i<3;i++) color[i] += Gradients.d.color[i].dx;
|
||||
invw += dinvw_dx;
|
||||
u += du_dx;
|
||||
v += dv_dx;
|
||||
z += dz_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);
|
||||
while(Height--) {
|
||||
hecker_DrawScanLine(gradients,left,right);
|
||||
left->Step(); right->Step();
|
||||
hecker_DrawScanLine(left,right);
|
||||
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;
|
||||
|
||||
gradients_fx_fl Gradients((const VERT**)v);
|
||||
|
||||
if(Y0 == Y1)
|
||||
{
|
||||
//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 edge2 = edge_fx_fl(Gradients,v,1,2);
|
||||
runscanline(Gradients,&edge1,&edge2);
|
||||
edge_fx_fl edge1 = edge_fx_fl(v,0,2);
|
||||
edge_fx_fl edge2 = edge_fx_fl(v,1,2);
|
||||
runscanline(&edge1,&edge2);
|
||||
}
|
||||
else if(Y1 == Y2)
|
||||
{
|
||||
//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 edge2 = edge_fx_fl(Gradients,v,0,1);
|
||||
runscanline(Gradients,&edge1,&edge2);
|
||||
edge_fx_fl edge1 = edge_fx_fl(v,0,2);
|
||||
edge_fx_fl edge2 = edge_fx_fl(v,0,1);
|
||||
runscanline(&edge1,&edge2);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -836,11 +818,11 @@ static void triangle_from_hecker()
|
|||
// 0
|
||||
// 1
|
||||
//2
|
||||
edge_fx_fl edge1 = edge_fx_fl(Gradients,v,0,2);
|
||||
edge_fx_fl edge2 = edge_fx_fl(Gradients,v,0,1);
|
||||
runscanline(Gradients,&edge1,&edge2);
|
||||
edge2 = edge_fx_fl(Gradients,v,1,2);
|
||||
runscanline(Gradients,&edge1,&edge2);
|
||||
edge_fx_fl edge1 = edge_fx_fl(v,0,2);
|
||||
edge_fx_fl edge2 = edge_fx_fl(v,0,1);
|
||||
runscanline(&edge1,&edge2);
|
||||
edge2 = edge_fx_fl(v,1,2);
|
||||
runscanline(&edge1,&edge2);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -848,11 +830,11 @@ static void triangle_from_hecker()
|
|||
// 0
|
||||
//2
|
||||
// 1
|
||||
edge_fx_fl edge1 = edge_fx_fl(Gradients,v,0,2);
|
||||
edge_fx_fl edge2 = edge_fx_fl(Gradients,v,0,1);
|
||||
runscanline(Gradients,&edge1,&edge2);
|
||||
edge1 = edge_fx_fl(Gradients,v,2,1);
|
||||
runscanline(Gradients,&edge1,&edge2);
|
||||
edge_fx_fl edge1 = edge_fx_fl(v,0,2);
|
||||
edge_fx_fl edge2 = edge_fx_fl(v,0,1);
|
||||
runscanline(&edge1,&edge2);
|
||||
edge1 = edge_fx_fl(v,2,1);
|
||||
runscanline(&edge1,&edge2);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue