Browse Source

dun_render: Overhaul mask handling

We notice that masks can be described by 2 parameters:

1. Whether they have 0 or 1 as their high bits.
2. Whether they shift to the left or to the right on the next line.

Describing masks this way allows us to lift them to template variables and simplify the code.
We also avoid handling the mask in the `RenderLine` loop entirely.

Also fixes a foliage rendering bug: Transparent foliage pixels were previously blended but they should have been simply skipped.
pull/5563/head
Gleb Mazovetskiy 3 years ago committed by Anders Jenbo
parent
commit
44ed0296d8
  1. 1231
      Source/engine/render/dun_render.cpp
  2. 29
      Source/engine/render/dun_render.hpp
  3. 27
      Source/engine/render/scrollrt.cpp
  4. 6
      Source/utils/attributes.h

1231
Source/engine/render/dun_render.cpp

File diff suppressed because it is too large Load Diff

29
Source/engine/render/dun_render.hpp

@ -11,6 +11,11 @@
#include "engine.h"
// #define DUN_RENDER_STATS
#ifdef DUN_RENDER_STATS
#include <unordered_map>
#endif
namespace devilution {
/**
@ -110,13 +115,35 @@ public:
[[nodiscard]] uint16_t frame() const
{
return SDL_SwapLE32(data_ & 0xFFF);
return data_ & 0xFFF;
}
private:
uint16_t data_;
};
#ifdef DUN_RENDER_STATS
struct DunRenderType {
TileType tileType;
uint8_t maskType;
bool operator==(const DunRenderType &other) const
{
return tileType == other.tileType && maskType == other.maskType;
}
};
struct DunRenderTypeHash {
size_t operator()(DunRenderType t) const noexcept
{
return std::hash<uint16_t> {}((static_cast<uint8_t>(t.tileType) << 1) | t.maskType);
}
};
extern std::unordered_map<DunRenderType, size_t, DunRenderTypeHash> DunRenderStats;
string_view TileTypeToString(TileType tileType);
string_view MaskTypeToString(uint8_t maskType);
#endif
/**
* @brief Blit current world CEL to the given buffer
* @param out Target buffer

27
Source/engine/render/scrollrt.cpp

@ -54,6 +54,10 @@
#include "debug.h"
#endif
#ifdef DUN_RENDER_STATS
#include "utils/format_int.hpp"
#endif
namespace devilution {
/**
@ -1010,12 +1014,35 @@ void DrawGame(const Surface &fullOut, Point position)
}
}
#ifdef DUN_RENDER_STATS
DunRenderStats.clear();
#endif
DrawFloor(out, position, { sx, sy }, rows, columns);
DrawTileContent(out, position, { sx, sy }, rows, columns);
if (*sgOptions.Graphics.zoom) {
Zoom(fullOut.subregionY(0, gnViewportHeight));
}
#ifdef DUN_RENDER_STATS
std::vector<std::pair<DunRenderType, size_t>> sortedStats(DunRenderStats.begin(), DunRenderStats.end());
std::sort(sortedStats.begin(), sortedStats.end(),
[](const std::pair<DunRenderType, size_t> &a, const std::pair<DunRenderType, size_t> &b) {
return a.first.maskType == b.first.maskType
? static_cast<uint8_t>(a.first.tileType) < static_cast<uint8_t>(b.first.tileType)
: a.first.maskType < b.first.maskType;
});
Point pos { 100, 20 };
for (size_t i = 0; i < sortedStats.size(); ++i) {
const auto &stat = sortedStats[i];
DrawString(out, StrCat(i, "."), Rectangle(pos, Size { 20, 16 }), UiFlags::AlignRight);
DrawString(out, MaskTypeToString(stat.first.maskType), { pos.x + 24, pos.y });
DrawString(out, TileTypeToString(stat.first.tileType), { pos.x + 184, pos.y });
DrawString(out, FormatInteger(stat.second), Rectangle({ pos.x + 354, pos.y }, Size(40, 16)), UiFlags::AlignRight);
pos.y += 16;
}
#endif
}
/**

6
Source/utils/attributes.h

@ -56,3 +56,9 @@
#else
#define DVL_EXCEPTIONS 1
#endif
#if defined(_MSC_VER)
#define DVL_RESTRICT __restrict
#else
#define DVL_RESTRICT __restrict__
#endif

Loading…
Cancel
Save