mirror of
https://github.com/diasurgical/DevilutionX.git
synced 2026-10-12 02:13:06 +00:00
light_render: Use an std::span for light tables
1. There is no need to store the light table width as it is always 256. 2. Use a fixed-extent `std::span` rather than a pointer for readability. This should optimize to the exact same code.
This commit is contained in:
@@ -10,6 +10,9 @@ namespace devilution {
|
||||
|
||||
constexpr char LightsMax = 15;
|
||||
|
||||
/** @brief A light table maps palette indices, so its size is the same as the palette size. */
|
||||
constexpr size_t LightTableSize = 256;
|
||||
|
||||
/** @brief Number of supported light levels */
|
||||
constexpr size_t NumLightingLevels = LightsMax + 1;
|
||||
|
||||
|
||||
@@ -491,27 +491,26 @@ void BuildLightmap(Point tilePosition, Point targetBufferPosition, uint16_t view
|
||||
|
||||
Lightmap::Lightmap(const uint8_t *outBuffer, uint16_t outPitch,
|
||||
std::span<const uint8_t> lightmapBuffer, uint16_t lightmapPitch,
|
||||
const uint8_t *lightTables, size_t lightTableSize)
|
||||
std::span<const std::array<uint8_t, LightTableSize>, NumLightingLevels> lightTables)
|
||||
: outBuffer(outBuffer)
|
||||
, outPitch(outPitch)
|
||||
, lightmapBuffer(lightmapBuffer)
|
||||
, lightmapPitch(lightmapPitch)
|
||||
, lightTables(lightTables)
|
||||
, lightTableSize(lightTableSize)
|
||||
{
|
||||
}
|
||||
|
||||
Lightmap Lightmap::build(bool perPixelLighting, Point tilePosition, Point targetBufferPosition,
|
||||
int viewportWidth, int viewportHeight, int rows, int columns,
|
||||
const uint8_t *outBuffer, uint16_t outPitch,
|
||||
const uint8_t *lightTables, size_t lightTableSize,
|
||||
std::span<const std::array<uint8_t, LightTableSize>, NumLightingLevels> lightTables,
|
||||
const uint8_t tileLights[MAXDUNX][MAXDUNY],
|
||||
uint_fast8_t microTileLen)
|
||||
{
|
||||
if (perPixelLighting) {
|
||||
BuildLightmap(tilePosition, targetBufferPosition, viewportWidth, viewportHeight, rows, columns, tileLights, microTileLen);
|
||||
}
|
||||
return Lightmap(outBuffer, outPitch, LightmapBuffer, viewportWidth, lightTables, lightTableSize);
|
||||
return Lightmap(outBuffer, outPitch, LightmapBuffer, viewportWidth, lightTables);
|
||||
}
|
||||
|
||||
Lightmap Lightmap::bleedUp(bool perPixelLighting, const Lightmap &source, Point targetBufferPosition, std::span<uint8_t> lightmapBuffer)
|
||||
@@ -566,7 +565,7 @@ Lightmap Lightmap::bleedUp(bool perPixelLighting, const Lightmap &source, Point
|
||||
|
||||
return Lightmap(outBuffer, source.outPitch,
|
||||
lightmapBuffer, lightmapPitch,
|
||||
source.lightTables, source.lightTableSize);
|
||||
source.lightTables);
|
||||
}
|
||||
|
||||
} // namespace devilution
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <span>
|
||||
|
||||
#include "engine/lighting_defs.hpp"
|
||||
#include "engine/point.hpp"
|
||||
#include "levels/gendung_defs.hpp"
|
||||
|
||||
@@ -11,19 +13,18 @@ namespace devilution {
|
||||
|
||||
class Lightmap {
|
||||
public:
|
||||
explicit Lightmap(const uint8_t *outBuffer, std::span<const uint8_t> lightmapBuffer, uint16_t pitch, const uint8_t *lightTables, size_t lightTableSize)
|
||||
: Lightmap(outBuffer, pitch, lightmapBuffer, pitch, lightTables, lightTableSize)
|
||||
explicit Lightmap(const uint8_t *outBuffer, std::span<const uint8_t> lightmapBuffer, uint16_t pitch, std::span<const std::array<uint8_t, LightTableSize>, NumLightingLevels> lightTables)
|
||||
: Lightmap(outBuffer, pitch, lightmapBuffer, pitch, lightTables)
|
||||
{
|
||||
}
|
||||
|
||||
explicit Lightmap(const uint8_t *outBuffer, uint16_t outPitch,
|
||||
std::span<const uint8_t> lightmapBuffer, uint16_t lightmapPitch,
|
||||
const uint8_t *lightTables, size_t lightTableSize);
|
||||
std::span<const std::array<uint8_t, LightTableSize>, NumLightingLevels> lightTables);
|
||||
|
||||
uint8_t adjustColor(uint8_t color, uint8_t lightLevel) const
|
||||
[[nodiscard]] uint8_t adjustColor(uint8_t color, uint8_t lightLevel) const
|
||||
{
|
||||
size_t offset = lightLevel * lightTableSize + color;
|
||||
return lightTables[offset];
|
||||
return lightTables[lightLevel][color];
|
||||
}
|
||||
|
||||
const uint8_t *getLightingAt(const uint8_t *outLoc) const
|
||||
@@ -45,7 +46,7 @@ public:
|
||||
static Lightmap build(bool perPixelLighting, Point tilePosition, Point targetBufferPosition,
|
||||
int viewportWidth, int viewportHeight, int rows, int columns,
|
||||
const uint8_t *outBuffer, uint16_t outPitch,
|
||||
const uint8_t *lightTables, size_t lightTableSize,
|
||||
std::span<const std::array<uint8_t, LightTableSize>, NumLightingLevels> lightTables,
|
||||
const uint8_t tileLights[MAXDUNX][MAXDUNY],
|
||||
uint_fast8_t microTileLen);
|
||||
|
||||
@@ -58,8 +59,7 @@ private:
|
||||
std::span<const uint8_t> lightmapBuffer;
|
||||
const uint16_t lightmapPitch;
|
||||
|
||||
const uint8_t *lightTables;
|
||||
const size_t lightTableSize;
|
||||
std::span<const std::array<uint8_t, LightTableSize>, NumLightingLevels> lightTables;
|
||||
};
|
||||
|
||||
} // namespace devilution
|
||||
|
||||
@@ -1133,7 +1133,7 @@ void DrawGame(const Surface &fullOut, Point position, Displacement offset)
|
||||
|
||||
Lightmap lightmap = Lightmap::build(*GetOptions().Graphics.perPixelLighting, position, Point {} + offset,
|
||||
gnScreenWidth, gnViewportHeight, rows, columns,
|
||||
out.at(0, 0), out.pitch(), LightTables[0].data(), LightTables[0].size(),
|
||||
out.at(0, 0), out.pitch(), LightTables,
|
||||
dLight, MicroTileLen);
|
||||
|
||||
DrawFloor(out, lightmap, position, Point {} + offset, rows, columns);
|
||||
|
||||
+2
-1
@@ -15,6 +15,7 @@
|
||||
|
||||
#include "automap.h"
|
||||
#include "engine/displacement.hpp"
|
||||
#include "engine/lighting_defs.hpp"
|
||||
#include "engine/load_file.hpp"
|
||||
#include "engine/point.hpp"
|
||||
#include "engine/points_in_rectangle_range.hpp"
|
||||
@@ -34,7 +35,7 @@ Light VisionList[MAXVISION];
|
||||
Light Lights[MAXLIGHTS];
|
||||
std::array<uint8_t, MAXLIGHTS> ActiveLights;
|
||||
int ActiveLightCount;
|
||||
std::array<std::array<uint8_t, 256>, NumLightingLevels> LightTables;
|
||||
std::array<std::array<uint8_t, LightTableSize>, NumLightingLevels> LightTables;
|
||||
uint8_t *FullyLitLightTable = nullptr;
|
||||
uint8_t *FullyDarkLightTable = nullptr;
|
||||
std::array<uint8_t, 256> InfravisionTable;
|
||||
|
||||
+1
-1
@@ -40,7 +40,7 @@ extern std::array<bool, MAXVISION> VisionActive;
|
||||
extern Light Lights[MAXLIGHTS];
|
||||
extern std::array<uint8_t, MAXLIGHTS> ActiveLights;
|
||||
extern int ActiveLightCount;
|
||||
extern DVL_API_FOR_TEST std::array<std::array<uint8_t, 256>, NumLightingLevels> LightTables;
|
||||
extern DVL_API_FOR_TEST std::array<std::array<uint8_t, LightTableSize>, NumLightingLevels> LightTables;
|
||||
/** @brief Contains a pointer to a light table that is fully lit (no color mapping is required). Can be null in hell. */
|
||||
extern DVL_API_FOR_TEST uint8_t *FullyLitLightTable;
|
||||
/** @brief Contains a pointer to a light table that is fully dark (every color result to 0/black). Can be null in hellfire levels. */
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <span>
|
||||
|
||||
#include <ankerl/unordered_dense.h>
|
||||
@@ -8,6 +10,7 @@
|
||||
#include "engine/assets.hpp"
|
||||
#include "engine/clx_sprite.hpp"
|
||||
#include "engine/displacement.hpp"
|
||||
#include "engine/lighting_defs.hpp"
|
||||
#include "engine/load_file.hpp"
|
||||
#include "engine/render/dun_render.hpp"
|
||||
#include "engine/surface.hpp"
|
||||
@@ -66,7 +69,8 @@ void InitOnce()
|
||||
void RunForTileMaskLight(benchmark::State &state, TileType tileType, MaskType maskType, const uint8_t *lightTable)
|
||||
{
|
||||
Surface out = Surface(SdlSurface.get());
|
||||
Lightmap lightmap(nullptr, {}, 1, nullptr, 0);
|
||||
std::array<std::array<uint8_t, LightTableSize>, NumLightingLevels> lightTables;
|
||||
Lightmap lightmap(/*outBuffer=*/nullptr, /*lightmapBuffer=*/ {}, /*pitch=*/1, lightTables);
|
||||
const std::span<const LevelCelBlock> tiles = Tiles[tileType];
|
||||
for (auto _ : state) {
|
||||
for (const LevelCelBlock &levelCelBlock : tiles) {
|
||||
|
||||
@@ -20,7 +20,7 @@ void BM_BuildLightmap(benchmark::State &state)
|
||||
const std::string benchmarkDataPath = paths::BasePath() + "test/fixtures/light_render_benchmark/dLight.dmp";
|
||||
FILE *lightFile = std::fopen(benchmarkDataPath.c_str(), "rb");
|
||||
uint8_t dLight[MAXDUNX][MAXDUNY];
|
||||
std::array<std::array<uint8_t, 256>, LightsMax> lightTables;
|
||||
std::array<std::array<uint8_t, LightTableSize>, NumLightingLevels> lightTables;
|
||||
if (lightFile != nullptr) {
|
||||
if (std::fread(&dLight[0][0], sizeof(uint8_t) * MAXDUNX * MAXDUNY, 1, lightFile) != 1) {
|
||||
std::perror("Failed to read dLight.dmp");
|
||||
@@ -50,7 +50,7 @@ void BM_BuildLightmap(benchmark::State &state)
|
||||
Lightmap lightmap = Lightmap::build(/*perPixelLighting=*/true,
|
||||
tilePosition, targetBufferPosition,
|
||||
viewportWidth, viewportHeight, rows, columns,
|
||||
outBuffer, outPitch, lightTables[0].data(), lightTables[0].size(),
|
||||
outBuffer, outPitch, lightTables,
|
||||
dLight, /*microTileLen=*/10);
|
||||
|
||||
uint8_t lightLevel = *lightmap.getLightingAt(outBuffer + outPitch * 120 + 120);
|
||||
|
||||
Reference in New Issue
Block a user