|
|
|
|
/**
|
|
|
|
|
* @file dun_render.hpp
|
|
|
|
|
*
|
|
|
|
|
* Interface of functionality for rendering the level tiles.
|
|
|
|
|
*/
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
#include <cstdint>
|
|
|
|
|
|
|
|
|
|
#include "engine/point.hpp"
|
|
|
|
|
#include "engine/surface.hpp"
|
|
|
|
|
#include "levels/dun_tile.hpp"
|
Simplify foliage rendering
During `ReencodeDungeonCels`, extracts floor tile foliage into
a triangle with the floor frame and a separate 16-px tall `TransparentSquare`.
This means that the floor frames are now always triangles and
the foliage can be rendered directly without masking.
Dungeon graphics sizes:
Map | Frames | Foliage frames | Byte size | Before PR | After PR
-----|--------|---------------:|-----------:|----------:|----------:
Town | 3,803 | 41 | 2,317,832 | 2,242,056 | 2,242,190
L1 | 1,119 | 11 | 738,836 | 721,604 | 721,110
L4 | 1,091 | 6 | 603,140 | 584,500 | 584,242
RG99 binary size reduced by ~4 KiB: 2,426,380 bytes -> 2,421,388 bytes
2 years ago
|
|
|
#include "levels/gendung.h"
|
|
|
|
|
#include "utils/attributes.h"
|
|
|
|
|
|
|
|
|
|
// #define DUN_RENDER_STATS
|
|
|
|
|
#ifdef DUN_RENDER_STATS
|
|
|
|
|
#include <ankerl/unordered_dense.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
namespace devilution {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Specifies the mask to use for rendering.
|
|
|
|
|
*/
|
|
|
|
|
enum class MaskType : uint8_t {
|
|
|
|
|
/** @brief The entire tile is opaque. */
|
|
|
|
|
Solid,
|
|
|
|
|
|
|
|
|
|
/** @brief The entire tile is blended with transparency. */
|
|
|
|
|
Transparent,
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Upper-right triangle is blended with transparency.
|
|
|
|
|
*
|
|
|
|
|
* Can only be used with `TileType::LeftTrapezoid` and
|
|
|
|
|
* `TileType::TransparentSquare`.
|
|
|
|
|
*
|
|
|
|
|
* The lower 16 rows are opaque.
|
|
|
|
|
* The upper 16 rows are arranged like this (🮆 = opaque, 🮐 = blended):
|
|
|
|
|
*
|
|
|
|
|
* 🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐
|
|
|
|
|
* 🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐
|
|
|
|
|
* 🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐
|
|
|
|
|
* 🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐
|
|
|
|
|
* 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐
|
|
|
|
|
* 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐
|
|
|
|
|
* 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐
|
|
|
|
|
* 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐
|
|
|
|
|
* 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐
|
|
|
|
|
* 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐
|
|
|
|
|
* 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐
|
|
|
|
|
* 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐🮐🮐
|
|
|
|
|
* 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐🮐🮐
|
|
|
|
|
* 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐🮐🮐
|
|
|
|
|
* 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮐🮐
|
|
|
|
|
* 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆
|
|
|
|
|
*/
|
|
|
|
|
Right,
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Upper-left triangle is blended with transparency.
|
|
|
|
|
*
|
|
|
|
|
* Can only be used with `TileType::RightTrapezoid` and
|
|
|
|
|
* `TileType::TransparentSquare`.
|
|
|
|
|
*
|
|
|
|
|
* The lower 16 rows are opaque.
|
|
|
|
|
* The upper 16 rows are arranged like this (🮆 = opaque, 🮐 = blended):
|
|
|
|
|
*
|
|
|
|
|
* 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆
|
|
|
|
|
* 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆
|
|
|
|
|
* 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆
|
|
|
|
|
* 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆
|
|
|
|
|
* 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆
|
|
|
|
|
* 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆
|
|
|
|
|
* 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆
|
|
|
|
|
* 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆
|
|
|
|
|
* 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆
|
|
|
|
|
* 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆
|
|
|
|
|
* 🮐🮐🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆
|
|
|
|
|
* 🮐🮐🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆
|
|
|
|
|
* 🮐🮐🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆
|
|
|
|
|
* 🮐🮐🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆
|
|
|
|
|
* 🮐🮐🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆
|
|
|
|
|
* 🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆🮆
|
|
|
|
|
*/
|
|
|
|
|
Left,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#ifdef DUN_RENDER_STATS
|
|
|
|
|
struct DunRenderType {
|
|
|
|
|
TileType tileType;
|
|
|
|
|
MaskType 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<uint32_t> {}((1 < static_cast<uint8_t>(t.tileType)) | static_cast<uint8_t>(t.maskType));
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
extern ankerl::unordered_dense::map<DunRenderType, size_t, DunRenderTypeHash> DunRenderStats;
|
|
|
|
|
|
|
|
|
|
std::string_view TileTypeToString(TileType tileType);
|
|
|
|
|
|
|
|
|
|
std::string_view MaskTypeToString(MaskType maskType);
|
|
|
|
|
#endif
|
|
|
|
|
|
Simplify foliage rendering
During `ReencodeDungeonCels`, extracts floor tile foliage into
a triangle with the floor frame and a separate 16-px tall `TransparentSquare`.
This means that the floor frames are now always triangles and
the foliage can be rendered directly without masking.
Dungeon graphics sizes:
Map | Frames | Foliage frames | Byte size | Before PR | After PR
-----|--------|---------------:|-----------:|----------:|----------:
Town | 3,803 | 41 | 2,317,832 | 2,242,056 | 2,242,190
L1 | 1,119 | 11 | 738,836 | 721,604 | 721,110
L4 | 1,091 | 6 | 603,140 | 584,500 | 584,242
RG99 binary size reduced by ~4 KiB: 2,426,380 bytes -> 2,421,388 bytes
2 years ago
|
|
|
/**
|
|
|
|
|
* @brief Low-level tile rendering function.
|
|
|
|
|
*/
|
|
|
|
|
void RenderTileFrame(const Surface &out, const Point &position, TileType tile, const uint8_t *src, int_fast16_t height,
|
|
|
|
|
MaskType maskType, const uint8_t *tbl);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Blit current world CEL to the given buffer
|
|
|
|
|
* @param out Target buffer
|
|
|
|
|
* @param position Target buffer coordinates
|
|
|
|
|
* @param levelCelBlock The MIN block of the level CEL file.
|
|
|
|
|
* @param maskType The mask to use,
|
|
|
|
|
* @param tbl LightTable or TRN for a tile.
|
|
|
|
|
*/
|
Simplify foliage rendering
During `ReencodeDungeonCels`, extracts floor tile foliage into
a triangle with the floor frame and a separate 16-px tall `TransparentSquare`.
This means that the floor frames are now always triangles and
the foliage can be rendered directly without masking.
Dungeon graphics sizes:
Map | Frames | Foliage frames | Byte size | Before PR | After PR
-----|--------|---------------:|-----------:|----------:|----------:
Town | 3,803 | 41 | 2,317,832 | 2,242,056 | 2,242,190
L1 | 1,119 | 11 | 738,836 | 721,604 | 721,110
L4 | 1,091 | 6 | 603,140 | 584,500 | 584,242
RG99 binary size reduced by ~4 KiB: 2,426,380 bytes -> 2,421,388 bytes
2 years ago
|
|
|
DVL_ALWAYS_INLINE void RenderTile(const Surface &out, const Point &position,
|
|
|
|
|
LevelCelBlock levelCelBlock, MaskType maskType, const uint8_t *tbl)
|
|
|
|
|
{
|
|
|
|
|
const TileType tileType = levelCelBlock.type();
|
|
|
|
|
RenderTileFrame(out, position, tileType,
|
|
|
|
|
GetDunFrame(levelCelBlock.frame()),
|
|
|
|
|
(tileType == TileType::LeftTriangle || tileType == TileType::RightTriangle)
|
|
|
|
|
? DunFrameTriangleHeight
|
|
|
|
|
: DunFrameHeight,
|
|
|
|
|
maskType, tbl);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Renders a floor foliage tile.
|
|
|
|
|
*/
|
|
|
|
|
DVL_ALWAYS_INLINE void RenderTileFoliage(const Surface &out, const Point &position, LevelCelBlock levelCelBlock, const uint8_t *tbl)
|
|
|
|
|
{
|
|
|
|
|
RenderTileFrame(out, Point { position.x, position.y - 16 }, TileType::TransparentSquare,
|
|
|
|
|
GetDunFrameFoliage(levelCelBlock.frame()), /*height=*/16, MaskType::Solid, tbl);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Render a black 64x31 tile ◆
|
|
|
|
|
* @param out Target buffer
|
|
|
|
|
* @param sx Target buffer coordinate (left corner of the tile)
|
|
|
|
|
* @param sy Target buffer coordinate (bottom corner of the tile)
|
|
|
|
|
*/
|
|
|
|
|
void world_draw_black_tile(const Surface &out, int sx, int sy);
|
|
|
|
|
|
|
|
|
|
} // namespace devilution
|