test: extend coverage of testTileTexture

This commit is contained in:
dualfroz committed 2026-09-13 21:12:44 +02:00
1 parent ea0e3b2ad0
commit 522662ded6
1 file changed
+140
+140
View File
@@ -301,3 +301,143 @@ VF_TEST(writeTileAgreesWithPixelAtEverywhere) {
}
}
// The atlas is built at sixteen pixels today, but nothing in the palette is
// allowed to depend on that. Alpha rules and contrast have to survive a
// different tile size.
VF_TEST(tilesKeepTheirAlphaAndContrastAtOtherTileSizes) {
const int sizes[] = {8, 16, 32};
for (int size : sizes) {
TileTextureParams params;
params.tileSize = size;
TileSampler sampler(params);
for (int tile = 0; tile < renderedTiles(sampler); ++tile) {
const TileSpec& spec = sampler.palette().specFor(tile);
int holes = 0;
int solid = 0;
for (int y = 0; y < size; ++y) {
for (int x = 0; x < size; ++x) {
uint8_t alpha = sampler.pixelAt(tile, x, y).a;
if (alpha == 0) ++holes;
if (alpha == 255) ++solid;
}
}
CHECK_EQ(holes + solid, size * size);
if (spec.cutout) {
CHECK(holes > 0);
CHECK(solid > 0);
if (holes == 0 || solid == 0) {
std::printf(" tile %d (%s) at size %d: %d holes, %d solid\n", tile, spec.name,
size, holes, solid);
}
} else {
CHECK_EQ(holes, 0);
}
int spread = interiorRange(sampler, tile).spread();
CHECK(spread >= 8);
if (spread < 8) {
std::printf(" tile %d (%s) at size %d is flat: spread %d\n", tile, spec.name, size,
spread);
}
}
}
}
// Boards run one way and their grain runs with them. Flipping the spec's axis
// has to flip which direction the tile varies in, otherwise the plank pattern
// is drawing wallpaper.
VF_TEST(plankGrainFollowsTheBoardDirection) {
TileSampler sampler;
int size = sampler.params().tileSize;
TileSpec board;
board.name = "testBoard";
board.pattern = TilePattern::Plank;
board.material = TileMaterial::Wood;
board.base = TileRgb{160, 120, 70};
board.accent = TileRgb{90, 64, 34};
board.noise = 0.0f;
board.scale = 0.35f;
board.density = 0.50f;
TileSpec upright = board;
upright.vertical = true;
auto axisSpread = [&](const TileSpec& spec, bool alongColumns) {
int lowest = 255;
int highest = 0;
for (int outer = 1; outer < size; ++outer) {
int total = 0;
for (int inner = 1; inner < size; ++inner) {
int x = alongColumns ? outer : inner;
int y = alongColumns ? inner : outer;
total += luminance(sampler.pixelOf(spec, 900, x, y));
}
int mean = total / (size - 1);
if (mean < lowest) lowest = mean;
if (mean > highest) highest = mean;
}
return highest - lowest;
};
int uprightAcrossColumns = axisSpread(upright, true);
int uprightAcrossRows = axisSpread(upright, false);
CHECK(uprightAcrossColumns > uprightAcrossRows);
int flatAcrossRows = axisSpread(board, false);
int flatAcrossColumns = axisSpread(board, true);
CHECK(flatAcrossRows > flatAcrossColumns);
}
// A ladder without gaps is a plank. Every cutout lattice has to leave real
// openings and still keep enough bar to stand on.
VF_TEST(latticeTilesLeaveOpeningsBetweenTheirBars) {
TileSampler sampler;
int size = sampler.params().tileSize;
int checked = 0;
for (int tile = 0; tile < renderedTiles(sampler); ++tile) {
const TileSpec& spec = sampler.palette().specFor(tile);
if (spec.pattern != TilePattern::Lattice || !spec.cutout) continue;
++checked;
int holes = 0;
for (int y = 0; y < size; ++y) {
for (int x = 0; x < size; ++x) {
if (sampler.pixelAt(tile, x, y).a == 0) ++holes;
}
}
float openFraction = static_cast<float>(holes) / static_cast<float>(size * size);
CHECK(openFraction > 0.15f);
CHECK(openFraction < 0.92f);
if (openFraction <= 0.15f || openFraction >= 0.92f) {
std::printf(" tile %d (%s) is %.2f open\n", tile, spec.name,
static_cast<double>(openFraction));
}
}
CHECK(checked >= 8);
}
// Veins have to be visible without swallowing the host rock, or every ore looks
// like a solid block of its own metal.
VF_TEST(oreVeinsCoverPartOfTheHostRockWithoutSwallowingIt) {
TileSampler sampler;
int size = sampler.params().tileSize;
int checked = 0;
for (int tile = 0; tile < renderedTiles(sampler); ++tile) {
const TileSpec& spec = sampler.palette().specFor(tile);
if (spec.pattern != TilePattern::OreSpeckle) continue;
++checked;
int vein = 0;
for (int y = 0; y < size; ++y) {
for (int x = 0; x < size; ++x) {
if (leansToAccent(sampler.pixelAt(tile, x, y), spec)) ++vein;
}
}
float coverage = static_cast<float>(vein) / static_cast<float>(size * size);
CHECK(coverage > 0.02f);
CHECK(coverage < 0.55f);
if (coverage <= 0.02f || coverage >= 0.55f) {
std::printf(" tile %d (%s) vein coverage %.3f\n", tile, spec.name,
static_cast<double>(coverage));
}
}
CHECK(checked >= 9);
}