add a hotkey to switch gpu cores. add a new triangle rasterizer (currently disabled) which should yield more accurate results once we wrestle with it some more. split the pixel ops out of the rasterizer so that it can be worked on mostly independently.

This commit is contained in:
zeromus 2009-02-25 09:57:06 +00:00
parent 33ec203f93
commit b804bd6ebc
7 changed files with 540 additions and 165 deletions

View File

@ -54,21 +54,22 @@ template<typename T>
inline T SIGNED_UNDERFLOW(T a,T b,T c) { return ((BIT31(a)&BIT31(~(b))&BIT31(~c))| inline T SIGNED_UNDERFLOW(T a,T b,T c) { return ((BIT31(a)&BIT31(~(b))&BIT31(~c))|
(BIT31(~a)&BIT31(b)&BIT31(c))); } (BIT31(~a)&BIT31(b)&BIT31(c))); }
#define EQ 0x0 //zero 15-feb-2009 - these werent getting used and they were getting in my way
#define NE 0x1 //#define EQ 0x0
#define CS 0x2 //#define NE 0x1
#define CC 0x3 //#define CS 0x2
#define MI 0x4 //#define CC 0x3
#define PL 0x5 //#define MI 0x4
#define VS 0x6 //#define PL 0x5
#define VC 0x7 //#define VS 0x6
#define HI 0x8 //#define VC 0x7
#define LS 0x9 //#define HI 0x8
#define GE 0xA //#define LS 0x9
#define LT 0xB //#define GE 0xA
#define GT 0xC //#define LT 0xB
#define LE 0xD //#define GT 0xC
#define AL 0xE //#define LE 0xD
//#define AL 0xE
extern const unsigned char arm_cond_table[16*16]; extern const unsigned char arm_cond_table[16*16];

View File

@ -90,8 +90,18 @@ struct POLYLIST {
}; };
struct VERT { struct VERT {
union {
float coord[4]; float coord[4];
struct {
float x,y,z,w;
};
};
union {
float texcoord[2]; float texcoord[2];
struct {
float u,v;
};
};
u8 color[3]; u8 color[3];
float fcolor[3]; float fcolor[3];
void color_to_float() { void color_to_float() {

View File

@ -23,6 +23,8 @@
//nothing in this file should be assumed to be accurate //nothing in this file should be assumed to be accurate
const bool USE_HECKER = false;
#include "rasterize.h" #include "rasterize.h"
#include <algorithm> #include <algorithm>
@ -40,9 +42,12 @@
using std::min; using std::min;
using std::max; using std::max;
using std::swap;
template<typename T> T _min(T a, T b, T c) { return min(min(a,b),c); } template<typename T> T _min(T a, T b, T c) { return min(min(a,b),c); }
template<typename T> T _max(T a, T b, T c) { return max(max(a,b),c); } template<typename T> T _max(T a, T b, T c) { return max(max(a,b),c); }
template<typename T> T _min(T a, T b, T c, T d) { return min(_min(a,b,d),c); }
template<typename T> T _max(T a, T b, T c, T d) { return max(_max(a,b,d),c); }
static int polynum; static int polynum;
@ -164,6 +169,10 @@ static VERT* verts[3];
INLINE static void SubmitVertex(int vert_index, VERT* rawvert) INLINE static void SubmitVertex(int vert_index, VERT* rawvert)
{ {
//HACK - reverse winding
if(USE_HECKER)
verts[2-vert_index] = rawvert;
else
verts[vert_index] = rawvert; verts[vert_index] = rawvert;
} }
@ -289,10 +298,15 @@ struct Shader
dst.color.components.g = modulate_table[texColor.components.g][materialColor.components.g]; dst.color.components.g = modulate_table[texColor.components.g][materialColor.components.g];
dst.color.components.b = modulate_table[texColor.components.b][materialColor.components.b]; dst.color.components.b = modulate_table[texColor.components.b][materialColor.components.b];
dst.color.components.a = modulate_table[texColor.components.a][materialColor.components.a]; dst.color.components.a = modulate_table[texColor.components.a][materialColor.components.a];
if(GetAsyncKeyState(VK_SHIFT)) {
//debugging tricks //debugging tricks
//dst.color = materialColor; dst.color = materialColor;
//dst.color.color = polynum*8+8; if(GetAsyncKeyState(VK_TAB)) {
//dst.color.components.a = 31; u8 alpha = dst.color.components.a;
dst.color.color = polynum*8+8;
dst.color.components.a = alpha;
}
}
break; break;
case 1: //decal case 1: //decal
u = invu/invw; u = invu/invw;
@ -408,135 +422,17 @@ static void alphaBlend(Fragment::Color & dst, const Fragment::Color & src)
} }
} }
//http://www.devmaster.net/forums/showthread.php?t=1884&page=1 void pixel(int adr,float r, float g, float b, float invu, float invv, float invw, float z) {
//todo - change to the tile-based renderer and try to apply some optimizations from that thread
static void triangle_from_devmaster()
{
// 28.4 fixed-point coordinates
const int Y1 = iround(16.0f * verts[0]->coord[1]);
const int Y2 = iround(16.0f * verts[1]->coord[1]);
const int Y3 = iround(16.0f * verts[2]->coord[1]);
const int X1 = iround(16.0f * verts[0]->coord[0]);
const int X2 = iround(16.0f * verts[1]->coord[0]);
const int X3 = iround(16.0f * verts[2]->coord[0]);
// Deltas
const int DX12 = X1 - X2;
const int DX23 = X2 - X3;
const int DX31 = X3 - X1;
const int DY12 = Y1 - Y2;
const int DY23 = Y2 - Y3;
const int DY31 = Y3 - Y1;
// Fixed-point deltas
const int FDX12 = DX12 << 4;
const int FDX23 = DX23 << 4;
const int FDX31 = DX31 << 4;
const int FDY12 = DY12 << 4;
const int FDY23 = DY23 << 4;
const int FDY31 = DY31 << 4;
// Bounding rectangle
int minx = (_min(X1, X2, X3) + 0xF) >> 4;
int maxx = (_max(X1, X2, X3) + 0xF) >> 4;
int miny = (_min(Y1, Y2, Y3) + 0xF) >> 4;
int maxy = (_max(Y1, Y2, Y3) + 0xF) >> 4;
int desty = miny;
// Half-edge constants
int C1 = DY12 * X1 - DX12 * Y1;
int C2 = DY23 * X2 - DX23 * Y2;
int C3 = DY31 * X3 - DX31 * Y3;
// Correct for fill convention
if(DY12 < 0 || (DY12 == 0 && DX12 > 0)) C1++;
if(DY23 < 0 || (DY23 == 0 && DX23 > 0)) C2++;
if(DY31 < 0 || (DY31 == 0 && DX31 > 0)) C3++;
int CY1 = C1 + DX12 * (miny << 4) - DY12 * (minx << 4);
int CY2 = C2 + DX23 * (miny << 4) - DY23 * (minx << 4);
int CY3 = C3 + DX31 * (miny << 4) - DY31 * (minx << 4);
float fx1 = verts[0]->coord[0], fy1 = verts[0]->coord[1], fz1 = verts[0]->coord[2];
float fx2 = verts[1]->coord[0], fy2 = verts[1]->coord[1], fz2 = verts[1]->coord[2];
float fx3 = verts[2]->coord[0], fy3 = verts[2]->coord[1], fz3 = verts[2]->coord[2];
float r1 = verts[0]->fcolor[0], g1 = verts[0]->fcolor[1], b1 = verts[0]->fcolor[2];
float r2 = verts[1]->fcolor[0], g2 = verts[1]->fcolor[1], b2 = verts[1]->fcolor[2];
float r3 = verts[2]->fcolor[0], g3 = verts[2]->fcolor[1], b3 = verts[2]->fcolor[2];
float u1 = verts[0]->texcoord[0], v1 = verts[0]->texcoord[1];
float u2 = verts[1]->texcoord[0], v2 = verts[1]->texcoord[1];
float u3 = verts[2]->texcoord[0], v3 = verts[2]->texcoord[1];
float w1 = verts[0]->coord[3], w2 = verts[1]->coord[3], w3 = verts[2]->coord[3];
Interpolator i_color_r(fx1,fx2,fx3,fy1,fy2,fy3,r1,r2,r3);
Interpolator i_color_g(fx1,fx2,fx3,fy1,fy2,fy3,g1,g2,g3);
Interpolator i_color_b(fx1,fx2,fx3,fy1,fy2,fy3,b1,b2,b3);
Interpolator i_tex_invu(fx1,fx2,fx3,fy1,fy2,fy3,u1,u2,u3);
Interpolator i_tex_invv(fx1,fx2,fx3,fy1,fy2,fy3,v1,v2,v3);
Interpolator i_z(fx1,fx2,fx3,fy1,fy2,fy3,fz1,fz2,fz3);
Interpolator i_invw(fx1,fx2,fx3,fy1,fy2,fy3,1.0f/w1,1.0f/w2,1.0f/w3);
i_color_r.init(minx,miny);
i_color_g.init(minx,miny);
i_color_b.init(minx,miny);
i_tex_invu.init(minx,miny);
i_tex_invv.init(minx,miny);
i_z.init(minx,miny);
i_invw.init(minx,miny);
for(int y = miny; y < maxy; y++)
{
int CX1 = CY1;
int CX2 = CY2;
int CX3 = CY3;
bool done = false;
i_color_r.push(); i_color_g.push(); i_color_b.push();
i_tex_invu.push(); i_tex_invv.push();
i_invw.push(); i_z.push();
assert(y>=0 && y<192); //I dont think we need this bounds check, so it is only here as an assert
int adr = (y<<8)+minx;
int xaccum = 0;
for(int x = minx; x < maxx; x++, adr++)
{
Fragment &destFragment = screen[adr]; Fragment &destFragment = screen[adr];
if(CX1 > 0 && CX2 > 0 && CX3 > 0)
{
done = true;
assert(x>=0 && x<256); //I dont think we need this bounds check, so it is only here as an assert
//execute interpolators.
//we defer this until the triangle scanline begins, and accumulate the number of deltas which were necessary.
if(xaccum==1) {
i_color_r.incx(); i_color_g.incx(); i_color_b.incx();
i_tex_invu.incx(); i_tex_invv.incx();
i_invw.incx(); i_z.incx();
} else {
i_color_r.incx(xaccum); i_color_g.incx(xaccum); i_color_b.incx(xaccum);
i_tex_invu.incx(xaccum); i_tex_invv.incx(xaccum);
i_invw.incx(xaccum); i_z.incx(xaccum);
}
xaccum = 0;
//depth test //depth test
int depth; int depth;
if(gfx3d.wbuffer) if(gfx3d.wbuffer)
//not sure about this //not sure about this
//this value was chosen to make the skybox, castle window decals, and water level render correctly in SM64 //this value was chosen to make the skybox, castle window decals, and water level render correctly in SM64
depth = 4096/i_invw.Z; depth = 4096/invw;
else else
{ {
float z = i_z.Z;
depth = z*0x7FFF; //not sure about this depth = z*0x7FFF; //not sure about this
} }
if(polyAttr.decalMode) if(polyAttr.decalMode)
@ -554,14 +450,14 @@ static void triangle_from_devmaster()
} }
} }
shader.invw = i_invw.Z; shader.invw = invw;
shader.invu = i_tex_invu.Z; shader.invu = invu;
shader.invv = i_tex_invv.Z; shader.invv = invv;
//perspective-correct the colors //perspective-correct the colors
float r = (i_color_r.Z / i_invw.Z) + 0.5f; r = (r / invw) + 0.5f;
float g = (i_color_g.Z / i_invw.Z) + 0.5f; g = (g / invw) + 0.5f;
float b = (i_color_b.Z / i_invw.Z) + 0.5f; b = (b / invw) + 0.5f;
//this is a HACK: //this is a HACK:
//we are being very sloppy with our interpolation precision right now //we are being very sloppy with our interpolation precision right now
@ -627,8 +523,6 @@ static void triangle_from_devmaster()
} }
} else if(done) break;
goto done_with_pixel; goto done_with_pixel;
depth_fail: depth_fail:
@ -640,12 +534,475 @@ static void triangle_from_devmaster()
rejected_fragment: rejected_fragment:
done_with_pixel: done_with_pixel:
xaccum++; ;
}
void scanline(int y, int xstart, int xend,
float r0, float g0, float b0, float invu0, float invv0, float invw0, float z0,
float r1, float g1, float b1, float invu1, float invv1, float invw1, float z1)
{
float dx = xend-xstart+1;
float dr_dx = (r1-r0)/dx;
float dg_dx = (g1-g0)/dx;
float db_dx = (b1-b0)/dx;
float du_dx = (invu1-invu0)/dx;
float dv_dx = (invv1-invv0)/dx;
float dw_dx = (invw1-invw0)/dx;
float dz_dx = (z1-z0)/dx;
for(int x=xstart;x<=xend;x++) {
int adr = (y<<8)+x;
pixel(adr,r0,g0,b0,invu0,invv0,invw0,z0);
r0 += dr_dx;
g0 += dg_dx;
b0 += db_dx;
invu0 += du_dx;
invv0 += dv_dx;
invw0 += dw_dx;
z0 += dz_dx;
}
}
typedef int fixed28_4;
inline fixed28_4 FloatToFixed28_4( float Value ) {
return Value * 16;
}
inline float Fixed28_4ToFloat( fixed28_4 Value ) {
return Value / 16.0;
}
//inline fixed16_16 FloatToFixed16_16( float Value ) {
// return Value * 65536;
//}
//inline float Fixed16_16ToFloat( fixed16_16 Value ) {
// return Value / 65536.0;
//}
inline fixed28_4 Fixed28_4Mul( fixed28_4 A, fixed28_4 B ) {
// could make this asm to prevent overflow
return (A * B) / 16; // 28.4 * 28.4 = 24.8 / 16 = 28.4
}
inline long Ceil28_4( fixed28_4 Value ) {
long ReturnValue;
long Numerator = Value - 1 + 16;
if(Numerator >= 0) {
ReturnValue = Numerator/16;
} else {
// deal with negative numerators correctly
ReturnValue = -((-Numerator)/16);
ReturnValue -= ((-Numerator) % 16) ? 1 : 0;
}
return ReturnValue;
}
struct Derivatives {
float dx, dy;
void calculate(float v0, float v1, float v2, float invdx, float invdy, const VERT** pVertices)
{
dx = invdx * (
((v1 - v2) * Fixed28_4ToFloat(pVertices[0]->y - pVertices[2]->y))
- ((v0 - v2) * Fixed28_4ToFloat(pVertices[1]->y - pVertices[2]->y))
);
dy = invdy * (
((v1 - v2) * Fixed28_4ToFloat(pVertices[0]->x - pVertices[2]->x))
- ((v0 - v2) * Fixed28_4ToFloat(pVertices[1]->x - pVertices[2]->x))
);
}
};
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 );
inline int Step( void );
long X, XStep, Numerator, Denominator; // DDA info for x
long ErrorTerm;
int Y, Height; // current y and vertical count
struct Interpolant {
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) {
curr = val + YPrestep * gradient.dy
+ XPrestep * gradient.dx;
step = XStep * gradient.dx + gradient.dy;
stepExtra = gradient.dx;
}
};
static const int NUM_INTERPOLANTS = 7;
union {
struct {
Interpolant invw,z,u,v,color[3];
};
Interpolant interpolants[NUM_INTERPOLANTS];
};
void doStepInterpolants() { for(int i=0;i<NUM_INTERPOLANTS;i++) interpolants[i].doStep(); }
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 )
{
Y = Ceil28_4(verts[Top]->y);
int YEnd = Ceil28_4(verts[Bottom]->y);
Height = YEnd - Y;
if(Height)
{
long dN = verts[Bottom]->y - verts[Top]->y;
long dM = verts[Bottom]->x - verts[Top]->x;
long InitialNumerator = dM*16*Y - dM*verts[Top]->y + dN*verts[Top]->x - 1 + dN*16;
FloorDivMod(InitialNumerator,dN*16,X,ErrorTerm);
FloorDivMod(dM*16,dN*16,XStep,Numerator);
Denominator = dN*16;
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);
for(int i=0;i<3;i++)
color[i].initialize(verts[Top]->fcolor[i],XStep,XPrestep,YPrestep,Gradients.d.color[i]);
}
}
void hecker_DrawScanLine( gradients_fx_fl const &Gradients,edge_fx_fl *pLeft, edge_fx_fl *pRight )
{
int XStart = pLeft->X;
int Width = pRight->X - XStart;
//char unsigned *pDestBits = Dest.pBits;
//char unsigned * const pTextureBits = Texture.pBits;
//pDestBits += pLeft->Y * Dest.DeltaScan + XStart;
//long TextureDeltaScan = Texture.DeltaScan;
float invw = pLeft->invw.curr;
float u = pLeft->u.curr;
float v = pLeft->v.curr;
float z = pLeft->z.curr;
float color[3] = {
pLeft->color[0].curr,
pLeft->color[1].curr,
pLeft->color[2].curr };
//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;
}
}
//http://chrishecker.com/Miscellaneous_Technical_Articles
static void triangle_from_hecker()
{
int Top, Middle, Bottom, MiddleForCompare, BottomForCompare;
fixed28_4 Y0 = verts[0]->y, Y1 = verts[1]->y, Y2 = verts[2]->y;
// sort vertices in y
if(Y0 < Y1) {
if(Y2 < Y0) {
Top = 2; Middle = 0; Bottom = 1;
MiddleForCompare = 0; BottomForCompare = 1;
} else {
Top = 0;
if(Y1 < Y2) {
Middle = 1; Bottom = 2;
MiddleForCompare = 1; BottomForCompare = 2;
} else {
Middle = 2; Bottom = 1;
MiddleForCompare = 2; BottomForCompare = 1;
}
}
} else {
if(Y2 < Y1) {
Top = 2; Middle = 1; Bottom = 0;
MiddleForCompare = 1; BottomForCompare = 0;
} else {
Top = 1;
if(Y0 < Y2) {
Middle = 0; Bottom = 2;
MiddleForCompare = 3; BottomForCompare = 2;
} else {
Middle = 2; Bottom = 0;
MiddleForCompare = 2; BottomForCompare = 3;
}
}
}
gradients_fx_fl Gradients((const VERT**)verts);
edge_fx_fl TopToBottom(Gradients,verts,Top,Bottom);
edge_fx_fl TopToMiddle(Gradients,verts,Top,Middle);
edge_fx_fl MiddleToBottom(Gradients,verts,Middle,Bottom);
edge_fx_fl *pLeft, *pRight;
int MiddleIsLeft;
if(BottomForCompare > MiddleForCompare) {
MiddleIsLeft = 0;
pLeft = &TopToBottom; pRight = &TopToMiddle;
} else {
MiddleIsLeft = 1;
pLeft = &TopToMiddle; pRight = &TopToBottom;
}
int Height = TopToMiddle.Height;
while(Height--) {
hecker_DrawScanLine(Gradients,pLeft,pRight);
TopToMiddle.Step(); TopToBottom.Step();
}
Height = MiddleToBottom.Height;
if(MiddleIsLeft) {
pLeft = &MiddleToBottom; pRight = &TopToBottom;
} else {
pLeft = &TopToBottom; pRight = &MiddleToBottom;
}
while(Height--) {
hecker_DrawScanLine(Gradients,pLeft,pRight);
MiddleToBottom.Step(); TopToBottom.Step();
}
}
//http://www.devmaster.net/forums/showthread.php?t=1884&page=1
static void triangle_from_devmaster()
{
if(USE_HECKER)
{
triangle_from_hecker();
return;
}
// 28.4 fixed-point coordinates
const int Y1 = iround(16.0f * verts[0]->coord[1]);
const int Y2 = iround(16.0f * verts[1]->coord[1]);
const int Y3 = iround(16.0f * verts[2]->coord[1]);
const int X1 = iround(16.0f * verts[0]->coord[0]);
const int X2 = iround(16.0f * verts[1]->coord[0]);
const int X3 = iround(16.0f * verts[2]->coord[0]);
// Deltas
const int DX12 = X1 - X2;
const int DX23 = X2 - X3;
const int DX31 = X3 - X1;
const int DY12 = Y1 - Y2;
const int DY23 = Y2 - Y3;
const int DY31 = Y3 - Y1;
// Fixed-point deltas
const int FDX12 = DX12 << 4;
const int FDX23 = DX23 << 4;
const int FDX31 = DX31 << 4;
const int FDY12 = DY12 << 4;
const int FDY23 = DY23 << 4;
const int FDY31 = DY31 << 4;
// Bounding rectangle
int minx = (_min(X1, X2, X3) + 0xF) >> 4;
int maxx = (_max(X1, X2, X3) + 0xF) >> 4;
int miny = (_min(Y1, Y2, Y3) + 0xF) >> 4;
int maxy = (_max(Y1, Y2, Y3) + 0xF) >> 4;
int desty = miny;
// Half-edge constants
int C1 = DY12 * X1 - DX12 * Y1;
int C2 = DY23 * X2 - DX23 * Y2;
int C3 = DY31 * X3 - DX31 * Y3;
// Correct for fill convention
if(DY12 < 0 || (DY12 == 0 && DX12 > 0)) C1++;
if(DY23 < 0 || (DY23 == 0 && DX23 > 0)) C2++;
if(DY31 < 0 || (DY31 == 0 && DX31 > 0)) C3++;
int CY1 = C1 + DX12 * (miny << 4) - DY12 * (minx << 4);
int CY2 = C2 + DX23 * (miny << 4) - DY23 * (minx << 4);
int CY3 = C3 + DX31 * (miny << 4) - DY31 * (minx << 4);
float fx1 = verts[0]->coord[0], fy1 = verts[0]->coord[1], fz1 = verts[0]->coord[2];
float fx2 = verts[1]->coord[0], fy2 = verts[1]->coord[1], fz2 = verts[1]->coord[2];
float fx3 = verts[2]->coord[0], fy3 = verts[2]->coord[1], fz3 = verts[2]->coord[2];
float r1 = verts[0]->fcolor[0], g1 = verts[0]->fcolor[1], b1 = verts[0]->fcolor[2];
float r2 = verts[1]->fcolor[0], g2 = verts[1]->fcolor[1], b2 = verts[1]->fcolor[2];
float r3 = verts[2]->fcolor[0], g3 = verts[2]->fcolor[1], b3 = verts[2]->fcolor[2];
float u1 = verts[0]->texcoord[0], v1 = verts[0]->texcoord[1];
float u2 = verts[1]->texcoord[0], v2 = verts[1]->texcoord[1];
float u3 = verts[2]->texcoord[0], v3 = verts[2]->texcoord[1];
float w1 = verts[0]->coord[3], w2 = verts[1]->coord[3], w3 = verts[2]->coord[3];
Interpolator i_color_r(fx1,fx2,fx3,fy1,fy2,fy3,r1,r2,r3);
Interpolator i_color_g(fx1,fx2,fx3,fy1,fy2,fy3,g1,g2,g3);
Interpolator i_color_b(fx1,fx2,fx3,fy1,fy2,fy3,b1,b2,b3);
Interpolator i_tex_invu(fx1,fx2,fx3,fy1,fy2,fy3,u1,u2,u3);
Interpolator i_tex_invv(fx1,fx2,fx3,fy1,fy2,fy3,v1,v2,v3);
Interpolator i_z(fx1,fx2,fx3,fy1,fy2,fy3,fz1,fz2,fz3);
Interpolator i_invw(fx1,fx2,fx3,fy1,fy2,fy3,1.0f/w1,1.0f/w2,1.0f/w3);
i_color_r.init(minx,miny);
i_color_g.init(minx,miny);
i_color_b.init(minx,miny);
i_tex_invu.init(minx,miny);
i_tex_invv.init(minx,miny);
i_z.init(minx,miny);
i_invw.init(minx,miny);
for(int y = miny; y < maxy; y++)
{
int CX1 = CY1;
int CX2 = CY2;
int CX3 = CY3;
bool done = false;
i_color_r.push(); i_color_g.push(); i_color_b.push();
i_tex_invu.push(); i_tex_invv.push();
i_invw.push(); i_z.push();
assert(y>=0 && y<192); //I dont think we need this bounds check, so it is only here as an assert
int adr = (y<<8)+minx;
int xstart = -1, xend;
//determine the current scanline, which will be in xstart <= x < xend
for(int x = minx; x < maxx; x++, adr++)
{
if(CX1 > 0 && CX2 > 0 && CX3 > 0)
{
xend = x;
if(!done)
xstart = x;
done = true;
} else if(done) break;
CX1 -= FDY12; CX1 -= FDY12;
CX2 -= FDY23; CX2 -= FDY23;
CX3 -= FDY31; CX3 -= FDY31;
} }
//---------
//render the scanline
if(xstart != -1)
{
//seed the interpolators with the distance to the start of this scanline
//this is crappy and we need to redo it now that we've changing the main interpolation method to bilinear
int xaccum = xstart-minx;
i_color_r.incx(xaccum); i_color_g.incx(xaccum); i_color_b.incx(xaccum);
i_tex_invu.incx(xaccum); i_tex_invv.incx(xaccum);
i_invw.incx(xaccum); i_z.incx(xaccum);
float rr = i_color_r.Z;
float gg = i_color_g.Z;
float bb = i_color_b.Z;
float uu = i_tex_invu.Z;
float vv = i_tex_invv.Z;
float ww = i_invw.Z;
float zz = i_z.Z;
//now boost the interpolators to the end of this scanline
i_color_r.pop();i_color_g.pop();i_color_b.pop();
i_tex_invu.pop();i_tex_invv.pop();
i_z.pop();i_invw.pop();
xaccum = xend-minx;
i_color_r.incx(xaccum); i_color_g.incx(xaccum); i_color_b.incx(xaccum);
i_tex_invu.incx(xaccum); i_tex_invv.incx(xaccum);
i_invw.incx(xaccum); i_z.incx(xaccum);
scanline(y, xstart, xend, rr,gg,bb,uu,vv,ww,zz,i_color_r.Z, i_color_g.Z, i_color_b.Z, i_tex_invu.Z, i_tex_invv.Z, i_invw.Z, i_z.Z);
}
//----------
i_color_r.pop(); i_color_r.incy(); i_color_r.pop(); i_color_r.incy();
i_color_g.pop(); i_color_g.incy(); i_color_g.pop(); i_color_g.incy();
i_color_b.pop(); i_color_b.incy(); i_color_b.pop(); i_color_b.incy();
@ -679,6 +1036,7 @@ static char SoftRastInit(void)
TexCache_BindTexture = BindTexture; TexCache_BindTexture = BindTexture;
TexCache_BindTextureData = BindTextureData; TexCache_BindTextureData = BindTextureData;
printf("SoftRast Initialized\n");
return 1; return 1;
} }
@ -974,10 +1332,9 @@ static void SoftRastRender()
//iterate over polys //iterate over polys
bool needInitTexture = true; bool needInitTexture = true;
polynum = 0;
for(int i=0;i<clippedPolyCounter;i++) for(int i=0;i<clippedPolyCounter;i++)
{ {
polynum = i;
TClippedPoly &clippedPoly = clippedPolys[i]; TClippedPoly &clippedPoly = clippedPolys[i];
POLY *poly = clippedPoly.poly; POLY *poly = clippedPoly.poly;
int type = clippedPoly.type; int type = clippedPoly.type;
@ -1022,6 +1379,11 @@ static void SoftRastRender()
needInitTexture = false; needInitTexture = false;
} }
if(USE_HECKER)
for(int i=0;i<type;i++)
for(int j=0;j<2;j++)
verts[i]->coord[j] = iround(16.0f * verts[i]->coord[j]);
//hmm... shader gets setup every time because it depends on sampler which may have just changed //hmm... shader gets setup every time because it depends on sampler which may have just changed
shader.setup(poly->polyAttr); shader.setup(poly->polyAttr);
@ -1035,24 +1397,24 @@ static void SoftRastRender()
SubmitVertex(0,verts[0]); SubmitVertex(0,verts[0]);
SubmitVertex(1,verts[1]); SubmitVertex(1,verts[1]);
SubmitVertex(2,verts[2]); SubmitVertex(2,verts[2]);
triangle_from_devmaster(); triangle_from_devmaster();polynum++;
SubmitVertex(0,verts[2]); SubmitVertex(0,verts[2]);
SubmitVertex(1,verts[3]); SubmitVertex(1,verts[3]);
SubmitVertex(2,verts[0]); SubmitVertex(2,verts[0]);
triangle_from_devmaster(); triangle_from_devmaster();polynum++;
} }
else else
{ {
SubmitVertex(0,verts[2]); SubmitVertex(0,verts[2]);
SubmitVertex(1,verts[1]); SubmitVertex(1,verts[1]);
SubmitVertex(2,verts[0]); SubmitVertex(2,verts[0]);
triangle_from_devmaster(); triangle_from_devmaster();polynum++;
SubmitVertex(0,verts[0]); SubmitVertex(0,verts[0]);
SubmitVertex(1,verts[3]); SubmitVertex(1,verts[3]);
SubmitVertex(2,verts[2]); SubmitVertex(2,verts[2]);
triangle_from_devmaster(); triangle_from_devmaster();polynum++;
} }
} }
else if(type == 3) else if(type == 3)
@ -1062,14 +1424,14 @@ static void SoftRastRender()
SubmitVertex(0,verts[0]); SubmitVertex(0,verts[0]);
SubmitVertex(1,verts[1]); SubmitVertex(1,verts[1]);
SubmitVertex(2,verts[2]); SubmitVertex(2,verts[2]);
triangle_from_devmaster(); triangle_from_devmaster();polynum++;
} }
else else
{ {
SubmitVertex(0,verts[2]); SubmitVertex(0,verts[2]);
SubmitVertex(1,verts[1]); SubmitVertex(1,verts[1]);
SubmitVertex(2,verts[0]); SubmitVertex(2,verts[0]);
triangle_from_devmaster(); triangle_from_devmaster();polynum++;
} }
} else printf("skipping type %d\n",type); } else printf("skipping type %d\n",type);

Binary file not shown.

View File

@ -64,6 +64,8 @@ struct SCustomKeys
SCustomKey Pause, FrameAdvance; SCustomKey Pause, FrameAdvance;
SCustomKey ToggleRasterizer;
SCustomKey PrintScreen; SCustomKey PrintScreen;
SCustomKey LastItem; // dummy, must be last SCustomKey LastItem; // dummy, must be last

View File

@ -78,9 +78,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "directx/ddraw.h" #include "directx/ddraw.h"
#define GPU3D_NULL 0
#define GPU3D_OPENGL 1
using namespace std; using namespace std;
#include <GdiPlus.h> #include <GdiPlus.h>

View File

@ -13,6 +13,9 @@ void Display();
void Pause(); void Pause();
void FrameAdvance(); void FrameAdvance();
#define GPU3D_NULL 0
#define GPU3D_OPENGL 1
#define GPU3D_SWRAST 2
#endif #endif