rasterizer: more correct texturing and alpha blending
This commit is contained in:
parent
ac68f0317f
commit
33be370fe6
|
@ -27,8 +27,6 @@
|
|||
#include "OGLRender.h"
|
||||
#include "debug.h"
|
||||
|
||||
//#define DEBUG_DUMP_TEXTURE
|
||||
|
||||
bool (*oglrender_init)() = 0;
|
||||
bool (*oglrender_beginOpenGL)() = 0;
|
||||
void (*oglrender_endOpenGL)() = 0;
|
||||
|
@ -331,11 +329,9 @@ static void createShaders()
|
|||
|
||||
static void OGLReset()
|
||||
{
|
||||
int i;
|
||||
|
||||
//reset the texture cache
|
||||
TexCache_Reset();
|
||||
for (i = 0; i < MAX_TEXTURE; i++)
|
||||
|
||||
for (int i = 0; i < MAX_TEXTURE; i++)
|
||||
texcache[i].id=oglTempTextureID[i];
|
||||
|
||||
// memset(GPU_screenStencil,0,sizeof(GPU_screenStencil));
|
||||
|
@ -343,6 +339,9 @@ static void OGLReset()
|
|||
needRefreshFramebuffer = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void BindTexture(u32 tx)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D,(GLuint)texcache[tx].id);
|
||||
|
@ -509,13 +508,11 @@ static void setTexture(unsigned int format, unsigned int texpal)
|
|||
|
||||
if (format==0)
|
||||
{
|
||||
// texcache_count=-1;
|
||||
if(hasShaders && hasTexture) { glUniform1i(hasTexLoc, 0); hasTexture = false; }
|
||||
return;
|
||||
}
|
||||
if (textureMode==0)
|
||||
{
|
||||
// texcache_count=-1;
|
||||
if(hasShaders && hasTexture) { glUniform1i(hasTexLoc, 0); hasTexture = false; }
|
||||
return;
|
||||
}
|
||||
|
@ -652,7 +649,7 @@ static void Control()
|
|||
else glDisable (GL_TEXTURE_2D);
|
||||
|
||||
if(gfx3d.enableAlphaTest)
|
||||
glAlphaFunc (GL_GREATER, gfx3d.alphaTestRef);
|
||||
glAlphaFunc (GL_GREATER, gfx3d.alphaTestRef/31.f);
|
||||
else
|
||||
glAlphaFunc (GL_GREATER, 0);
|
||||
|
||||
|
@ -684,7 +681,13 @@ static void OGLRender()
|
|||
glViewport(gfx3d.viewport.x,gfx3d.viewport.y,gfx3d.viewport.width,gfx3d.viewport.height);
|
||||
|
||||
//we're not using the alpha clear color right now
|
||||
glClearColor(gfx3d.clearColor[0],gfx3d.clearColor[1],gfx3d.clearColor[2], gfx3d.clearColor[3]);
|
||||
float clearColor[4] = {
|
||||
((float)(gfx3d.clearColor&0x1F))/31.0f,
|
||||
((float)((gfx3d.clearColor>>5)&0x1F))/31.0f,
|
||||
((float)((gfx3d.clearColor>>10)&0x1F))/31.0f,
|
||||
((float)((gfx3d.clearColor>>16)&0x1F))/31.0f,
|
||||
};
|
||||
glClearColor(clearColor[0],clearColor[1],clearColor[2],clearColor[3]);
|
||||
glClearDepth(gfx3d.clearDepth);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
|
||||
|
|
|
@ -289,7 +289,7 @@ void gfx3d_reset()
|
|||
GFX_FIFOclear();
|
||||
}
|
||||
|
||||
void gfx3d_glViewPort(unsigned long v)
|
||||
void gfx3d_glViewPort(u32 v)
|
||||
{
|
||||
//zero: NHerve messed with this in mod2 and mod3, but im still not sure its perfect. need to research this.
|
||||
gfx3d.viewport.x = (v&0xFF);
|
||||
|
@ -299,15 +299,13 @@ void gfx3d_glViewPort(unsigned long v)
|
|||
}
|
||||
|
||||
|
||||
void gfx3d_glClearColor(unsigned long v)
|
||||
void gfx3d_glClearColor(u32 v)
|
||||
{
|
||||
gfx3d.clearColor[0] = ((float)(v&0x1F))/31.0f;
|
||||
gfx3d.clearColor[1] = ((float)((v>>5)&0x1F))/31.0f;
|
||||
gfx3d.clearColor[2] = ((float)((v>>10)&0x1F))/31.0f;
|
||||
gfx3d.clearColor[3] = ((float)((v>>16)&0x1F))/31.0f;
|
||||
gfx3d.clearColor = v;
|
||||
|
||||
}
|
||||
|
||||
void gfx3d_glFogColor(unsigned long v)
|
||||
void gfx3d_glFogColor(u32 v)
|
||||
{
|
||||
gfx3d.fogColor[0] = ((float)((v )&0x1F))/31.0f;
|
||||
gfx3d.fogColor[1] = ((float)((v>> 5)&0x1F))/31.0f;
|
||||
|
@ -315,12 +313,12 @@ void gfx3d_glFogColor(unsigned long v)
|
|||
gfx3d.fogColor[3] = ((float)((v>>16)&0x1F))/31.0f;
|
||||
}
|
||||
|
||||
void gfx3d_glFogOffset (unsigned long v)
|
||||
void gfx3d_glFogOffset (u32 v)
|
||||
{
|
||||
gfx3d.fogOffset = (float)(v&0xffff);
|
||||
}
|
||||
|
||||
void gfx3d_glClearDepth(unsigned long v)
|
||||
void gfx3d_glClearDepth(u32 v)
|
||||
{
|
||||
//Thanks to NHerve
|
||||
v &= 0x7FFFF;
|
||||
|
@ -328,7 +326,7 @@ void gfx3d_glClearDepth(unsigned long v)
|
|||
gfx3d.clearDepth = depth24b / ((float)(1<<24));
|
||||
}
|
||||
|
||||
void gfx3d_glMatrixMode(unsigned long v)
|
||||
void gfx3d_glMatrixMode(u32 v)
|
||||
{
|
||||
mode = (v&3);
|
||||
}
|
||||
|
@ -374,7 +372,7 @@ BOOL gfx3d_glLoadMatrix4x3(signed long v)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
void gfx3d_glStoreMatrix(unsigned long v)
|
||||
void gfx3d_glStoreMatrix(u32 v)
|
||||
{
|
||||
//this command always works on both pos and vector when either pos or pos-vector are the current mtx mode
|
||||
short mymode = (mode==1?2:mode);
|
||||
|
@ -388,7 +386,7 @@ void gfx3d_glStoreMatrix(unsigned long v)
|
|||
MatrixStackLoadMatrix (&mtxStack[1], v&31, mtxCurrent[1]);
|
||||
}
|
||||
|
||||
void gfx3d_glRestoreMatrix(unsigned long v)
|
||||
void gfx3d_glRestoreMatrix(u32 v)
|
||||
{
|
||||
//this command always works on both pos and vector when either pos or pos-vector are the current mtx mode
|
||||
short mymode = (mode==1?2:mode);
|
||||
|
@ -550,7 +548,7 @@ BOOL gfx3d_glMultMatrix4x4(signed long v)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
void gfx3d_glBegin(unsigned long v)
|
||||
void gfx3d_glBegin(u32 v)
|
||||
{
|
||||
vtxFormat = v&0x03;
|
||||
triStripToggle = 0;
|
||||
|
@ -563,7 +561,7 @@ void gfx3d_glEnd(void)
|
|||
tempVertInfo.count = 0;
|
||||
}
|
||||
|
||||
void gfx3d_glColor3b(unsigned long v)
|
||||
void gfx3d_glColor3b(u32 v)
|
||||
{
|
||||
colorRGB[0] = (v&0x1F);
|
||||
colorRGB[1] = ((v>>5)&0x1F);
|
||||
|
@ -729,7 +727,7 @@ BOOL gfx3d_glVertex16b(unsigned int v)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
void gfx3d_glVertex10b(unsigned long v)
|
||||
void gfx3d_glVertex10b(u32 v)
|
||||
{
|
||||
coord[0] = float10Table[v&1023];
|
||||
coord[1] = float10Table[(v>>10)&1023];
|
||||
|
@ -746,7 +744,7 @@ void gfx3d_glVertex3_cord(unsigned int one, unsigned int two, unsigned int v)
|
|||
SetVertex ();
|
||||
}
|
||||
|
||||
void gfx3d_glVertex_rel(unsigned long v)
|
||||
void gfx3d_glVertex_rel(u32 v)
|
||||
{
|
||||
coord[0] += float10RelTable[v&1023];
|
||||
coord[1] += float10RelTable[(v>>10)&1023];
|
||||
|
@ -797,7 +795,7 @@ static void gfx3d_glPolygonAttrib_cache()
|
|||
//polyID = (polyAttr>>24)&0x1F;
|
||||
}
|
||||
|
||||
void gfx3d_glPolygonAttrib (unsigned long val)
|
||||
void gfx3d_glPolygonAttrib (u32 val)
|
||||
{
|
||||
polyAttr = val;
|
||||
gfx3d_glPolygonAttrib_cache();
|
||||
|
@ -812,7 +810,7 @@ void gfx3d_glPolygonAttrib (unsigned long val)
|
|||
21-25 Ambient Reflection Green
|
||||
26-30 Ambient Reflection Blue
|
||||
*/
|
||||
void gfx3d_glMaterial0(unsigned long val)
|
||||
void gfx3d_glMaterial0(u32 val)
|
||||
{
|
||||
dsDiffuse = val&0xFFFF;
|
||||
dsAmbient = val>>16;
|
||||
|
@ -825,13 +823,13 @@ void gfx3d_glMaterial0(unsigned long val)
|
|||
}
|
||||
}
|
||||
|
||||
void gfx3d_glMaterial1(unsigned long val)
|
||||
void gfx3d_glMaterial1(u32 val)
|
||||
{
|
||||
dsSpecular = val&0xFFFF;
|
||||
dsEmission = val>>16;
|
||||
}
|
||||
|
||||
BOOL gfx3d_glShininess (unsigned long val)
|
||||
BOOL gfx3d_glShininess (u32 val)
|
||||
{
|
||||
shininessTable[shininessInd++] = ((val & 0xFF) / 256.0f);
|
||||
shininessTable[shininessInd++] = (((val >> 8) & 0xFF) / 256.0f);
|
||||
|
@ -858,18 +856,18 @@ static void gfx3d_glTexImage_cache()
|
|||
{
|
||||
texCoordinateTransform = (textureFormat>>30);
|
||||
}
|
||||
void gfx3d_glTexImage(unsigned long val)
|
||||
void gfx3d_glTexImage(u32 val)
|
||||
{
|
||||
textureFormat = val;
|
||||
gfx3d_glTexImage_cache();
|
||||
}
|
||||
|
||||
void gfx3d_glTexPalette(unsigned long val)
|
||||
void gfx3d_glTexPalette(u32 val)
|
||||
{
|
||||
texturePalette = val;
|
||||
}
|
||||
|
||||
void gfx3d_glTexCoord(unsigned long val)
|
||||
void gfx3d_glTexCoord(u32 val)
|
||||
{
|
||||
_t = (s16)(val>>16);
|
||||
_s = (s16)(val&0xFFFF);
|
||||
|
@ -893,7 +891,7 @@ void gfx3d_glTexCoord(unsigned long val)
|
|||
|
||||
#define vec3dot(a, b) (((a[0]) * (b[0])) + ((a[1]) * (b[1])) + ((a[2]) * (b[2])))
|
||||
|
||||
void gfx3d_glNormal(unsigned long v)
|
||||
void gfx3d_glNormal(u32 v)
|
||||
{
|
||||
int i,c;
|
||||
ALIGN(16) float normal[3] = { normalTable[v&1023],
|
||||
|
@ -1016,7 +1014,7 @@ static void gfx3d_glLightDirection_cache(int index)
|
|||
20-29 Directional Vector's Z component (1bit sign + 9bit fractional part)
|
||||
30-31 Light Number (0..3)
|
||||
*/
|
||||
void gfx3d_glLightDirection (unsigned long v)
|
||||
void gfx3d_glLightDirection (u32 v)
|
||||
{
|
||||
int index = v>>30;
|
||||
|
||||
|
@ -1024,18 +1022,18 @@ void gfx3d_glLightDirection (unsigned long v)
|
|||
gfx3d_glLightDirection_cache(index);
|
||||
}
|
||||
|
||||
void gfx3d_glLightColor (unsigned long v)
|
||||
void gfx3d_glLightColor (u32 v)
|
||||
{
|
||||
int index = v>>30;
|
||||
lightColor[index] = v;
|
||||
}
|
||||
|
||||
void gfx3d_glAlphaFunc(unsigned long v)
|
||||
void gfx3d_glAlphaFunc(u32 v)
|
||||
{
|
||||
gfx3d.alphaTestRef = (v&31)/31.f;
|
||||
gfx3d.alphaTestRef = v&31;
|
||||
}
|
||||
|
||||
BOOL gfx3d_glBoxTest(unsigned long v)
|
||||
BOOL gfx3d_glBoxTest(u32 v)
|
||||
{
|
||||
u32 gxstat = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x600);
|
||||
gxstat |= 0x00000001; // busy
|
||||
|
@ -1051,7 +1049,7 @@ BOOL gfx3d_glBoxTest(unsigned long v)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL gfx3d_glPosTest(unsigned long v)
|
||||
BOOL gfx3d_glPosTest(u32 v)
|
||||
{
|
||||
u32 gxstat = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x600);
|
||||
gxstat |= 0x00000001; // busy
|
||||
|
@ -1079,7 +1077,7 @@ BOOL gfx3d_glPosTest(unsigned long v)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
void gfx3d_glVecTest(unsigned long v)
|
||||
void gfx3d_glVecTest(u32 v)
|
||||
{
|
||||
u32 gxstat = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x600);
|
||||
gxstat &= 0xFFFFFFFE;
|
||||
|
@ -1238,7 +1236,7 @@ static void gfx3d_FlushFIFO()
|
|||
GFX_FIFOclear();
|
||||
}
|
||||
|
||||
void gfx3d_glFlush(unsigned long v)
|
||||
void gfx3d_glFlush(u32 v)
|
||||
{
|
||||
gfx3d_FlushFIFO();
|
||||
|
||||
|
@ -2014,7 +2012,7 @@ static void gfx3d_Control_cache()
|
|||
}
|
||||
}
|
||||
|
||||
void gfx3d_Control(unsigned long v)
|
||||
void gfx3d_Control(u32 v)
|
||||
{
|
||||
control = v;
|
||||
gfx3d_Control_cache();
|
||||
|
@ -2114,12 +2112,12 @@ SFORMAT SF_GFX3D[]={
|
|||
{ "GSSH", 4, 1, &gfx3d.shading},
|
||||
{ "GSWB", 4, 1, &gfx3d.wbuffer},
|
||||
{ "GSSM", 4, 1, &gfx3d.sortmode},
|
||||
{ "GSAR", 4, 1, &gfx3d.alphaTestRef},
|
||||
{ "GSAR", 1, 1, &gfx3d.alphaTestRef},
|
||||
{ "GSVX", 4, 1, &gfx3d.viewport.x},
|
||||
{ "GSVY", 4, 1, &gfx3d.viewport.y},
|
||||
{ "GSVW", 4, 1, &gfx3d.viewport.width},
|
||||
{ "GSVH", 4, 1, &gfx3d.viewport.height},
|
||||
{ "GSCC", 4, 4, gfx3d.clearColor},
|
||||
{ "GSCC", 4, 1, &gfx3d.clearColor},
|
||||
{ "GSCD", 4, 1, &gfx3d.clearDepth},
|
||||
{ "GSFC", 4, 4, gfx3d.fogColor},
|
||||
{ "GSFO", 4, 1, &gfx3d.fogOffset},
|
||||
|
|
|
@ -117,8 +117,8 @@ struct GFX3D
|
|||
, vertlist(0)
|
||||
, alphaTestRef(0)
|
||||
, clearDepth(1)
|
||||
, clearColor(0)
|
||||
{
|
||||
clearColor[0] = clearColor[1] = clearColor[2] = clearColor[3] = 0;
|
||||
fogColor[0] = fogColor[1] = fogColor[2] = fogColor[3] = 0;
|
||||
fogOffset = 0;
|
||||
}
|
||||
|
@ -135,7 +135,7 @@ struct GFX3D
|
|||
|
||||
BOOL wbuffer, sortmode;
|
||||
|
||||
float alphaTestRef;
|
||||
u8 alphaTestRef;
|
||||
|
||||
struct VIEWPORT {
|
||||
VIEWPORT()
|
||||
|
@ -144,7 +144,7 @@ struct GFX3D
|
|||
int x, y, width, height;
|
||||
} viewport;
|
||||
|
||||
float clearColor[4];
|
||||
u32 clearColor;
|
||||
float clearDepth;
|
||||
float fogColor[4];
|
||||
float fogOffset;
|
||||
|
|
|
@ -47,6 +47,92 @@ template<typename T> T max(T a, T b, T c) { return max(max(a,b),c); }
|
|||
|
||||
static u8 modulate_table[32][32];
|
||||
|
||||
//----texture cache---
|
||||
|
||||
//TODO - the texcache could ask for a buffer to generate into
|
||||
//that would avoid us ever having to buffercopy..
|
||||
struct TextureBuffers
|
||||
{
|
||||
static const int numTextures = MAX_TEXTURE+1;
|
||||
u8* buffers[numTextures];
|
||||
|
||||
void clear() { memset(buffers,0,sizeof(buffers)); }
|
||||
|
||||
TextureBuffers()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
void free()
|
||||
{
|
||||
for(int i=0;i<numTextures;i++)
|
||||
delete[] buffers[i];
|
||||
clear();
|
||||
}
|
||||
|
||||
~TextureBuffers() {
|
||||
free();
|
||||
}
|
||||
|
||||
void setCurrent(int num)
|
||||
{
|
||||
currentData = buffers[num];
|
||||
}
|
||||
|
||||
void create(int num, u8* data)
|
||||
{
|
||||
delete[] buffers[num];
|
||||
int size = texcache[num].sizeX * texcache[num].sizeY * 4;
|
||||
buffers[num] = new u8[size];
|
||||
setCurrent(num);
|
||||
memcpy(currentData,data,size);
|
||||
}
|
||||
u8* currentData;
|
||||
} textures;
|
||||
|
||||
//called from the texture cache to change the active texture
|
||||
static void BindTexture(u32 tx)
|
||||
{
|
||||
textures.setCurrent(tx);
|
||||
}
|
||||
|
||||
//caled from the texture cache to change to a new texture
|
||||
static void BindTextureData(u32 tx, u8* data)
|
||||
{
|
||||
textures.create(tx,data);
|
||||
}
|
||||
|
||||
//---------------
|
||||
|
||||
struct PolyAttr
|
||||
{
|
||||
u32 val;
|
||||
|
||||
bool decalMode;
|
||||
bool translucent;
|
||||
bool translucentDepthWrite;
|
||||
|
||||
bool isVisible(bool backfacing)
|
||||
{
|
||||
switch((val>>6)&3) {
|
||||
case 0: return false;
|
||||
case 1: return backfacing;
|
||||
case 2: return !backfacing;
|
||||
case 3: return true;
|
||||
default: assert(false); return false;
|
||||
}
|
||||
}
|
||||
|
||||
void setup(u32 polyAttr, bool translucent)
|
||||
{
|
||||
val = polyAttr;
|
||||
decalMode = BIT14(val);
|
||||
this->translucent = translucent;
|
||||
translucentDepthWrite = BIT11(val);
|
||||
}
|
||||
|
||||
} polyAttr;
|
||||
|
||||
struct Fragment
|
||||
{
|
||||
union Color {
|
||||
|
@ -99,20 +185,20 @@ static struct
|
|||
wrap = (format>>16)&0xF;
|
||||
}
|
||||
|
||||
FORCEINLINE void clamp(int &val, int size, int sizemask){
|
||||
FORCEINLINE void clamp(int &val, const int size, const int sizemask){
|
||||
if(val<0) val = 0;
|
||||
if(val>sizemask) val = sizemask;
|
||||
}
|
||||
FORCEINLINE void hclamp(int &val) { clamp(val,width,wmask); }
|
||||
FORCEINLINE void vclamp(int &val) { clamp(val,height,hmask); }
|
||||
|
||||
FORCEINLINE void repeat(int &val, int size, int sizemask) {
|
||||
FORCEINLINE void repeat(int &val, const int size, const int sizemask) {
|
||||
val &= sizemask;
|
||||
}
|
||||
FORCEINLINE void hrepeat(int &val) { repeat(val,width,wmask); }
|
||||
FORCEINLINE void vrepeat(int &val) { repeat(val,height,hmask); }
|
||||
|
||||
FORCEINLINE void flip(int &val, int size, int sizemask) {
|
||||
FORCEINLINE void flip(int &val, const int size, const int sizemask) {
|
||||
val &= ((size<<1)-1);
|
||||
if(val>=size) val = (size<<1)-val-1;
|
||||
}
|
||||
|
@ -152,7 +238,7 @@ static struct
|
|||
dowrap(iu,iv);
|
||||
|
||||
Fragment::Color color;
|
||||
u32 col32 = ((u32*)TexCache_texMAP)[(iv<<wshift)+iu];
|
||||
u32 col32 = ((u32*)textures.currentData)[(iv<<wshift)+iu];
|
||||
//todo - teach texcache how to provide these already in 5555
|
||||
col32 >>= 3;
|
||||
col32 &= 0x1F1F1F1F;
|
||||
|
@ -250,6 +336,42 @@ struct Interpolator
|
|||
FORCEINLINE void incx(int count) { Z += dx*count; }
|
||||
};
|
||||
|
||||
void alphaBlend(Fragment & dst, const Fragment & src)
|
||||
{
|
||||
if(gfx3d.enableAlphaBlending)
|
||||
{
|
||||
if(src.color.components.a == 0)
|
||||
{
|
||||
dst.color.components.a = max(src.color.components.a,dst.color.components.a);
|
||||
}
|
||||
else if(src.color.components.a == 31 || dst.color.components.a == 0)
|
||||
{
|
||||
dst.color = src.color;
|
||||
dst.color.components.a = max(src.color.components.a,dst.color.components.a);
|
||||
}
|
||||
else
|
||||
{
|
||||
u8 alpha = src.color.components.a+1;
|
||||
u8 invAlpha = 32 - alpha;
|
||||
dst.color.components.r = (alpha*src.color.components.r + invAlpha*dst.color.components.r)>>5;
|
||||
dst.color.components.g = (alpha*src.color.components.g + invAlpha*dst.color.components.g)>>5;
|
||||
dst.color.components.b = (alpha*src.color.components.b + invAlpha*dst.color.components.b)>>5;
|
||||
dst.color.components.a = max(src.color.components.a,dst.color.components.a);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(src.color.components.a == 0)
|
||||
{
|
||||
//do nothing; the fragment is totally transparent
|
||||
}
|
||||
else
|
||||
{
|
||||
dst.color = src.color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//http://www.devmaster.net/forums/showthread.php?t=1884&page=1
|
||||
//todo - change to the tile-based renderer and try to apply some optimizations from that thread
|
||||
static void triangle_from_devmaster()
|
||||
|
@ -363,9 +485,16 @@ static void triangle_from_devmaster()
|
|||
//this is just a temporary measure until we do proper clipping against the clip frustum.
|
||||
//since we dont, we are receiving waaay out of bounds polys and so unless we do this we spend a lot of time calculating
|
||||
//out of bounds pixels
|
||||
i_color_r.incx(xaccum); i_color_g.incx(xaccum); i_color_b.incx(xaccum); i_color_a.incx(xaccum);
|
||||
i_tex_invu.incx(xaccum); i_tex_invv.incx(xaccum);
|
||||
i_w.incx(xaccum); i_invw.incx(xaccum);
|
||||
//if(xaccum==1) {
|
||||
// i_color_r.incx(); i_color_g.incx(); i_color_b.incx(); i_color_a.incx();
|
||||
// i_tex_invu.incx(); i_tex_invv.incx();
|
||||
// i_w.incx(); i_invw.incx();
|
||||
//} else {
|
||||
i_color_r.incx(xaccum); i_color_g.incx(xaccum); i_color_b.incx(xaccum); i_color_a.incx(xaccum);
|
||||
i_tex_invu.incx(xaccum); i_tex_invv.incx(xaccum);
|
||||
i_w.incx(xaccum); i_invw.incx(xaccum);
|
||||
//}
|
||||
|
||||
xaccum = 0;
|
||||
|
||||
int adr = (y<<8)+x;
|
||||
|
@ -373,8 +502,16 @@ static void triangle_from_devmaster()
|
|||
|
||||
//w-buffer depth test
|
||||
int w = i_w.cur();
|
||||
if(w>destFragment.depth)
|
||||
goto rejected_fragment;
|
||||
if(polyAttr.decalMode)
|
||||
{
|
||||
if(abs(w-destFragment.depth)>1)
|
||||
goto rejected_fragment;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(w>=destFragment.depth)
|
||||
goto rejected_fragment;
|
||||
}
|
||||
|
||||
shader.invw = i_invw.Z;
|
||||
shader.invu = i_tex_invu.Z;
|
||||
|
@ -396,24 +533,32 @@ static void triangle_from_devmaster()
|
|||
Fragment shaderOutput;
|
||||
shader.shade(shaderOutput);
|
||||
|
||||
//alpha blend
|
||||
if(shaderOutput.color.components.a == 31)
|
||||
//alpha test
|
||||
if(gfx3d.enableAlphaTest)
|
||||
{
|
||||
destFragment.color = shaderOutput.color;
|
||||
if(shaderOutput.color.components.a < gfx3d.alphaTestRef)
|
||||
goto rejected_fragment;
|
||||
}
|
||||
|
||||
//alpha blending
|
||||
alphaBlend(destFragment, shaderOutput);
|
||||
|
||||
//depth writing
|
||||
if(destFragment.color.components.a == 0)
|
||||
{
|
||||
//never update depth if the pixel is transparent
|
||||
}
|
||||
else
|
||||
{
|
||||
u8 alpha = shaderOutput.color.components.a+1;
|
||||
u8 invAlpha = 32 - alpha;
|
||||
destFragment.color.components.r = (alpha*shaderOutput.color.components.r + invAlpha*destFragment.color.components.r)>>5;
|
||||
destFragment.color.components.g = (alpha*shaderOutput.color.components.g + invAlpha*destFragment.color.components.g)>>5;
|
||||
destFragment.color.components.b = (alpha*shaderOutput.color.components.b + invAlpha*destFragment.color.components.b)>>5;
|
||||
destFragment.color.components.a = max(shaderOutput.color.components.a,destFragment.color.components.a);
|
||||
if(!polyAttr.translucent)
|
||||
destFragment.depth = w;
|
||||
else
|
||||
if(polyAttr.translucent && polyAttr.translucentDepthWrite)
|
||||
destFragment.depth = w;
|
||||
}
|
||||
|
||||
destFragment.depth = w;
|
||||
|
||||
} else if(done) break;
|
||||
|
||||
rejected_fragment:
|
||||
xaccum++;
|
||||
|
||||
|
@ -446,12 +591,18 @@ static char Init(void)
|
|||
for(int j=0;j<32;j++)
|
||||
modulate_table[i][j] = ((i+1)*(j+1)-1)>>5;
|
||||
|
||||
TexCache_Reset();
|
||||
TexCache_BindTexture = BindTexture;
|
||||
TexCache_BindTextureData = BindTextureData;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void Reset() {}
|
||||
|
||||
static void Close() {}
|
||||
static void Close()
|
||||
{
|
||||
}
|
||||
|
||||
static void VramReconfigureSignal() {
|
||||
TexCache_Invalidate();
|
||||
|
@ -462,7 +613,7 @@ static void GetLine(int line, u16* dst, u8* dstAlpha)
|
|||
Fragment* src = screen+((191-line)<<8);
|
||||
for(int i=0;i<256;i++)
|
||||
{
|
||||
|
||||
const bool testRenderAlpha = false;
|
||||
u8 r = src->color.components.r;
|
||||
u8 g = src->color.components.g;
|
||||
u8 b = src->color.components.b;
|
||||
|
@ -470,6 +621,13 @@ static void GetLine(int line, u16* dst, u8* dstAlpha)
|
|||
if(src->color.components.a > 0)
|
||||
*dst |= 0x8000;
|
||||
*dstAlpha = alpha_5bit_to_4bit[src->color.components.a];
|
||||
|
||||
if(testRenderAlpha)
|
||||
{
|
||||
*dst = 0x8000 | R5G5B5TORGB15(src->color.components.a,src->color.components.a,src->color.components.a);
|
||||
*dstAlpha = 16;
|
||||
}
|
||||
|
||||
src++;
|
||||
dst++;
|
||||
dstAlpha++;
|
||||
|
@ -487,9 +645,18 @@ static void Render()
|
|||
//B. backface cull
|
||||
//C. transforms
|
||||
|
||||
Fragment::Color clearColor;
|
||||
clearColor.components.r = gfx3d.clearColor&0x1F;
|
||||
clearColor.components.g = (gfx3d.clearColor>>5)&0x1F;
|
||||
clearColor.components.b = (gfx3d.clearColor>>10)&0x1F;
|
||||
clearColor.components.a = (gfx3d.clearColor>>16)&0x1F;
|
||||
memset(screen,0,sizeof(screen));
|
||||
for(int i=0;i<256*192;i++)
|
||||
{
|
||||
screen[i].depth = 0x007FFFFF;
|
||||
screen[i].color = clearColor;
|
||||
}
|
||||
|
||||
|
||||
for(int i=0;i<gfx3d.vertlist->count;i++)
|
||||
{
|
||||
|
@ -518,6 +685,8 @@ static void Render()
|
|||
type==4?&gfx3d.vertlist->list[poly->vertIndexes[3]]:0
|
||||
};
|
||||
|
||||
polyAttr.setup(poly->polyAttr, poly->isTranslucent());
|
||||
|
||||
//HACK: backface culling
|
||||
//this should be moved to gfx3d, but first we need to redo the way the lists are built
|
||||
//because it is too convoluted right now.
|
||||
|
@ -532,11 +701,14 @@ static void Render()
|
|||
Vector3Cross(cross,ab,ac);
|
||||
float view[3] = {0,0,1};
|
||||
float dot = Vector3Dot(view,cross);
|
||||
if(dot<0) {
|
||||
bool backfacing = dot<0;
|
||||
|
||||
if(!polyAttr.isVisible(backfacing)) {
|
||||
culled++;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(i==0 || lastTextureFormat != poly->texParam || lastTexturePalette != poly->texPalette || lastPolyAttr != poly->polyAttr)
|
||||
{
|
||||
TexCache_SetTexture(poly->texParam,poly->texPalette);
|
||||
|
@ -572,7 +744,6 @@ static void Render()
|
|||
|
||||
triangle_from_devmaster();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//printf("rendered %d of %d polys after backface culling\n",gfx3d.polylist->count-culled,gfx3d.polylist->count);
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
using std::min;
|
||||
using std::max;
|
||||
|
||||
#define DEBUG_DUMP_TEXTURE
|
||||
|
||||
//This class represents a number of regions of memory which should be viewed as contiguous
|
||||
class MemSpan
|
||||
{
|
||||
|
@ -129,35 +131,21 @@ static MemSpan MemSpan_TexPalette(u32 ofs, u32 len)
|
|||
return ret;
|
||||
}
|
||||
|
||||
//================================================= Textures
|
||||
TextureCache texcache[MAX_TEXTURE+1];
|
||||
//u32 texcache_count;
|
||||
u32 texcache_start;
|
||||
u32 texcache_stop;
|
||||
|
||||
|
||||
u8 TexCache_texMAP[1024*2048*4];
|
||||
//raw ds format poly attributes
|
||||
|
||||
//todo - make all color conversions go through a properly spread table!!
|
||||
|
||||
#if defined (DEBUG_DUMP_TEXTURE) && defined (WIN32)
|
||||
#define DO_DEBUG_DUMP_TEXTURE
|
||||
static void DebugDumpTexture(int which)
|
||||
{
|
||||
char fname[100];
|
||||
sprintf(fname,"c:\\dump\\%d.bmp", which);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D,texcache[which].id);
|
||||
glGetTexImage( GL_TEXTURE_2D ,
|
||||
0,
|
||||
GL_BGRA_EXT,
|
||||
GL_UNSIGNED_BYTE,
|
||||
TexCache_texMAP);
|
||||
|
||||
NDS_WriteBMP_32bppBuffer(texcache[which].sizeX,texcache[which].sizeY,TexCache_texMAP,fname);
|
||||
}
|
||||
#else
|
||||
#define DebugDumpTexture(which) do { (void)which; } while (0)
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -247,27 +235,26 @@ void TexCache_SetTexture(unsigned int format, unsigned int texpal)
|
|||
if (!texcache[tx].suspectedInvalid) goto ACCEPT;
|
||||
|
||||
//if we couldnt cache this entire texture due to it being too large, then reject it
|
||||
if (texSize+indexSize > (int)sizeof(texcache[tx].texture)) goto REJECT;
|
||||
if (texSize+indexSize > (int)sizeof(texcache[tx].dump.texture)) goto REJECT;
|
||||
|
||||
//when the palettes dont match:
|
||||
//note that we are considering 4x4 textures to have a palette size of 0.
|
||||
//they really have a potentially HUGE palette, too big for us to handle like a normal palette,
|
||||
//so they go through a different system
|
||||
if (mspal.size != 0 && memcmp(texcache[tx].palette,pal,mspal.size)) goto REJECT;
|
||||
if (mspal.size != 0 && memcmp(texcache[tx].dump.palette,pal,mspal.size)) goto REJECT;
|
||||
|
||||
//when the texture data doesn't match
|
||||
if(ms.memcmp(texcache[tx].texture,sizeof(texcache[tx].texture))) goto REJECT;
|
||||
if(ms.memcmp(texcache[tx].dump.texture,sizeof(texcache[tx].dump.texture))) goto REJECT;
|
||||
|
||||
//if the texture is 4x4 then the index data must match
|
||||
if(textureMode == TEXMODE_4X4)
|
||||
{
|
||||
if(msIndex.memcmp(texcache[tx].texture + texcache[tx].textureSize,texcache[tx].indexSize)) goto REJECT;
|
||||
if(msIndex.memcmp(texcache[tx].dump.texture + texcache[tx].dump.textureSize,texcache[tx].dump.indexSize)) goto REJECT;
|
||||
}
|
||||
|
||||
|
||||
ACCEPT:
|
||||
texcache[tx].suspectedInvalid = false;
|
||||
// texcache_count = tx;
|
||||
if(lastTexture == -1 || (int)tx != lastTexture)
|
||||
{
|
||||
lastTexture = tx;
|
||||
|
@ -303,27 +290,22 @@ REJECT:
|
|||
texcache[tx].sizeY=sizeY;
|
||||
texcache[tx].invSizeX=1.0f/((float)(sizeX));
|
||||
texcache[tx].invSizeY=1.0f/((float)(sizeY));
|
||||
texcache[tx].textureSize = ms.dump(texcache[tx].texture,sizeof(texcache[tx].texture));
|
||||
texcache[tx].dump.textureSize = ms.dump(texcache[tx].dump.texture,sizeof(texcache[tx].dump.texture));
|
||||
|
||||
//dump palette data for cache keying
|
||||
if ( palSize )
|
||||
{
|
||||
memcpy(texcache[tx].palette, pal, palSize*2);
|
||||
memcpy(texcache[tx].dump.palette, pal, palSize*2);
|
||||
}
|
||||
//dump 4x4 index data for cache keying
|
||||
texcache[tx].indexSize = 0;
|
||||
texcache[tx].dump.indexSize = 0;
|
||||
if(textureMode == TEXMODE_4X4)
|
||||
{
|
||||
texcache[tx].indexSize = min(msIndex.size,(int)sizeof(texcache[tx].texture) - texcache[tx].textureSize);
|
||||
msIndex.dump(texcache[tx].texture+texcache[tx].textureSize,texcache[tx].indexSize);
|
||||
texcache[tx].dump.indexSize = min(msIndex.size,(int)sizeof(texcache[tx].dump.texture) - texcache[tx].dump.textureSize);
|
||||
msIndex.dump(texcache[tx].dump.texture+texcache[tx].dump.textureSize,texcache[tx].dump.indexSize);
|
||||
}
|
||||
|
||||
|
||||
//glMatrixMode (GL_TEXTURE);
|
||||
//glLoadIdentity ();
|
||||
//glScaled (texcache[tx].invSizeX, texcache[tx].invSizeY, 1.0f);
|
||||
|
||||
|
||||
//INFO("Texture %03i - format=%08X; pal=%04X (mode %X, width %04i, height %04i)\n",i, texcache[i].frm, texcache[i].pal, texcache[i].mode, sizeX, sizeY);
|
||||
|
||||
//============================================================================ Texture conversion
|
||||
|
@ -392,7 +374,6 @@ REJECT:
|
|||
bits = ((*adr)>>4);
|
||||
c = pal[bits];
|
||||
*dwdst++ = RGB15TO32(c,(bits == 0) ? palZeroTransparent : 255);
|
||||
|
||||
adr++;
|
||||
}
|
||||
}
|
||||
|
@ -563,25 +544,18 @@ REJECT:
|
|||
if(TexCache_BindTextureData != 0)
|
||||
TexCache_BindTextureData(tx,TexCache_texMAP);
|
||||
|
||||
#ifdef DO_DEBUG_DUMP_TEXTURE
|
||||
DebugDumpTexture(tx);
|
||||
|
||||
//============================================================================================
|
||||
|
||||
// texcache_count=tx;
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void TexCache_Reset()
|
||||
{
|
||||
memset(&texcache,0,sizeof(texcache));
|
||||
memset(texcache,0,sizeof(texcache));
|
||||
|
||||
//texcache_count=0;
|
||||
texcache_start=0;
|
||||
texcache_stop=MAX_TEXTURE<<1;
|
||||
|
||||
for(int i=0;i<MAX_TEXTURE+1;i++)
|
||||
texcache[i].suspectedInvalid = true;
|
||||
}
|
||||
|
||||
TextureCache* TexCache_Curr()
|
||||
|
|
|
@ -18,9 +18,12 @@ struct ALIGN(8) TextureCache
|
|||
u32 sizeY;
|
||||
float invSizeX;
|
||||
float invSizeY;
|
||||
|
||||
struct {
|
||||
int textureSize, indexSize;
|
||||
u8 texture[128*1024]; // 128Kb texture slot
|
||||
u8 palette[256*2];
|
||||
} dump;
|
||||
|
||||
//set if this texture is suspected be invalid due to a vram reconfigure
|
||||
bool suspectedInvalid;
|
||||
|
|
|
@ -1082,6 +1082,10 @@
|
|||
RelativePath="..\render3D.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\render3D.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\ROMReader.cpp"
|
||||
>
|
||||
|
|
Loading…
Reference in New Issue