Skip to content

Commit 402d5a4

Browse files
authored
Render dirt in OOB area (diasurgical#8331)
1 parent d0fb28d commit 402d5a4

2 files changed

Lines changed: 74 additions & 3 deletions

File tree

Source/engine/render/scrollrt.cpp

Lines changed: 73 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -928,10 +928,8 @@ void DrawFloor(const Surface &out, const Lightmap &lightmap, Point tilePosition,
928928
{
929929
for (int i = 0; i < rows; i++) {
930930
for (int j = 0; j < columns; j++, tilePosition += Direction::East, targetBufferPosition.x += TILE_WIDTH) {
931-
if (!InDungeonBounds(tilePosition)) {
932-
world_draw_black_tile(out, targetBufferPosition.x, targetBufferPosition.y);
931+
if (!InDungeonBounds(tilePosition))
933932
continue;
934-
}
935933
if (IsFloor(tilePosition)) {
936934
DrawFloorTile(out, lightmap, tilePosition, targetBufferPosition);
937935
}
@@ -1018,6 +1016,77 @@ void DrawTileContent(const Surface &out, const Lightmap &lightmap, Point tilePos
10181016
}
10191017
}
10201018

1019+
void DrawDirtTile(const Surface &out, const Lightmap &lightmap, Point tilePosition, Point targetBufferPosition)
1020+
{
1021+
// This should be the *top-left* of the 2×2 dirt pattern in the actual dungeon.
1022+
// You might need to tweak these to where your dirt patch actually lives.
1023+
constexpr Point base { 0, 0 };
1024+
1025+
// Decide which of the 4 tiles of the 2×2 block to use,
1026+
// based on where this OOB tile is in the world grid.
1027+
const int ox = (tilePosition.x & 1); // 0 or 1
1028+
const int oy = (tilePosition.y & 1); // 0 or 1
1029+
1030+
Point sample {
1031+
base.x + ox,
1032+
base.y + oy,
1033+
};
1034+
1035+
// Safety: clamp in case tilePosition is wildly outside and base+offset ever escapes
1036+
sample.x = std::clamp(sample.x, 0, MAXDUNX - 1);
1037+
sample.y = std::clamp(sample.y, 0, MAXDUNY - 1);
1038+
1039+
if (!InDungeonBounds(sample) || dPiece[sample.x][sample.y] == 0) {
1040+
// Failsafe: if our sample somehow isn't valid, fall back to black
1041+
world_draw_black_tile(out, targetBufferPosition.x, targetBufferPosition.y);
1042+
return;
1043+
}
1044+
1045+
const int lightTableIndex = dLight[sample.x][sample.y];
1046+
1047+
// Let the normal dungeon tile renderer compose the full tile
1048+
DrawCell(out, lightmap, sample, targetBufferPosition, lightTableIndex);
1049+
}
1050+
1051+
/**
1052+
* @brief Render a row of tiles
1053+
* @param out Buffer to render to
1054+
* @param lightmap Per-pixel light buffer
1055+
* @param tilePosition dPiece coordinates
1056+
* @param targetBufferPosition Target buffer coordinates
1057+
* @param rows Number of rows
1058+
* @param columns Tile in a row
1059+
*/
1060+
void DrawOOB(const Surface &out, const Lightmap &lightmap, Point tilePosition, Point targetBufferPosition, int rows, int columns)
1061+
{
1062+
for (int i = 0; i < rows + 5; i++) { // 5 extra rows needed to make sure everything gets rendered at the bottom half of the screen
1063+
for (int j = 0; j < columns; j++, tilePosition += Direction::East, targetBufferPosition.x += TILE_WIDTH) {
1064+
if (!InDungeonBounds(tilePosition)) {
1065+
if (leveltype == DTYPE_TOWN) {
1066+
world_draw_black_tile(out, targetBufferPosition.x, targetBufferPosition.y);
1067+
} else {
1068+
DrawDirtTile(out, lightmap, tilePosition, targetBufferPosition);
1069+
}
1070+
}
1071+
}
1072+
// Return to start of row
1073+
tilePosition += Displacement(Direction::West) * columns;
1074+
targetBufferPosition.x -= columns * TILE_WIDTH;
1075+
1076+
// Jump to next row
1077+
targetBufferPosition.y += TILE_HEIGHT / 2;
1078+
if ((i & 1) != 0) {
1079+
tilePosition.x++;
1080+
columns--;
1081+
targetBufferPosition.x += TILE_WIDTH / 2;
1082+
} else {
1083+
tilePosition.y++;
1084+
columns++;
1085+
targetBufferPosition.x -= TILE_WIDTH / 2;
1086+
}
1087+
}
1088+
}
1089+
10211090
/**
10221091
* @brief Scale up the top left part of the buffer 2x.
10231092
*/
@@ -1183,6 +1252,7 @@ void DrawGame(const Surface &fullOut, Point position, Displacement offset)
11831252

11841253
DrawFloor(out, lightmap, position, Point {} + offset, rows, columns);
11851254
DrawTileContent(out, lightmap, position, Point {} + offset, rows, columns);
1255+
DrawOOB(out, lightmap, position, Point {} + offset, rows, columns);
11861256

11871257
if (*GetOptions().Graphics.zoom) {
11881258
Zoom(fullOut.subregionY(0, gnViewportHeight));

docs/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1212
#### Graphics / Audio
1313

1414
- Music doesn't unmute when focus is lost on level transition with Auto Pause On Focus Lost disabled
15+
- Image ghosting visible on border of map in higher resolutions
1516

1617
## DevilutionX 1.5.2
1718

0 commit comments

Comments
 (0)