Skip to content

Commit 3b9c904

Browse files
committed
Improve texture clamping and mirroring
1 parent 05b9028 commit 3b9c904

File tree

1 file changed

+43
-45
lines changed

1 file changed

+43
-45
lines changed

src/rdp.cpp

+43-45
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,12 @@ enum CycleType
4545

4646
struct Tile
4747
{
48-
uint16_t sBase;
48+
uint16_t s1, s2;
4949
uint16_t sMask;
5050
bool sMirror;
5151
bool sClamp;
5252

53-
uint16_t tBase;
53+
uint16_t t1, t2;
5454
uint16_t tMask;
5555
bool tMirror;
5656
bool tClamp;
@@ -365,8 +365,8 @@ inline uint32_t RDP::colorToAlpha(uint32_t color)
365365
uint32_t RDP::getTexel(Tile &tile, int s, int t, bool rect)
366366
{
367367
// Offset the texture coordinates relative to the tile
368-
s -= tile.sBase;
369-
t -= tile.tBase;
368+
s -= tile.s1;
369+
t -= tile.t1;
370370

371371
// Fall back to nearest sampling, or filter based on https://www.shadertoy.com/view/Ws2fWV
372372
if (!Settings::texFilter || !texFilter || cycleType >= COPY_MODE)
@@ -407,20 +407,14 @@ uint32_t RDP::getTexel(Tile &tile, int s, int t, bool rect)
407407
uint32_t RDP::getRawTexel(Tile &tile, int s, int t)
408408
{
409409
// Clamp, mirror, or mask the S-coordinate based on tile settings
410-
if (tile.sClamp)
411-
s = std::max<int>(std::min<int>(s, tile.sMask), 0);
412-
else if (tile.sMirror)
413-
s = ((s & (tile.sMask + 1)) ? ~s : s) & tile.sMask;
414-
else
415-
s &= tile.sMask;
410+
if (tile.sClamp) s = std::max<int>(std::min<int>(s, (tile.s2 - tile.s1) >> 5), 0);
411+
if (tile.sMirror && (s & (tile.sMask + 1))) s = ~s;
412+
s &= tile.sMask;
416413

417414
// Clamp, mirror, or mask the T-coordinate based on tile settings
418-
if (tile.tClamp)
419-
t = std::max<int>(std::min<int>(t, tile.tMask), 0);
420-
else if (tile.tMirror)
421-
t = ((t & (tile.tMask + 1)) ? ~t : t) & tile.tMask;
422-
else
423-
t &= tile.tMask;
415+
if (tile.tClamp) t = std::max<int>(std::min<int>(t, (tile.t2 - tile.t1) >> 5), 0);
416+
if (tile.tMirror && (t & (tile.tMask + 1))) t = ~t;
417+
t &= tile.tMask;
424418

425419
// Get an RGBA32 texel from a tile at the given coordinates
426420
switch (tile.format)
@@ -1438,40 +1432,48 @@ void RDP::setOtherModes()
14381432

14391433
void RDP::loadTlut()
14401434
{
1441-
// Decode the operands
1435+
// Decode the operands and set texture coordinate bounds
14421436
Tile &tile = tiles[(opcode[0] >> 24) & 0x7];
1443-
uint16_t indexL = ((opcode[0] >> 44) & 0xFFF) >> 1;
1444-
uint16_t indexH = ((opcode[0] >> 12) & 0xFFF) >> 1;
1445-
1446-
// Copy 16-bit texture lookup values into TMEM
1447-
for (int i = indexL; i <= indexH; i += 2)
1437+
uint16_t s1 = (tile.s1 = ((opcode[0] >> 44) & 0xFFF) << 3) >> 4;
1438+
uint16_t t1 = (tile.t1 = ((opcode[0] >> 32) & 0xFFF) << 3) >> 4;
1439+
uint16_t s2 = (tile.s2 = ((opcode[0] >> 12) & 0xFFF) << 3) >> 4;
1440+
uint16_t t2 = (tile.t2 = ((opcode[0] >> 0) & 0xFFF) << 3) >> 4;
1441+
1442+
// Copy 16-bit texture lookup values into TMEM, duplicated 4 times
1443+
// TODO: actually use T-coordinates?
1444+
for (int s = s1; s <= s2; s += 2)
14481445
{
1449-
uint16_t src = Memory::read<uint16_t>(texAddress + i);
1450-
uint8_t *dst = &tmem[(tile.address + i * 4) & 0xFF8];
1451-
dst[0] = src >> 8;
1452-
dst[1] = src >> 0;
1446+
uint16_t src = Memory::read<uint16_t>(texAddress + s);
1447+
uint8_t *dst = &tmem[(tile.address + s * 4) & 0xFF8];
1448+
for (int i = 0; i < 8; i += 2)
1449+
{
1450+
dst[i + 0] = src >> 8;
1451+
dst[i + 1] = src >> 0;
1452+
}
14531453
}
14541454
}
14551455

14561456
void RDP::setTileSize()
14571457
{
1458-
// Set the low texture coordinates for reference
1459-
// TODO: use the high coordinates for something?
1458+
// Set the texture coordinate bounds
14601459
Tile &tile = tiles[(opcode[0] >> 24) & 0x7];
1461-
tile.sBase = ((opcode[0] >> 44) & 0xFFF) << 3;
1462-
tile.tBase = ((opcode[0] >> 32) & 0xFFF) << 3;
1460+
tile.s1 = ((opcode[0] >> 44) & 0xFFF) << 3;
1461+
tile.t1 = ((opcode[0] >> 32) & 0xFFF) << 3;
1462+
tile.s2 = ((opcode[0] >> 12) & 0xFFF) << 3;
1463+
tile.t2 = ((opcode[0] >> 0) & 0xFFF) << 3;
14631464
}
14641465

14651466
void RDP::loadBlock()
14661467
{
1467-
// Decode the operands
1468+
// Decode the operands and set texture coordinate bounds
14681469
Tile &tile = tiles[(opcode[0] >> 24) & 0x7];
1469-
uint16_t count = ((opcode[0] >> 12) & 0xFFF);
1470-
uint16_t dxt = (opcode[0] & 0xFFF);
1471-
1472-
// Adjust the byte count based on the texel size
1473-
count = (count << 2) >> (~texFormat & 0x3);
1470+
uint16_t s1 = (tile.s1 = ((opcode[0] >> 44) & 0xFFF) << 3) >> 1;
1471+
uint16_t t1 = (tile.t1 = ((opcode[0] >> 32) & 0xFFF) << 3) >> 1;
1472+
uint16_t s2 = (tile.s2 = ((opcode[0] >> 12) & 0xFFF) << 3) >> 1;
1473+
uint16_t dxt = (tile.t2 = ((opcode[0] >> 0) & 0xFFF) << 3) >> 3;
14741474

1475+
// Adjust the byte count based on texel size
1476+
uint16_t count = (s2 - s1) >> (~texFormat & 0x3);
14751477
uint16_t d = 0;
14761478
bool odd = false;
14771479

@@ -1523,16 +1525,12 @@ void RDP::loadBlock()
15231525

15241526
void RDP::loadTile()
15251527
{
1526-
// Decode the operands
1528+
// Decode the operands and set texture coordinate bounds
15271529
Tile &tile = tiles[(opcode[0] >> 24) & 0x7];
1528-
uint16_t t2 = ((opcode[0] >> 0) & 0xFFF) >> 2;
1529-
uint16_t s2 = ((opcode[0] >> 12) & 0xFFF) >> 2;
1530-
uint16_t t1 = ((opcode[0] >> 32) & 0xFFF) >> 2;
1531-
uint16_t s1 = ((opcode[0] >> 44) & 0xFFF) >> 2;
1532-
1533-
// Save the low texture coordinates for reference
1534-
tile.sBase = ((opcode[0] >> 44) & 0xFFF) << 3;
1535-
tile.tBase = ((opcode[0] >> 32) & 0xFFF) << 3;
1530+
uint16_t s1 = (tile.s1 = ((opcode[0] >> 44) & 0xFFF) << 3) >> 5;
1531+
uint16_t t1 = (tile.t1 = ((opcode[0] >> 32) & 0xFFF) << 3) >> 5;
1532+
uint16_t s2 = (tile.s2 = ((opcode[0] >> 12) & 0xFFF) << 3) >> 5;
1533+
uint16_t t2 = (tile.t2 = ((opcode[0] >> 0) & 0xFFF) << 3) >> 5;
15361534

15371535
// Only support loading textures without conversion for now
15381536
if (texFormat != tile.format)

0 commit comments

Comments
 (0)