Rendering Engine 0.2.17
Modular Graphics Rendering Engine | v0.2.17
Loading...
Searching...
No Matches
texture_atlas_maker_tests.cpp
Go to the documentation of this file.
1// This file is part of the Rendering Engine project.
2// Author: Alexander Obzherin <alexanderobzherin@gmail.com>
3// Copyright (c) 2026 Alexander Obzherin
4// Distributed under the terms of the zlib License. See LICENSE.md for details.
5
7#include <gtest/gtest.h>
8
9using namespace rendering_engine;
10
11namespace
12{
13using Positions = std::map<char, std::pair<unsigned int, unsigned int>>;
14
15ImageData SolidImage(unsigned width, unsigned height, Color color)
16{
17 ImageData image(width, height);
18 image.Fill(color);
19 return image;
20}
21
22void ExpectAtlasPixels(const ImageData& atlas, const std::map<char, ImageData>& sources,
23 const Positions& positions)
24{
25 ASSERT_EQ(positions.size(), sources.size());
26 // Account for every pixel, including cell padding and unused cells.
27 for (unsigned y = 0; y < atlas.GetHeight(); ++y)
28 {
29 for (unsigned x = 0; x < atlas.GetWidth(); ++x)
30 {
31 SCOPED_TRACE(::testing::Message() << "pixel " << x << ", " << y);
32 Color expected(0, 0, 0, 255);
33 unsigned coveringImages = 0;
34 for (const auto& source : sources)
35 {
36 const auto found = positions.find(source.first);
37 ASSERT_NE(found, positions.end());
38 const auto left = found->second.first;
39 const auto top = found->second.second;
40 if (x >= left && y >= top && x - left < source.second.GetWidth() &&
41 y - top < source.second.GetHeight())
42 {
43 ++coveringImages;
44 expected = source.second.GetPixel(x - left, y - top);
45 }
46 }
47 EXPECT_LE(coveringImages, 1U);
48 EXPECT_EQ(atlas.GetPixel(x, y), expected);
49 }
50 }
51}
52}
53
54TEST(TextureAtlasMaker, EmptyCollectionReportsFailure)
55{
56 TextureAtlasMaker maker({});
57 Positions positions;
58 ImageData atlas;
59 EXPECT_FALSE(maker.CreateTextureAtlas(positions, atlas));
60 EXPECT_TRUE(positions.empty());
61 EXPECT_EQ(atlas.GetWidth(), 0U);
62 EXPECT_EQ(atlas.GetHeight(), 0U);
63 EXPECT_TRUE(atlas.GetImageDataRGBA().empty());
64}
65
66TEST(TextureAtlasMaker, SingleImagePreservesPixelsAndRecordsOrigin)
67{
68 ImageData source(2, 2, std::vector<std::uint8_t>{
69 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16});
70 const std::map<char, ImageData> images{{'A', source}};
71 TextureAtlasMaker maker(images);
72 Positions positions;
73 ImageData atlas;
74 ASSERT_TRUE(maker.CreateTextureAtlas(positions, atlas));
75 EXPECT_EQ(atlas.GetWidth(), 2U);
76 EXPECT_EQ(atlas.GetHeight(), 2U);
77 const Positions expected{{'A', {0, 0}}};
78 EXPECT_EQ(positions, expected);
79 EXPECT_EQ(atlas.GetImageDataRGBA(), source.GetImageDataRGBA());
80}
81
82TEST(TextureAtlasMaker, UniformImagesUseGridAndLeaveUnusedCellBlack)
83{
84 const std::map<char, ImageData> images{
85 {'C', SolidImage(2, 2, Color(0, 0, 255, 64))},
86 {'A', SolidImage(2, 2, Color(255, 0, 0, 128))},
87 {'B', SolidImage(2, 2, Color(0, 255, 0, 192))}
88 };
89 TextureAtlasMaker maker(images);
90 Positions positions;
91 ImageData atlas;
92 ASSERT_TRUE(maker.CreateTextureAtlas(positions, atlas));
93 ASSERT_EQ(atlas.GetWidth(), 4U);
94 ASSERT_EQ(atlas.GetHeight(), 4U);
95 // This overload uses an ordered map, unlike the optional glyph overload.
96 const Positions expected{{'A', {0, 0}}, {'B', {2, 0}}, {'C', {0, 2}}};
97 EXPECT_EQ(positions, expected);
98 ExpectAtlasPixels(atlas, images, positions);
99}
100
101TEST(TextureAtlasMaker, MixedSizesUseMaximumCellDimensionsAndBlackPadding)
102{
103 const std::map<char, ImageData> images{
104 {'A', SolidImage(2, 3, Color(255, 0, 0))},
105 {'B', SolidImage(4, 1, Color(0, 255, 0))},
106 {'C', SolidImage(1, 2, Color(0, 0, 255))}
107 };
108 TextureAtlasMaker maker(images);
109 Positions positions;
110 ImageData atlas;
111 ASSERT_TRUE(maker.CreateTextureAtlas(positions, atlas));
112 // 4x3 cells, two columns and two rows for these three images.
113 ASSERT_EQ(atlas.GetWidth(), 8U);
114 ASSERT_EQ(atlas.GetHeight(), 6U);
115 const Positions expected{{'A', {0, 0}}, {'B', {4, 0}}, {'C', {0, 3}}};
116 EXPECT_EQ(positions, expected);
117 ExpectAtlasPixels(atlas, images, positions);
118}
Represents raw 2D image data stored in memory.
unsigned int GetWidth() const
Returns the image width.
std::vector< uint8_t > GetImageDataRGBA() const
Gets raw image data in RGBA format.
unsigned int GetHeight() const
Returns the image height.
const Color GetPixel(unsigned int x, unsigned int y) const
Retrieves the color of a specific pixel.
Builds texture atlases from collections of images.
bool CreateTextureAtlas(std::map< char, std::pair< unsigned int, unsigned int > > &texAtlasData, ImageData &texAtlasImage)
Creates a texture atlas from the stored image collection.
Represents a color with red, green, blue, and alpha channels.
TEST(TextureAtlasMaker, EmptyCollectionReportsFailure)