diff --git a/Source/Core/VideoCommon/Src/BPMemory.h b/Source/Core/VideoCommon/Src/BPMemory.h index 9ffdce0582..1a29439b36 100644 --- a/Source/Core/VideoCommon/Src/BPMemory.h +++ b/Source/Core/VideoCommon/Src/BPMemory.h @@ -686,8 +686,9 @@ union FogRangeKElement u32 LO : 12; u32 regid : 8; }; + // TODO: Which scaling coefficient should we use here? This is just a guess! - float GetValue(int i) { return (i ? HI : LO) / 32.f; } + float GetValue(int i) { return (i ? HI : LO) / 256.f; } u32 HEX; }; @@ -697,7 +698,7 @@ struct FogRangeParams { struct { - u32 Center : 10; + u32 Center : 10; // viewport center + 342 u32 Enabled : 1; u32 unused : 13; u32 regid : 8; diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/Tev.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/Tev.cpp index 7aa4420e62..fa072508eb 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/Tev.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/Tev.cpp @@ -20,6 +20,7 @@ #include "Tev.h" #include "EfbInterface.h" #include "TextureSampler.h" +#include "XFMemLoader.h" #include "SWPixelEngine.h" #include "SWStatistics.h" #include "SWVideoConfig.h" @@ -750,12 +751,19 @@ void Tev::Draw() if(bpmem.fogRange.Base.Enabled) { - // TODO: Check if this is correct (especially the magic values) - float offset = Position[0] - bpmem.fogRange.Base.Center + 324.f; - int index = 9 - std::abs(Position[0] - bpmem.fogRange.Base.Center + 324) / (162/5); - float k = bpmem.fogRange.K[index/2].GetValue(index%2); - float x_adjust = sqrt(offset*offset/162.f/162.f + k*k)/k; - ze *= x_adjust; + // TODO: This is untested and should definitely be checked against real hw. + // - No idea if offset is really normalized against the viewport width or against the projection matrix or yet something else + // - scaling of the "k" coefficient isn't clear either. + + // First, calculate the offset from the viewport center (normalized to 0..1) + float offset = (Position[0] - (bpmem.fogRange.Base.Center - 342)) / (float)swxfregs.viewport.wd; + // Based on that, choose the index such that points which are far away from the z-axis use the 10th "k" value and such that central points use the first value. + int index = 9 - std::abs(offset) * 9.f; + index = (index < 0) ? 0 : (index > 9) ? 9 : 0; // TODO: Shouldn't be necessary! + // Look up coefficient... Seems like multiplying by 4 makes Fortune Street work properly (fog is too strong without the factor) + float k = bpmem.fogRange.K[index/2].GetValue(index%2) * 4.f; + float x_adjust = sqrt(offset*offset + k*k)/k; + ze *= x_adjust; // NOTE: This is basically dividing by a cosine (hidden behind GXInitFogAdjTable): 1/cos = c/b = sqrt(a^2+b^2)/b } ze -= bpmem.fog.c_proj_fsel.GetC(); diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/TransformUnit.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/TransformUnit.cpp index c95365eddd..e7bb4b91f2 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/TransformUnit.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/TransformUnit.cpp @@ -88,13 +88,13 @@ void TransformPosition(const InputVertexData *src, OutputVertexData *dst) const float* mat = (const float*)&swxfregs.posMatrices[src->posMtx * 4]; MultiplyVec3Mat34(src->position, mat, dst->mvPosition); - if (swxfregs.projection[6] == 0) + if (swxfregs.projection.type == GX_PERSPECTIVE) { - MultipleVec3Perspective(dst->mvPosition, swxfregs.projection, dst->projectedPosition); + MultipleVec3Perspective(dst->mvPosition, swxfregs.projection.rawProjection, dst->projectedPosition); } else { - MultipleVec3Ortho(dst->mvPosition, swxfregs.projection, dst->projectedPosition); + MultipleVec3Ortho(dst->mvPosition, swxfregs.projection.rawProjection, dst->projectedPosition); } } diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/XFMemLoader.h b/Source/Plugins/Plugin_VideoSoftware/Src/XFMemLoader.h index f5bb8c3c43..86e8e6c9d8 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/XFMemLoader.h +++ b/Source/Plugins/Plugin_VideoSoftware/Src/XFMemLoader.h @@ -85,6 +85,9 @@ struct Light #define LIGHTATTN_NONE 2 #define LIGHTATTN_DIR 3 +#define GX_PERSPECTIVE 0 +#define GX_ORTHOGRAPHIC 1 + union LitChannel { struct @@ -160,6 +163,12 @@ struct Viewport float farZ; }; +struct Projection +{ + float rawProjection[6]; + u32 type; // only GX_PERSPECTIVE or GX_ORTHOGRAPHIC are allowed +}; + union TexMtxInfo { struct @@ -218,7 +227,7 @@ struct XFRegisters TXFMatrixIndexA MatrixIndexA; // 0x1018 TXFMatrixIndexB MatrixIndexB; // 0x1019 Viewport viewport; // 0x101a - 0x101f - float projection[7]; // 0x1020 - 0x1026 + Projection projection; // 0x1020 - 0x1026 u32 unk8[24]; // 0x1027 - 0x103e u32 numTexGens; // 0x103f TexMtxInfo texMtxInfo[8]; // 0x1040 - 0x1047