Merge pull request #2743 from wwylele/wrap-fix
pica/rasterizer: implement/stub texture wrap mode 4-7
This commit is contained in:
		| @@ -30,10 +30,10 @@ struct TexturingRegs { | ||||
|             Repeat = 2, | ||||
|             MirroredRepeat = 3, | ||||
|             // Mode 4-7 produces some weird result and may be just invalid: | ||||
|             // 4: Positive coord: clamp to edge; negative coord: repeat | ||||
|             // 5: Positive coord: clamp to border; negative coord: repeat | ||||
|             // 6: Repeat | ||||
|             // 7: Repeat | ||||
|             ClampToEdge2 = 4,   // Positive coord: clamp to edge; negative coord: repeat | ||||
|             ClampToBorder2 = 5, // Positive coord: clamp to border; negative coord: repeat | ||||
|             Repeat2 = 6,        // Same as Repeat | ||||
|             Repeat3 = 7,        // Same as Repeat | ||||
|         }; | ||||
|  | ||||
|         enum TextureFilter : u32 { | ||||
|   | ||||
| @@ -55,6 +55,12 @@ inline GLenum WrapMode(Pica::TexturingRegs::TextureConfig::WrapMode mode) { | ||||
|         GL_CLAMP_TO_BORDER, // WrapMode::ClampToBorder | ||||
|         GL_REPEAT,          // WrapMode::Repeat | ||||
|         GL_MIRRORED_REPEAT, // WrapMode::MirroredRepeat | ||||
|         // TODO(wwylele): ClampToEdge2 and ClampToBorder2 are not properly implemented here. See the | ||||
|         // comments in enum WrapMode. | ||||
|         GL_CLAMP_TO_EDGE,   // WrapMode::ClampToEdge2 | ||||
|         GL_CLAMP_TO_BORDER, // WrapMode::ClampToBorder2 | ||||
|         GL_REPEAT,          // WrapMode::Repeat2 | ||||
|         GL_REPEAT,          // WrapMode::Repeat3 | ||||
|     }; | ||||
|  | ||||
|     // Range check table for input | ||||
| @@ -65,6 +71,13 @@ inline GLenum WrapMode(Pica::TexturingRegs::TextureConfig::WrapMode mode) { | ||||
|         return GL_CLAMP_TO_EDGE; | ||||
|     } | ||||
|  | ||||
|     if (static_cast<u32>(mode) > 3) { | ||||
|         // It is still unclear whether mode 4-7 are valid, so log it if a game uses them. | ||||
|         // TODO(wwylele): telemetry should be added here so we can collect more info about which | ||||
|         // game uses this. | ||||
|         LOG_WARNING(Render_OpenGL, "Using texture wrap mode %u", static_cast<u32>(mode)); | ||||
|     } | ||||
|  | ||||
|     GLenum gl_mode = wrap_mode_table[mode]; | ||||
|  | ||||
|     // Check for dummy values indicating an unknown mode | ||||
|   | ||||
| @@ -357,10 +357,22 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve | ||||
|                 int t = (int)(v * float24::FromFloat32(static_cast<float>(texture.config.height))) | ||||
|                             .ToFloat32(); | ||||
|  | ||||
|                 if ((texture.config.wrap_s == TexturingRegs::TextureConfig::ClampToBorder && | ||||
|                      (s < 0 || static_cast<u32>(s) >= texture.config.width)) || | ||||
|                     (texture.config.wrap_t == TexturingRegs::TextureConfig::ClampToBorder && | ||||
|                      (t < 0 || static_cast<u32>(t) >= texture.config.height))) { | ||||
|                 bool use_border_s = false; | ||||
|                 bool use_border_t = false; | ||||
|  | ||||
|                 if (texture.config.wrap_s == TexturingRegs::TextureConfig::ClampToBorder) { | ||||
|                     use_border_s = s < 0 || s >= static_cast<int>(texture.config.width); | ||||
|                 } else if (texture.config.wrap_s == TexturingRegs::TextureConfig::ClampToBorder2) { | ||||
|                     use_border_s = s >= static_cast<int>(texture.config.width); | ||||
|                 } | ||||
|  | ||||
|                 if (texture.config.wrap_t == TexturingRegs::TextureConfig::ClampToBorder) { | ||||
|                     use_border_t = t < 0 || t >= static_cast<int>(texture.config.height); | ||||
|                 } else if (texture.config.wrap_t == TexturingRegs::TextureConfig::ClampToBorder2) { | ||||
|                     use_border_t = t >= static_cast<int>(texture.config.height); | ||||
|                 } | ||||
|  | ||||
|                 if (use_border_s || use_border_t) { | ||||
|                     auto border_color = texture.config.border_color; | ||||
|                     texture_color[i] = {border_color.r, border_color.g, border_color.b, | ||||
|                                         border_color.a}; | ||||
|   | ||||
| @@ -18,22 +18,33 @@ using TevStageConfig = TexturingRegs::TevStageConfig; | ||||
|  | ||||
| int GetWrappedTexCoord(TexturingRegs::TextureConfig::WrapMode mode, int val, unsigned size) { | ||||
|     switch (mode) { | ||||
|     case TexturingRegs::TextureConfig::ClampToEdge2: | ||||
|         // For negative coordinate, ClampToEdge2 behaves the same as Repeat | ||||
|         if (val < 0) { | ||||
|             return static_cast<int>(static_cast<unsigned>(val) % size); | ||||
|         } | ||||
|     // [[fallthrough]] | ||||
|     case TexturingRegs::TextureConfig::ClampToEdge: | ||||
|         val = std::max(val, 0); | ||||
|         val = std::min(val, (int)size - 1); | ||||
|         val = std::min(val, static_cast<int>(size) - 1); | ||||
|         return val; | ||||
|  | ||||
|     case TexturingRegs::TextureConfig::ClampToBorder: | ||||
|         return val; | ||||
|  | ||||
|     case TexturingRegs::TextureConfig::ClampToBorder2: | ||||
|     // For ClampToBorder2, the case of positive coordinate beyond the texture size is already | ||||
|     // handled outside. Here we only handle the negative coordinate in the same way as Repeat. | ||||
|     case TexturingRegs::TextureConfig::Repeat2: | ||||
|     case TexturingRegs::TextureConfig::Repeat3: | ||||
|     case TexturingRegs::TextureConfig::Repeat: | ||||
|         return (int)((unsigned)val % size); | ||||
|         return static_cast<int>(static_cast<unsigned>(val) % size); | ||||
|  | ||||
|     case TexturingRegs::TextureConfig::MirroredRepeat: { | ||||
|         unsigned int coord = ((unsigned)val % (2 * size)); | ||||
|         unsigned int coord = (static_cast<unsigned>(val) % (2 * size)); | ||||
|         if (coord >= size) | ||||
|             coord = 2 * size - 1 - coord; | ||||
|         return (int)coord; | ||||
|         return static_cast<int>(coord); | ||||
|     } | ||||
|  | ||||
|     default: | ||||
|   | ||||
		Reference in New Issue
	
	Block a user