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;
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue