SoftRasterizer:
- Refactor SoftRasterizer to use Render3D as the base class.
This commit is contained in:
parent
d627a5b6aa
commit
f48ed9fb89
|
@ -722,6 +722,7 @@ static void SetVertex()
|
||||||
vert.color[0] = GFX3D_5TO6(colorRGB[0]);
|
vert.color[0] = GFX3D_5TO6(colorRGB[0]);
|
||||||
vert.color[1] = GFX3D_5TO6(colorRGB[1]);
|
vert.color[1] = GFX3D_5TO6(colorRGB[1]);
|
||||||
vert.color[2] = GFX3D_5TO6(colorRGB[2]);
|
vert.color[2] = GFX3D_5TO6(colorRGB[2]);
|
||||||
|
vert.color_to_float();
|
||||||
tempVertInfo.map[tempVertInfo.count] = vertlist->count + tempVertInfo.count - continuation;
|
tempVertInfo.map[tempVertInfo.count] = vertlist->count + tempVertInfo.count - continuation;
|
||||||
tempVertInfo.count++;
|
tempVertInfo.count++;
|
||||||
|
|
||||||
|
@ -1603,15 +1604,15 @@ static BOOL gfx3d_glBoxTest(u32 v)
|
||||||
//clip each poly
|
//clip each poly
|
||||||
for(int i=0;i<6;i++)
|
for(int i=0;i<6;i++)
|
||||||
{
|
{
|
||||||
POLY* poly = &polys[i];
|
const POLY &thePoly = polys[i];
|
||||||
VERT* vertTable[4] = {
|
const VERT *vertTable[4] = {
|
||||||
&verts[poly->vertIndexes[0]],
|
&verts[thePoly.vertIndexes[0]],
|
||||||
&verts[poly->vertIndexes[1]],
|
&verts[thePoly.vertIndexes[1]],
|
||||||
&verts[poly->vertIndexes[2]],
|
&verts[thePoly.vertIndexes[2]],
|
||||||
&verts[poly->vertIndexes[3]]
|
&verts[thePoly.vertIndexes[3]]
|
||||||
};
|
};
|
||||||
|
|
||||||
boxtestClipper.clipPoly<false>(poly,vertTable);
|
boxtestClipper.clipPoly<false>(thePoly, vertTable);
|
||||||
|
|
||||||
//if any portion of this poly was retained, then the test passes.
|
//if any portion of this poly was retained, then the test passes.
|
||||||
if(boxtestClipper.clippedPolyCounter>0) {
|
if(boxtestClipper.clippedPolyCounter>0) {
|
||||||
|
@ -2612,9 +2613,9 @@ static T interpolate(const float ratio, const T& x0, const T& x1) {
|
||||||
|
|
||||||
//http://www.cs.berkeley.edu/~ug/slide/pipeline/assignments/as6/discussion.shtml
|
//http://www.cs.berkeley.edu/~ug/slide/pipeline/assignments/as6/discussion.shtml
|
||||||
#ifdef OPTIMIZED_CLIPPING_METHOD
|
#ifdef OPTIMIZED_CLIPPING_METHOD
|
||||||
template<int coord, int which> static FORCEINLINE VERT clipPoint(bool hirez, VERT* inside, VERT* outside)
|
template<int coord, int which> static FORCEINLINE VERT clipPoint(bool hirez, const VERT *inside, const VERT *outside)
|
||||||
#else
|
#else
|
||||||
static FORCEINLINE VERT clipPoint(VERT* inside, VERT* outside, int coord, int which)
|
static FORCEINLINE VERT clipPoint(const VERT *inside, const VERT *outside, int coord, int which)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
VERT ret;
|
VERT ret;
|
||||||
|
@ -2679,13 +2680,13 @@ public:
|
||||||
m_next.init(verts);
|
m_next.init(verts);
|
||||||
}
|
}
|
||||||
|
|
||||||
void clipVert(bool hirez, VERT* vert)
|
void clipVert(bool hirez, const VERT *vert)
|
||||||
{
|
{
|
||||||
if(m_prevVert)
|
if(m_prevVert)
|
||||||
this->clipSegmentVsPlane(hirez, m_prevVert, vert);
|
this->clipSegmentVsPlane(hirez, m_prevVert, vert);
|
||||||
else
|
else
|
||||||
m_firstVert = vert;
|
m_firstVert = (VERT *)vert;
|
||||||
m_prevVert = vert;
|
m_prevVert = (VERT *)vert;
|
||||||
}
|
}
|
||||||
|
|
||||||
// closes the loop and returns the number of clipped output verts
|
// closes the loop and returns the number of clipped output verts
|
||||||
|
@ -2701,10 +2702,10 @@ private:
|
||||||
VERT* m_firstVert;
|
VERT* m_firstVert;
|
||||||
Next& m_next;
|
Next& m_next;
|
||||||
|
|
||||||
FORCEINLINE void clipSegmentVsPlane(bool hirez, VERT* vert0, VERT* vert1)
|
FORCEINLINE void clipSegmentVsPlane(bool hirez, const VERT *vert0, const VERT *vert1)
|
||||||
{
|
{
|
||||||
float* vert0coord = vert0->coord;
|
const float *vert0coord = vert0->coord;
|
||||||
float* vert1coord = vert1->coord;
|
const float *vert1coord = vert1->coord;
|
||||||
bool out0, out1;
|
bool out0, out1;
|
||||||
if(which==-1)
|
if(which==-1)
|
||||||
out0 = vert0coord[coord] < -vert0coord[3];
|
out0 = vert0coord[coord] < -vert0coord[3];
|
||||||
|
@ -2730,7 +2731,7 @@ private:
|
||||||
if(!out0 && !out1)
|
if(!out0 && !out1)
|
||||||
{
|
{
|
||||||
CLIPLOG(" both inside\n");
|
CLIPLOG(" both inside\n");
|
||||||
m_next.clipVert(hirez,vert1);
|
m_next.clipVert(hirez, vert1);
|
||||||
}
|
}
|
||||||
|
|
||||||
//exiting volume: insert the clipped point
|
//exiting volume: insert the clipped point
|
||||||
|
@ -2738,7 +2739,7 @@ private:
|
||||||
{
|
{
|
||||||
CLIPLOG(" exiting\n");
|
CLIPLOG(" exiting\n");
|
||||||
assert((u32)numScratchClipVerts < MAX_SCRATCH_CLIP_VERTS);
|
assert((u32)numScratchClipVerts < MAX_SCRATCH_CLIP_VERTS);
|
||||||
scratchClipVerts[numScratchClipVerts] = clipPoint<coord, which>(hirez,vert0,vert1);
|
scratchClipVerts[numScratchClipVerts] = clipPoint<coord, which>(hirez, vert0, vert1);
|
||||||
m_next.clipVert(hirez,&scratchClipVerts[numScratchClipVerts++]);
|
m_next.clipVert(hirez,&scratchClipVerts[numScratchClipVerts++]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2746,7 +2747,7 @@ private:
|
||||||
if(out0 && !out1) {
|
if(out0 && !out1) {
|
||||||
CLIPLOG(" entering\n");
|
CLIPLOG(" entering\n");
|
||||||
assert((u32)numScratchClipVerts < MAX_SCRATCH_CLIP_VERTS);
|
assert((u32)numScratchClipVerts < MAX_SCRATCH_CLIP_VERTS);
|
||||||
scratchClipVerts[numScratchClipVerts] = clipPoint<coord, which>(hirez,vert1,vert0);
|
scratchClipVerts[numScratchClipVerts] = clipPoint<coord, which>(hirez, vert1, vert0);
|
||||||
m_next.clipVert(hirez,&scratchClipVerts[numScratchClipVerts++]);
|
m_next.clipVert(hirez,&scratchClipVerts[numScratchClipVerts++]);
|
||||||
m_next.clipVert(hirez,vert1);
|
m_next.clipVert(hirez,vert1);
|
||||||
}
|
}
|
||||||
|
@ -2761,7 +2762,7 @@ public:
|
||||||
m_nextDestVert = verts;
|
m_nextDestVert = verts;
|
||||||
m_numVerts = 0;
|
m_numVerts = 0;
|
||||||
}
|
}
|
||||||
void clipVert(bool hirez, VERT* vert)
|
void clipVert(bool hirez, const VERT *vert)
|
||||||
{
|
{
|
||||||
assert((u32)m_numVerts < MAX_CLIPPED_VERTS);
|
assert((u32)m_numVerts < MAX_CLIPPED_VERTS);
|
||||||
*m_nextDestVert++ = *vert;
|
*m_nextDestVert++ = *vert;
|
||||||
|
@ -2786,16 +2787,16 @@ typedef ClipperPlane<1,-1,Stage4> Stage3; static Stage3 clipper3 (clipper
|
||||||
typedef ClipperPlane<0, 1,Stage3> Stage2; static Stage2 clipper2 (clipper3); // right plane
|
typedef ClipperPlane<0, 1,Stage3> Stage2; static Stage2 clipper2 (clipper3); // right plane
|
||||||
typedef ClipperPlane<0,-1,Stage2> Stage1; static Stage1 clipper (clipper2); // left plane
|
typedef ClipperPlane<0,-1,Stage2> Stage1; static Stage1 clipper (clipper2); // left plane
|
||||||
|
|
||||||
template<bool hirez> void GFX3D_Clipper::clipPoly(POLY* poly, VERT** verts)
|
template<bool hirez> void GFX3D_Clipper::clipPoly(const POLY &poly, const VERT **verts)
|
||||||
{
|
{
|
||||||
CLIPLOG("==Begin poly==\n");
|
CLIPLOG("==Begin poly==\n");
|
||||||
|
|
||||||
int type = poly->type;
|
int type = poly.type;
|
||||||
numScratchClipVerts = 0;
|
numScratchClipVerts = 0;
|
||||||
|
|
||||||
clipper.init(clippedPolys[clippedPolyCounter].clipVerts);
|
clipper.init(clippedPolys[clippedPolyCounter].clipVerts);
|
||||||
for(int i=0;i<type;i++)
|
for(int i=0;i<type;i++)
|
||||||
clipper.clipVert(hirez,verts[i]);
|
clipper.clipVert(hirez, verts[i]);
|
||||||
int outType = clipper.finish(hirez);
|
int outType = clipper.finish(hirez);
|
||||||
|
|
||||||
assert((u32)outType < MAX_CLIPPED_VERTS);
|
assert((u32)outType < MAX_CLIPPED_VERTS);
|
||||||
|
@ -2807,13 +2808,13 @@ template<bool hirez> void GFX3D_Clipper::clipPoly(POLY* poly, VERT** verts)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
clippedPolys[clippedPolyCounter].type = outType;
|
clippedPolys[clippedPolyCounter].type = outType;
|
||||||
clippedPolys[clippedPolyCounter].poly = poly;
|
clippedPolys[clippedPolyCounter].poly = (POLY *)&poly;
|
||||||
clippedPolyCounter++;
|
clippedPolyCounter++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//these templates needed to be instantiated manually
|
//these templates needed to be instantiated manually
|
||||||
template void GFX3D_Clipper::clipPoly<true>(POLY* poly, VERT** verts);
|
template void GFX3D_Clipper::clipPoly<true>(const POLY &poly, const VERT **verts);
|
||||||
template void GFX3D_Clipper::clipPoly<false>(POLY* poly, VERT** verts);
|
template void GFX3D_Clipper::clipPoly<false>(const POLY &poly, const VERT **verts);
|
||||||
|
|
||||||
void GFX3D_Clipper::clipSegmentVsPlane(VERT** verts, const int coord, int which)
|
void GFX3D_Clipper::clipSegmentVsPlane(VERT** verts, const int coord, int which)
|
||||||
{
|
{
|
||||||
|
@ -2897,9 +2898,9 @@ FORCEINLINE void GFX3D_Clipper::clipPolyVsPlane(const int coord, int which)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void GFX3D_Clipper::clipPoly(POLY* poly, VERT** verts)
|
void GFX3D_Clipper::clipPoly(const POLY &poly, const VERT **verts)
|
||||||
{
|
{
|
||||||
int type = poly->type;
|
int type = poly.type;
|
||||||
|
|
||||||
CLIPLOG("==Begin poly==\n");
|
CLIPLOG("==Begin poly==\n");
|
||||||
|
|
||||||
|
@ -2930,7 +2931,7 @@ void GFX3D_Clipper::clipPoly(POLY* poly, VERT** verts)
|
||||||
{
|
{
|
||||||
//TODO - build right in this list instead of copying
|
//TODO - build right in this list instead of copying
|
||||||
clippedPolys[clippedPolyCounter] = tempClippedPoly;
|
clippedPolys[clippedPolyCounter] = tempClippedPoly;
|
||||||
clippedPolys[clippedPolyCounter].poly = poly;
|
clippedPolys[clippedPolyCounter].poly = &poly;
|
||||||
clippedPolyCounter++;
|
clippedPolyCounter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -587,12 +587,12 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
//the entry point for poly clipping
|
//the entry point for poly clipping
|
||||||
template<bool hirez> void clipPoly(POLY* poly, VERT** verts);
|
template<bool hirez> void clipPoly(const POLY &poly, const VERT **verts);
|
||||||
|
|
||||||
//the output of clipping operations goes into here.
|
//the output of clipping operations goes into here.
|
||||||
//be sure you init it before clipping!
|
//be sure you init it before clipping!
|
||||||
TClippedPoly *clippedPolys;
|
TClippedPoly *clippedPolys;
|
||||||
int clippedPolyCounter;
|
size_t clippedPolyCounter;
|
||||||
void reset() { clippedPolyCounter=0; }
|
void reset() { clippedPolyCounter=0; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -23,9 +23,11 @@
|
||||||
|
|
||||||
extern GPU3DInterface gpu3DRasterize;
|
extern GPU3DInterface gpu3DRasterize;
|
||||||
|
|
||||||
union FragmentColor {
|
union FragmentColor
|
||||||
|
{
|
||||||
u32 color;
|
u32 color;
|
||||||
struct {
|
struct
|
||||||
|
{
|
||||||
u8 r,g,b,a;
|
u8 r,g,b,a;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -37,60 +39,70 @@ inline FragmentColor MakeFragmentColor(u8 r, u8 g,u8 b,u8 a)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Fragment
|
struct FragmentAttributes
|
||||||
{
|
{
|
||||||
u32 depth;
|
u32 depth;
|
||||||
|
u8 opaquePolyID;
|
||||||
struct
|
u8 translucentPolyID;
|
||||||
{
|
|
||||||
u8 opaque, translucent;
|
|
||||||
} polyid;
|
|
||||||
|
|
||||||
u8 stencil;
|
u8 stencil;
|
||||||
|
bool isFogged;
|
||||||
struct
|
bool isTranslucentPoly;
|
||||||
{
|
|
||||||
u8 isTranslucentPoly:1;
|
|
||||||
u8 fogged:1;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class TexCacheItem;
|
class TexCacheItem;
|
||||||
|
|
||||||
class SoftRasterizerEngine
|
class SoftRasterizerRenderer : public Render3D
|
||||||
{
|
{
|
||||||
public:
|
protected:
|
||||||
//debug:
|
|
||||||
int _debug_drawClippedUserPoly;
|
|
||||||
|
|
||||||
SoftRasterizerEngine();
|
|
||||||
|
|
||||||
void initFramebuffer(const int width, const int height, const bool clearImage);
|
|
||||||
void framebufferProcess();
|
|
||||||
void updateToonTable();
|
|
||||||
void updateFogTable();
|
|
||||||
void updateFloatColors();
|
|
||||||
void performClipping(bool hirez);
|
|
||||||
template<bool CUSTOM> void performViewportTransforms(int width, int height);
|
|
||||||
void performCoordAdjustment(const bool skipBackfacing);
|
|
||||||
void performBackfaceTests();
|
|
||||||
void setupTextures(const bool skipBackfacing);
|
|
||||||
|
|
||||||
FragmentColor toonTable[32];
|
|
||||||
u8 fogTable[32768];
|
|
||||||
GFX3D_Clipper clipper;
|
GFX3D_Clipper clipper;
|
||||||
|
u8 fogTable[32768];
|
||||||
|
bool _enableEdgeMark;
|
||||||
|
bool _enableFog;
|
||||||
|
bool _enableFogAlphaOnly;
|
||||||
|
u32 _fogColor;
|
||||||
|
u32 _fogOffset;
|
||||||
|
u32 _fogShift;
|
||||||
|
bool _renderGeometryNeedsFinish;
|
||||||
|
|
||||||
|
// SoftRasterizer-specific methods
|
||||||
|
virtual Render3DError InitTables();
|
||||||
|
|
||||||
|
size_t performClipping(bool hirez, const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList);
|
||||||
|
template<bool CUSTOM> void performViewportTransforms(const size_t polyCount);
|
||||||
|
void performCoordAdjustment(const size_t polyCount);
|
||||||
|
void performBackfaceTests(const size_t polyCount);
|
||||||
|
void setupTextures(const size_t polyCount);
|
||||||
|
|
||||||
|
// Base rendering methods
|
||||||
|
virtual Render3DError BeginRender(const GFX3D_State *renderState);
|
||||||
|
virtual Render3DError RenderGeometry(const GFX3D_State *renderState, const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList);
|
||||||
|
virtual Render3DError RenderEdgeMarking(const u16 *colorTable);
|
||||||
|
virtual Render3DError RenderFog(const u8 *densityTable, const u32 color, const u32 offset, const u8 shift, const bool alphaOnly);
|
||||||
|
|
||||||
|
virtual Render3DError UpdateToonTable(const u16 *toonTableBuffer);
|
||||||
|
|
||||||
|
virtual Render3DError ClearUsingImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthStencilBuffer, const bool *__restrict fogBuffer);
|
||||||
|
virtual Render3DError ClearUsingValues(const u8 r, const u8 g, const u8 b, const u8 a, const u32 clearDepth, const u8 clearPolyID, const bool enableFog) const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
int _debug_drawClippedUserPoly;
|
||||||
|
size_t _clippedPolyCount;
|
||||||
|
FragmentColor _toonColor32LUT[32];
|
||||||
GFX3D_Clipper::TClippedPoly *clippedPolys;
|
GFX3D_Clipper::TClippedPoly *clippedPolys;
|
||||||
int clippedPolyCounter;
|
FragmentAttributes *screenAttributes;
|
||||||
TexCacheItem* polyTexKeys[POLYLIST_SIZE];
|
FragmentColor *screenColor;
|
||||||
|
TexCacheItem *polyTexKeys[POLYLIST_SIZE];
|
||||||
bool polyVisible[POLYLIST_SIZE];
|
bool polyVisible[POLYLIST_SIZE];
|
||||||
bool polyBackfacing[POLYLIST_SIZE];
|
bool polyBackfacing[POLYLIST_SIZE];
|
||||||
Fragment *screen;
|
size_t _framebufferWidth;
|
||||||
FragmentColor *screenColor;
|
size_t _framebufferHeight;
|
||||||
POLYLIST* polylist;
|
|
||||||
VERTLIST* vertlist;
|
SoftRasterizerRenderer();
|
||||||
INDEXLIST* indexlist;
|
virtual ~SoftRasterizerRenderer();
|
||||||
int width, height;
|
|
||||||
|
virtual Render3DError Reset();
|
||||||
|
virtual Render3DError Render(const GFX3D_State *renderState, const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList, const u64 frameCount);
|
||||||
|
virtual Render3DError RenderFinish();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -168,6 +168,8 @@ Render3DError Render3D::ClearFramebuffer(const GFX3D_State *renderState)
|
||||||
|
|
||||||
if (renderState->enableClearImage)
|
if (renderState->enableClearImage)
|
||||||
{
|
{
|
||||||
|
//the lion, the witch, and the wardrobe (thats book 1, suck it you new-school numberers)
|
||||||
|
//uses the scroll registers in the main game engine
|
||||||
const u16 *__restrict clearColorBuffer = (u16 *__restrict)MMU.texInfo.textureSlotAddr[2];
|
const u16 *__restrict clearColorBuffer = (u16 *__restrict)MMU.texInfo.textureSlotAddr[2];
|
||||||
const u16 *__restrict clearDepthBuffer = (u16 *__restrict)MMU.texInfo.textureSlotAddr[3];
|
const u16 *__restrict clearDepthBuffer = (u16 *__restrict)MMU.texInfo.textureSlotAddr[3];
|
||||||
const u16 scrollBits = T1ReadWord(MMU.ARM9_REG, 0x356); //CLRIMAGE_OFFSET
|
const u16 scrollBits = T1ReadWord(MMU.ARM9_REG, 0x356); //CLRIMAGE_OFFSET
|
||||||
|
@ -185,8 +187,15 @@ Render3DError Render3D::ClearFramebuffer(const GFX3D_State *renderState)
|
||||||
const size_t x = (ix + xScroll) & 0xFF;
|
const size_t x = (ix + xScroll) & 0xFF;
|
||||||
const size_t adr = y + x;
|
const size_t adr = y + x;
|
||||||
|
|
||||||
|
//this is tested by harry potter and the order of the phoenix.
|
||||||
|
//TODO (optimization) dont do this if we are mapped to blank memory (such as in sonic chronicles)
|
||||||
|
//(or use a special zero fill in the bulk clearing above)
|
||||||
this->clearImageColor16Buffer[dd] = clearColorBuffer[adr];
|
this->clearImageColor16Buffer[dd] = clearColorBuffer[adr];
|
||||||
|
|
||||||
|
//this is tested quite well in the sonic chronicles main map mode
|
||||||
|
//where depth values are used for trees etc you can walk behind
|
||||||
this->clearImageDepthStencilBuffer[dd] = dsDepthToD24S8_LUT[clearDepthBuffer[adr] & 0x7FFF] | polyID;
|
this->clearImageDepthStencilBuffer[dd] = dsDepthToD24S8_LUT[clearDepthBuffer[adr] & 0x7FFF] | polyID;
|
||||||
|
|
||||||
this->clearImageFogBuffer[dd] = BIT15(clearDepthBuffer[adr]);
|
this->clearImageFogBuffer[dd] = BIT15(clearDepthBuffer[adr]);
|
||||||
|
|
||||||
dd++;
|
dd++;
|
||||||
|
|
Loading…
Reference in New Issue