diff --git a/src/xenia/gpu/dxbc_shader_translator_fetch.cc b/src/xenia/gpu/dxbc_shader_translator_fetch.cc index 25bf6d9d7..ee5f2ebc5 100644 --- a/src/xenia/gpu/dxbc_shader_translator_fetch.cc +++ b/src/xenia/gpu/dxbc_shader_translator_fetch.cc @@ -1373,23 +1373,26 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction( // It's probably applicable to tfetchCube too, we're going to assume it's // used for them the same way as for stacked textures. // http://web.archive.org/web/20090511231340/http://msdn.microsoft.com:80/en-us/library/bb313959.aspx - // Adding 1/1024 - quarter of one fixed-point unit of subpixel precision - // (not to touch rounding when the GPU is converting to fixed-point) - to - // resolve the ambiguity when the texture coordinate is directly between two - // pixels, which hurts nearest-neighbor sampling (fixes the XBLA logo being - // blocky in Banjo-Kazooie and the outlines around things and overall - // blockiness in Halo 3). - float offset_x = instr.attributes.offset_x; - if (instr.opcode != FetchOpcode::kGetTextureWeights) { - offset_x += 1.0f / 1024.0f; + // Subtracting 1/1024 - quarter of one fixed-point unit of subpixel + // precision (not to touch rounding when the GPU is converting to + // fixed-point) - to resolve the ambiguity when the texture coordinate is + // directly between two pixels, which hurts nearest-neighbor sampling (fixes + // the XBLA logo being blocky in Banjo-Kazooie and the outlines around + // things and overall blockiness in Halo 3). The sign was checked in Halo 3, + // with plus there are outlines when MSAA is enabled, and also outline + // around the weapon when it's drawn over a shadow. + float offset_x = instr.attributes.offset_x - (1.0f / 1024.0f); + if (instr.opcode == FetchOpcode::kGetTextureWeights) { + // Needed for correct shadow filtering (at least in Halo 3). + offset_x += 0.5f; } float offset_y = 0.0f, offset_z = 0.0f; if (instr.dimension == TextureDimension::k2D || instr.dimension == TextureDimension::k3D || instr.dimension == TextureDimension::kCube) { - offset_y = instr.attributes.offset_y; - if (instr.opcode != FetchOpcode::kGetTextureWeights) { - offset_y += 1.0f / 1024.0f; + offset_y = instr.attributes.offset_y - (1.0f / 1024.0f); + if (instr.opcode == FetchOpcode::kGetTextureWeights) { + offset_y += 0.5f; } // Don't care about the Z offset for cubemaps when getting weights because // zero Z will be returned anyway (the face index doesn't participate in @@ -1398,10 +1401,12 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction( (instr.dimension == TextureDimension::kCube && instr.opcode != FetchOpcode::kGetTextureWeights)) { offset_z = instr.attributes.offset_z; - if (instr.opcode != FetchOpcode::kGetTextureWeights && - instr.dimension == TextureDimension::k3D) { + if (instr.dimension == TextureDimension::k3D) { // Z is the face index for cubemaps, so don't apply the epsilon to it. - offset_z += 1.0f / 1024.0f; + offset_z -= 1.0f / 1024.0f; + if (instr.opcode == FetchOpcode::kGetTextureWeights) { + offset_z += 0.5f; + } } } }