rasterize: add fog emulation
This commit is contained in:
parent
9828895c53
commit
db610129bb
|
@ -24,6 +24,7 @@ Graphics:
|
||||||
bug: fix disp fifo capture
|
bug: fix disp fifo capture
|
||||||
bug: fix simultaneous vram display and capture via same bank
|
bug: fix simultaneous vram display and capture via same bank
|
||||||
bug: swrast: add clear image and scroll emulation
|
bug: swrast: add clear image and scroll emulation
|
||||||
|
bug: swrast: add fog emulation
|
||||||
bug: swrast: fixes to shadow rendering
|
bug: swrast: fixes to shadow rendering
|
||||||
|
|
||||||
Windows:
|
Windows:
|
||||||
|
|
|
@ -1973,20 +1973,16 @@ void VIEWPORT::decode(u32 v)
|
||||||
void gfx3d_glClearColor(u32 v)
|
void gfx3d_glClearColor(u32 v)
|
||||||
{
|
{
|
||||||
gfx3d.clearColor = v;
|
gfx3d.clearColor = v;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void gfx3d_glFogColor(u32 v)
|
void gfx3d_glFogColor(u32 v)
|
||||||
{
|
{
|
||||||
gfx3d.fogColor[0] = ((float)((v )&0x1F))/31.0f;
|
gfx3d.fogColor = v;
|
||||||
gfx3d.fogColor[1] = ((float)((v>> 5)&0x1F))/31.0f;
|
|
||||||
gfx3d.fogColor[2] = ((float)((v>>10)&0x1F))/31.0f;
|
|
||||||
gfx3d.fogColor[3] = ((float)((v>>16)&0x1F))/31.0f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void gfx3d_glFogOffset (u32 v)
|
void gfx3d_glFogOffset (u32 v)
|
||||||
{
|
{
|
||||||
gfx3d.fogOffset = (float)(v&0xffff);
|
gfx3d.fogOffset = (v&0x7fff);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gfx3d_glClearDepth(u32 v)
|
void gfx3d_glClearDepth(u32 v)
|
||||||
|
@ -2307,7 +2303,10 @@ static void gfx3d_doFlush()
|
||||||
gfx3d.enableAlphaBlending = BIT3(control);
|
gfx3d.enableAlphaBlending = BIT3(control);
|
||||||
gfx3d.enableAntialiasing = BIT4(control);
|
gfx3d.enableAntialiasing = BIT4(control);
|
||||||
gfx3d.enableEdgeMarking = BIT5(control);
|
gfx3d.enableEdgeMarking = BIT5(control);
|
||||||
|
gfx3d.enableFogAlphaOnly = BIT6(control);
|
||||||
|
gfx3d.enableFog = BIT7(control);
|
||||||
gfx3d.enableClearImage = BIT14(control);
|
gfx3d.enableClearImage = BIT14(control);
|
||||||
|
gfx3d.fogShift = (control>>8)&0xF;
|
||||||
|
|
||||||
int polycount = polylist->count;
|
int polycount = polylist->count;
|
||||||
|
|
||||||
|
@ -3123,6 +3122,10 @@ SFORMAT SF_GFX3D[]={
|
||||||
{ "GSEB", 4, 1, &gfx3d.enableAlphaBlending},
|
{ "GSEB", 4, 1, &gfx3d.enableAlphaBlending},
|
||||||
{ "GSEX", 4, 1, &gfx3d.enableAntialiasing},
|
{ "GSEX", 4, 1, &gfx3d.enableAntialiasing},
|
||||||
{ "GSEE", 4, 1, &gfx3d.enableEdgeMarking},
|
{ "GSEE", 4, 1, &gfx3d.enableEdgeMarking},
|
||||||
|
{ "GSEC", 4, 1, &gfx3d.enableClearImage},
|
||||||
|
{ "GSEF", 4, 1, &gfx3d.enableFog},
|
||||||
|
{ "GSEO", 4, 1, &gfx3d.enableFogAlphaOnly},
|
||||||
|
{ "GFSH", 4, 1, &gfx3d.fogShift},
|
||||||
{ "GSSH", 4, 1, &gfx3d.shading},
|
{ "GSSH", 4, 1, &gfx3d.shading},
|
||||||
{ "GSWB", 4, 1, &gfx3d.wbuffer},
|
{ "GSWB", 4, 1, &gfx3d.wbuffer},
|
||||||
{ "GSSM", 4, 1, &gfx3d.sortmode},
|
{ "GSSM", 4, 1, &gfx3d.sortmode},
|
||||||
|
@ -3130,7 +3133,7 @@ SFORMAT SF_GFX3D[]={
|
||||||
{ "GSVP", 4, 1, &viewport},
|
{ "GSVP", 4, 1, &viewport},
|
||||||
{ "GSCC", 4, 1, &gfx3d.clearColor},
|
{ "GSCC", 4, 1, &gfx3d.clearColor},
|
||||||
{ "GSCD", 4, 1, &gfx3d.clearDepth},
|
{ "GSCD", 4, 1, &gfx3d.clearDepth},
|
||||||
{ "GSFC", 4, 4, gfx3d.fogColor},
|
{ "GSFC", 4, 4, &gfx3d.fogColor},
|
||||||
{ "GSFO", 4, 1, &gfx3d.fogOffset},
|
{ "GSFO", 4, 1, &gfx3d.fogOffset},
|
||||||
{ "GST2", 2, 32, gfx3d.u16ToonTable},
|
{ "GST2", 2, 32, gfx3d.u16ToonTable},
|
||||||
{ "GSST", 4, 128, shininessTable},
|
{ "GSST", 4, 128, shininessTable},
|
||||||
|
|
|
@ -185,6 +185,9 @@ struct GFX3D
|
||||||
, enableAntialiasing(false)
|
, enableAntialiasing(false)
|
||||||
, enableEdgeMarking(false)
|
, enableEdgeMarking(false)
|
||||||
, enableClearImage(false)
|
, enableClearImage(false)
|
||||||
|
, enableFog(false)
|
||||||
|
, enableFogAlphaOnly(false)
|
||||||
|
, fogShift(0)
|
||||||
, shading(TOON)
|
, shading(TOON)
|
||||||
, polylist(0)
|
, polylist(0)
|
||||||
, vertlist(0)
|
, vertlist(0)
|
||||||
|
@ -193,12 +196,14 @@ struct GFX3D
|
||||||
, clearColor(0)
|
, clearColor(0)
|
||||||
, frameCtr(0)
|
, frameCtr(0)
|
||||||
, frameCtrRaw(0)
|
, frameCtrRaw(0)
|
||||||
|
, fogOffset(0)
|
||||||
|
, fogColor(0)
|
||||||
{
|
{
|
||||||
fogColor[0] = fogColor[1] = fogColor[2] = fogColor[3] = 0;
|
|
||||||
fogOffset = 0;
|
|
||||||
}
|
}
|
||||||
BOOL enableTexturing, enableAlphaTest, enableAlphaBlending,
|
BOOL enableTexturing, enableAlphaTest, enableAlphaBlending,
|
||||||
enableAntialiasing, enableEdgeMarking, enableClearImage;
|
enableAntialiasing, enableEdgeMarking, enableClearImage, enableFog, enableFogAlphaOnly;
|
||||||
|
|
||||||
|
u32 fogShift;
|
||||||
|
|
||||||
static const u32 TOON = 0;
|
static const u32 TOON = 0;
|
||||||
static const u32 HIGHLIGHT = 1;
|
static const u32 HIGHLIGHT = 1;
|
||||||
|
@ -214,8 +219,13 @@ struct GFX3D
|
||||||
|
|
||||||
u32 clearDepth;
|
u32 clearDepth;
|
||||||
u32 clearColor;
|
u32 clearColor;
|
||||||
float fogColor[4];
|
#include "PACKED.h"
|
||||||
float fogOffset;
|
struct {
|
||||||
|
u32 fogColor;
|
||||||
|
u32 pad[3]; //for savestate compatibility as of 26-jul-09
|
||||||
|
};
|
||||||
|
#include "PACKED_END.h"
|
||||||
|
u32 fogOffset;
|
||||||
|
|
||||||
//ticks every time flush() is called
|
//ticks every time flush() is called
|
||||||
int frameCtr;
|
int frameCtr;
|
||||||
|
|
|
@ -194,6 +194,7 @@ struct PolyAttr
|
||||||
u8 alpha;
|
u8 alpha;
|
||||||
bool backfacing;
|
bool backfacing;
|
||||||
bool translucent;
|
bool translucent;
|
||||||
|
u8 fogged;
|
||||||
|
|
||||||
bool isVisible(bool backfacing)
|
bool isVisible(bool backfacing)
|
||||||
{
|
{
|
||||||
|
@ -214,6 +215,7 @@ struct PolyAttr
|
||||||
polyid = (polyAttr>>24)&0x3F;
|
polyid = (polyAttr>>24)&0x3F;
|
||||||
alpha = (polyAttr>>16)&0x1F;
|
alpha = (polyAttr>>16)&0x1F;
|
||||||
drawBackPlaneIntersectingPolys = BIT12(val);
|
drawBackPlaneIntersectingPolys = BIT12(val);
|
||||||
|
fogged = BIT15(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
} polyAttr;
|
} polyAttr;
|
||||||
|
@ -239,7 +241,10 @@ struct Fragment
|
||||||
|
|
||||||
u8 stencil;
|
u8 stencil;
|
||||||
|
|
||||||
u8 isTranslucentPoly;
|
struct {
|
||||||
|
u8 isTranslucentPoly:1;
|
||||||
|
u8 fogged:1;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
static VERT* verts[MAX_CLIPPED_VERTS];
|
static VERT* verts[MAX_CLIPPED_VERTS];
|
||||||
|
@ -252,7 +257,7 @@ INLINE static void SubmitVertex(int vert_index, VERT& rawvert)
|
||||||
static Fragment screen[256*192];
|
static Fragment screen[256*192];
|
||||||
static FragmentColor screenColor[256*192];
|
static FragmentColor screenColor[256*192];
|
||||||
static FragmentColor toonTable[32];
|
static FragmentColor toonTable[32];
|
||||||
|
static u8 fogTable[32768];
|
||||||
|
|
||||||
FORCEINLINE int iround(float f) {
|
FORCEINLINE int iround(float f) {
|
||||||
return (int)f; //lol
|
return (int)f; //lol
|
||||||
|
@ -559,6 +564,7 @@ static FORCEINLINE void pixel(int adr,float r, float g, float b, float invu, flo
|
||||||
{
|
{
|
||||||
destFragment.polyid.opaque = polyAttr.polyid;
|
destFragment.polyid.opaque = polyAttr.polyid;
|
||||||
destFragment.isTranslucentPoly = polyAttr.translucent?1:0;
|
destFragment.isTranslucentPoly = polyAttr.translucent?1:0;
|
||||||
|
destFragment.fogged = polyAttr.fogged;
|
||||||
destFragmentColor = shaderOutput;
|
destFragmentColor = shaderOutput;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -584,6 +590,8 @@ static FORCEINLINE void pixel(int adr,float r, float g, float b, float invu, flo
|
||||||
|
|
||||||
//alpha blending and write color
|
//alpha blending and write color
|
||||||
alphaBlend(destFragmentColor, shaderOutput);
|
alphaBlend(destFragmentColor, shaderOutput);
|
||||||
|
|
||||||
|
destFragment.fogged &= polyAttr.fogged;
|
||||||
}
|
}
|
||||||
|
|
||||||
//depth writing
|
//depth writing
|
||||||
|
@ -1010,6 +1018,30 @@ static void SoftRastFramebufferProcess()
|
||||||
|
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
if(gfx3d.enableFog)
|
||||||
|
{
|
||||||
|
u32 r = gfx3d.fogColor&0x1F;
|
||||||
|
u32 g = (gfx3d.fogColor>>5)&0x1F;
|
||||||
|
u32 b = (gfx3d.fogColor>>10)&0x1F;
|
||||||
|
u32 a = (gfx3d.fogColor>>16)&0x1F;
|
||||||
|
for(int i=0;i<256*192;i++)
|
||||||
|
{
|
||||||
|
Fragment &destFragment = screen[i];
|
||||||
|
if(!destFragment.fogged) continue;
|
||||||
|
FragmentColor &destFragmentColor = screenColor[i];
|
||||||
|
u32 fogIndex = destFragment.depth>>9;
|
||||||
|
assert(fogIndex<32768);
|
||||||
|
u8 fog = fogTable[fogIndex];
|
||||||
|
if(fog==127) fog=128;
|
||||||
|
if(!gfx3d.enableFogAlphaOnly)
|
||||||
|
{
|
||||||
|
destFragmentColor.r = ((128-fog)*destFragmentColor.r + r*fog)>>7;
|
||||||
|
destFragmentColor.g = ((128-fog)*destFragmentColor.g + g*fog)>>7;
|
||||||
|
destFragmentColor.b = ((128-fog)*destFragmentColor.b + b*fog)>>7;
|
||||||
|
}
|
||||||
|
destFragmentColor.a = ((128-fog)*destFragmentColor.a + a*fog)>>7;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SoftRastConvertFramebuffer()
|
static void SoftRastConvertFramebuffer()
|
||||||
|
@ -1218,6 +1250,8 @@ static void SoftRastRender()
|
||||||
clearFragment.polyid.translucent = kUnsetTranslucentPolyID;
|
clearFragment.polyid.translucent = kUnsetTranslucentPolyID;
|
||||||
clearFragment.depth = gfx3d.clearDepth;
|
clearFragment.depth = gfx3d.clearDepth;
|
||||||
clearFragment.stencil = 0;
|
clearFragment.stencil = 0;
|
||||||
|
clearFragment.isTranslucentPoly = 0;
|
||||||
|
clearFragment.fogged = BIT15(gfx3d.clearColor);
|
||||||
for(int i=0;i<256*192;i++)
|
for(int i=0;i<256*192;i++)
|
||||||
screen[i] = clearFragment;
|
screen[i] = clearFragment;
|
||||||
|
|
||||||
|
@ -1254,6 +1288,7 @@ static void SoftRastRender()
|
||||||
depth &= 0x7FFF;
|
depth &= 0x7FFF;
|
||||||
//TODO - might consider a lookup table for this
|
//TODO - might consider a lookup table for this
|
||||||
dst->depth = gfx3d_extendDepth_15_to_24(depth);
|
dst->depth = gfx3d_extendDepth_15_to_24(depth);
|
||||||
|
dst->fogged = BIT15(depth);
|
||||||
|
|
||||||
dstColor++;
|
dstColor++;
|
||||||
dst++;
|
dst++;
|
||||||
|
@ -1272,6 +1307,36 @@ static void SoftRastRender()
|
||||||
toonTable[i].b = (gfx3d.u16ToonTable[i]>>10)&0x1F;
|
toonTable[i].b = (gfx3d.u16ToonTable[i]>>10)&0x1F;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//setup fog variables (but only if fog is enabled)
|
||||||
|
if(gfx3d.enableFog)
|
||||||
|
{
|
||||||
|
u8* fogDensity = MMU.MMU_MEM[ARMCPU_ARM9][0x40] + 0x360;
|
||||||
|
//TODO - this might be a little slow;
|
||||||
|
//we might need to hash all the variables and only recompute this when something changes
|
||||||
|
const int increment = (0x400 >> gfx3d.fogShift);
|
||||||
|
for(u32 i=0;i<32768;i++) {
|
||||||
|
if(i<gfx3d.fogOffset) {
|
||||||
|
fogTable[i] = fogDensity[0];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for(int j=0;j<31;j++) {
|
||||||
|
u32 value = gfx3d.fogOffset + increment*(j+1);
|
||||||
|
if(i<=value) {
|
||||||
|
if(j==0) {
|
||||||
|
fogTable[i] = fogDensity[0];
|
||||||
|
goto done;
|
||||||
|
} else {
|
||||||
|
int lastValue = value - increment;
|
||||||
|
fogTable[i] = ((value-i)*fogDensity[j-1] + (increment-(value-i))*fogDensity[j])/increment;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fogTable[i] = fogDensity[31];
|
||||||
|
done: ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//convert colors to float to get more precision in case we need it
|
//convert colors to float to get more precision in case we need it
|
||||||
for(int i=0;i<gfx3d.vertlist->count;i++)
|
for(int i=0;i<gfx3d.vertlist->count;i++)
|
||||||
gfx3d.vertlist->list[i].color_to_float();
|
gfx3d.vertlist->list[i].color_to_float();
|
||||||
|
|
Loading…
Reference in New Issue