Sample the last texel where the projected q isn't positive

The GE doesn't divide by a q <= 0: it samples the last texel in u and v,
whatever s and t are, in clamp and repeat modes alike (gpu/texmtx/negq). The
hardware backends divided, which mirrors a projected texture behind its
projector: Fate/Extra's character shadows ran up the school's walls (#18667).
The software renderer sampled (0, 0) instead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Henrik RydgårdandClaude Opus 5.5 committed 2026-10-10 01:04:23 +02:00
1 parent b9b1a29c42
commit 763bcde73e
5 files changed
+29 -16

No files matched your search

+4 -4
View File
@@ -1236,8 +1236,8 @@ static inline void GetTextureCoordinatesGE(const UVPlanes &planes, const int64_t
const float q = TruncateToFloat24((float)((double)qs[i] * planes.scaleQ));
qOut[i] = q;
if (!(q > 0.0f)) {
s[i] = 0.0f;
t[i] = 0.0f;
s[i] = GE_NONPOSITIVE_Q_UV;
t[i] = GE_NONPOSITIVE_Q_UV;
continue;
}
const double r = GERecip(q);
@@ -2616,8 +2616,8 @@ static float LineUVComponentAt(const int64_t c[2], double scale, const VertexDat
static void LineTextureCoordinatesAt(const LineUV &uv, const VertexData &v0, const VertexData &v1, int px, int py, float &s, float &t, float &q) {
q = LineUVComponentAt(uv.q, uv.scaleQ, v0, v1, px, py);
if (!(q > 0.0f)) {
s = 0.0f;
t = 0.0f;
s = GE_NONPOSITIVE_Q_UV;
t = GE_NONPOSITIVE_Q_UV;
return;
}
const double r = GERecip(q);