diff --git a/Source/Core/VideoBackends/Software/TransformUnit.cpp b/Source/Core/VideoBackends/Software/TransformUnit.cpp index 57492cc326..38734fa17c 100644 --- a/Source/Core/VideoBackends/Software/TransformUnit.cpp +++ b/Source/Core/VideoBackends/Software/TransformUnit.cpp @@ -106,24 +106,26 @@ void TransformNormal(const InputVertexData* src, bool nbt, OutputVertexData* dst static void TransformTexCoordRegular(const TexMtxInfo& texinfo, int coordNum, bool specialCase, const InputVertexData* srcVertex, OutputVertexData* dstVertex) { - const Vec3* src; + Vec3 src; switch (texinfo.sourcerow) { case XF_SRCGEOM_INROW: - src = &srcVertex->position; + src = srcVertex->position; break; case XF_SRCNORMAL_INROW: - src = &srcVertex->normal[0]; + src = srcVertex->normal[0]; break; case XF_SRCBINORMAL_T_INROW: - src = &srcVertex->normal[1]; + src = srcVertex->normal[1]; break; case XF_SRCBINORMAL_B_INROW: - src = &srcVertex->normal[2]; + src = srcVertex->normal[2]; break; default: _assert_(texinfo.sourcerow >= XF_SRCTEX0_INROW && texinfo.sourcerow <= XF_SRCTEX7_INROW); - src = (Vec3*)srcVertex->texCoords[texinfo.sourcerow - XF_SRCTEX0_INROW]; + src.x = srcVertex->texCoords[texinfo.sourcerow - XF_SRCTEX0_INROW][0]; + src.y = srcVertex->texCoords[texinfo.sourcerow - XF_SRCTEX0_INROW][1]; + src.z = 1.0f; break; } @@ -133,18 +135,18 @@ static void TransformTexCoordRegular(const TexMtxInfo& texinfo, int coordNum, bo if (texinfo.projection == XF_TEXPROJ_ST) { if (texinfo.inputform == XF_TEXINPUT_AB11 || specialCase) - MultiplyVec2Mat24(*src, mat, *dst); + MultiplyVec2Mat24(src, mat, *dst); else - MultiplyVec3Mat24(*src, mat, *dst); + MultiplyVec3Mat24(src, mat, *dst); } else // texinfo.projection == XF_TEXPROJ_STQ { _assert_(!specialCase); if (texinfo.inputform == XF_TEXINPUT_AB11) - MultiplyVec2Mat34(*src, mat, *dst); + MultiplyVec2Mat34(src, mat, *dst); else - MultiplyVec3Mat34(*src, mat, *dst); + MultiplyVec3Mat34(src, mat, *dst); } if (xfmem.dualTexTrans.enabled) @@ -177,6 +179,15 @@ static void TransformTexCoordRegular(const TexMtxInfo& texinfo, int coordNum, bo MultiplyVec3Mat34(tempCoord, postMat, *dst); } } + + // When q is 0, the GameCube appears to have a special case + // This can be seen in devkitPro's neheGX Lesson08 example for Wii + // Makes differences in Rogue Squadron 3 (Hoth sky) and The Last Story (shadow culling) + if (dst->z == 0.0f) + { + dst->x = MathUtil::Clamp(dst->x / 2.0f, -1.0f, 1.0f); + dst->y = MathUtil::Clamp(dst->y / 2.0f, -1.0f, 1.0f); + } } struct LightPointer diff --git a/Source/Core/VideoCommon/VertexShaderGen.cpp b/Source/Core/VideoCommon/VertexShaderGen.cpp index a42f090716..5c516e0053 100644 --- a/Source/Core/VideoCommon/VertexShaderGen.cpp +++ b/Source/Core/VideoCommon/VertexShaderGen.cpp @@ -381,6 +381,16 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const vertex_shader_uid_da i, i, i, i); } + // When q is 0, the GameCube appears to have a special case + // This can be seen in devkitPro's neheGX Lesson08 example for Wii + // Makes differences in Rogue Squadron 3 (Hoth sky) and The Last Story (shadow culling) + // TODO: check if this only affects XF_TEXGEN_REGULAR + if (texinfo.texgentype == XF_TEXGEN_REGULAR) + { + out.Write("if(o.tex%d.z == 0.0f)\n", i); + out.Write("\to.tex%d.xy = clamp(o.tex%d.xy / 2.0f, float2(-1.0f), float2(1.0f));\n", i, i); + } + out.Write("}\n"); }