From db610129bb951f3041e071783c785f4681d5d954 Mon Sep 17 00:00:00 2001 From: zeromus Date: Sun, 26 Jul 2009 21:13:38 +0000 Subject: [PATCH] rasterize: add fog emulation --- desmume/ChangeLog | 1 + desmume/src/gfx3d.cpp | 17 ++++++---- desmume/src/gfx3d.h | 20 +++++++++--- desmume/src/rasterize.cpp | 69 +++++++++++++++++++++++++++++++++++++-- 4 files changed, 93 insertions(+), 14 deletions(-) diff --git a/desmume/ChangeLog b/desmume/ChangeLog index 39a15d31f..2e02040c3 100644 --- a/desmume/ChangeLog +++ b/desmume/ChangeLog @@ -24,6 +24,7 @@ Graphics: bug: fix disp fifo capture bug: fix simultaneous vram display and capture via same bank bug: swrast: add clear image and scroll emulation + bug: swrast: add fog emulation bug: swrast: fixes to shadow rendering Windows: diff --git a/desmume/src/gfx3d.cpp b/desmume/src/gfx3d.cpp index 7cb9dd25f..377b79a37 100644 --- a/desmume/src/gfx3d.cpp +++ b/desmume/src/gfx3d.cpp @@ -1973,20 +1973,16 @@ void VIEWPORT::decode(u32 v) void gfx3d_glClearColor(u32 v) { gfx3d.clearColor = v; - } void gfx3d_glFogColor(u32 v) { - gfx3d.fogColor[0] = ((float)((v )&0x1F))/31.0f; - 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; + gfx3d.fogColor = v; } void gfx3d_glFogOffset (u32 v) { - gfx3d.fogOffset = (float)(v&0xffff); + gfx3d.fogOffset = (v&0x7fff); } void gfx3d_glClearDepth(u32 v) @@ -2307,7 +2303,10 @@ static void gfx3d_doFlush() gfx3d.enableAlphaBlending = BIT3(control); gfx3d.enableAntialiasing = BIT4(control); gfx3d.enableEdgeMarking = BIT5(control); + gfx3d.enableFogAlphaOnly = BIT6(control); + gfx3d.enableFog = BIT7(control); gfx3d.enableClearImage = BIT14(control); + gfx3d.fogShift = (control>>8)&0xF; int polycount = polylist->count; @@ -3123,6 +3122,10 @@ SFORMAT SF_GFX3D[]={ { "GSEB", 4, 1, &gfx3d.enableAlphaBlending}, { "GSEX", 4, 1, &gfx3d.enableAntialiasing}, { "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}, { "GSWB", 4, 1, &gfx3d.wbuffer}, { "GSSM", 4, 1, &gfx3d.sortmode}, @@ -3130,7 +3133,7 @@ SFORMAT SF_GFX3D[]={ { "GSVP", 4, 1, &viewport}, { "GSCC", 4, 1, &gfx3d.clearColor}, { "GSCD", 4, 1, &gfx3d.clearDepth}, - { "GSFC", 4, 4, gfx3d.fogColor}, + { "GSFC", 4, 4, &gfx3d.fogColor}, { "GSFO", 4, 1, &gfx3d.fogOffset}, { "GST2", 2, 32, gfx3d.u16ToonTable}, { "GSST", 4, 128, shininessTable}, diff --git a/desmume/src/gfx3d.h b/desmume/src/gfx3d.h index b22aa1951..7bc15962c 100644 --- a/desmume/src/gfx3d.h +++ b/desmume/src/gfx3d.h @@ -185,6 +185,9 @@ struct GFX3D , enableAntialiasing(false) , enableEdgeMarking(false) , enableClearImage(false) + , enableFog(false) + , enableFogAlphaOnly(false) + , fogShift(0) , shading(TOON) , polylist(0) , vertlist(0) @@ -193,12 +196,14 @@ struct GFX3D , clearColor(0) , frameCtr(0) , frameCtrRaw(0) + , fogOffset(0) + , fogColor(0) { - fogColor[0] = fogColor[1] = fogColor[2] = fogColor[3] = 0; - fogOffset = 0; } BOOL enableTexturing, enableAlphaTest, enableAlphaBlending, - enableAntialiasing, enableEdgeMarking, enableClearImage; + enableAntialiasing, enableEdgeMarking, enableClearImage, enableFog, enableFogAlphaOnly; + + u32 fogShift; static const u32 TOON = 0; static const u32 HIGHLIGHT = 1; @@ -214,8 +219,13 @@ struct GFX3D u32 clearDepth; u32 clearColor; - float fogColor[4]; - float fogOffset; + #include "PACKED.h" + 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 int frameCtr; diff --git a/desmume/src/rasterize.cpp b/desmume/src/rasterize.cpp index c324ed889..818d83230 100644 --- a/desmume/src/rasterize.cpp +++ b/desmume/src/rasterize.cpp @@ -194,6 +194,7 @@ struct PolyAttr u8 alpha; bool backfacing; bool translucent; + u8 fogged; bool isVisible(bool backfacing) { @@ -214,6 +215,7 @@ struct PolyAttr polyid = (polyAttr>>24)&0x3F; alpha = (polyAttr>>16)&0x1F; drawBackPlaneIntersectingPolys = BIT12(val); + fogged = BIT15(val); } } polyAttr; @@ -239,7 +241,10 @@ struct Fragment u8 stencil; - u8 isTranslucentPoly; + struct { + u8 isTranslucentPoly:1; + u8 fogged:1; + }; }; 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 FragmentColor screenColor[256*192]; static FragmentColor toonTable[32]; - +static u8 fogTable[32768]; FORCEINLINE int iround(float f) { 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.isTranslucentPoly = polyAttr.translucent?1:0; + destFragment.fogged = polyAttr.fogged; destFragmentColor = shaderOutput; } 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 alphaBlend(destFragmentColor, shaderOutput); + + destFragment.fogged &= polyAttr.fogged; } //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() @@ -1218,6 +1250,8 @@ static void SoftRastRender() clearFragment.polyid.translucent = kUnsetTranslucentPolyID; clearFragment.depth = gfx3d.clearDepth; clearFragment.stencil = 0; + clearFragment.isTranslucentPoly = 0; + clearFragment.fogged = BIT15(gfx3d.clearColor); for(int i=0;i<256*192;i++) screen[i] = clearFragment; @@ -1254,6 +1288,7 @@ static void SoftRastRender() depth &= 0x7FFF; //TODO - might consider a lookup table for this dst->depth = gfx3d_extendDepth_15_to_24(depth); + dst->fogged = BIT15(depth); dstColor++; dst++; @@ -1272,6 +1307,36 @@ static void SoftRastRender() 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(icount;i++) gfx3d.vertlist->list[i].color_to_float();