Populate cached images into the texture atlas

This commit is contained in:
Dan Paulat 2023-07-30 22:31:05 -05:00
parent 0f9fbdbf63
commit 4c093d65f6
5 changed files with 104 additions and 18 deletions

View file

@ -27,6 +27,8 @@ static constexpr size_t kPointsPerVertex = 10;
static constexpr size_t kBufferLength = static constexpr size_t kBufferLength =
kNumTriangles * kVerticesPerTriangle * kPointsPerVertex; kNumTriangles * kVerticesPerTriangle * kPointsPerVertex;
static const std::string kTextureName = "lines/default-1x7";
class GeoLine::Impl class GeoLine::Impl
{ {
public: public:
@ -115,7 +117,7 @@ void GeoLine::Initialize()
} }
p->texture_ = p->texture_ =
util::TextureAtlas::Instance().GetTextureAttributes("lines/default-1x7"); util::TextureAtlas::Instance().GetTextureAttributes(kTextureName);
gl.glGenVertexArrays(1, &p->vao_); gl.glGenVertexArrays(1, &p->vao_);
gl.glGenBuffers(1, &p->vbo_); gl.glGenBuffers(1, &p->vbo_);
@ -248,6 +250,9 @@ void GeoLine::Impl::Update()
{ {
gl::OpenGLFunctions& gl = context_->gl(); gl::OpenGLFunctions& gl = context_->gl();
texture_ =
util::TextureAtlas::Instance().GetTextureAttributes(kTextureName);
// Latitude and longitude coordinates in degrees // Latitude and longitude coordinates in degrees
const float lx = points_[0].latitude_; const float lx = points_[0].latitude_;
const float rx = points_[1].latitude_; const float rx = points_[1].latitude_;

View file

@ -459,14 +459,23 @@ void PlacefileManager::Impl::LoadResources(
const QUrl baseUrl = const QUrl baseUrl =
QUrl::fromUserInput(QString::fromStdString(placefile->name())); QUrl::fromUserInput(QString::fromStdString(placefile->name()));
// TODO: Parallelize std::vector<std::string> urlStrings;
for (auto& iconFile : iconFiles) urlStrings.reserve(iconFiles.size());
{
QUrl fileUrl = QUrl(QString::fromStdString(iconFile->filename_));
QUrl resolvedUrl = baseUrl.resolved(fileUrl);
ResourceManager::LoadImageResource(resolvedUrl.toString().toStdString()); std::transform(iconFiles.cbegin(),
} iconFiles.cend(),
std::back_inserter(urlStrings),
[&baseUrl](auto& iconFile)
{
// Resolve target URL relative to base URL
QUrl fileUrl =
QUrl(QString::fromStdString(iconFile->filename_));
QUrl resolvedUrl = baseUrl.resolved(fileUrl);
return resolvedUrl.toString().toStdString();
});
ResourceManager::LoadImageResources(urlStrings);
} }
} // namespace manager } // namespace manager

View file

@ -5,6 +5,9 @@
#include <scwx/qt/util/texture_atlas.hpp> #include <scwx/qt/util/texture_atlas.hpp>
#include <scwx/util/logger.hpp> #include <scwx/util/logger.hpp>
#include <execution>
#include <mutex>
#include <QFontDatabase> #include <QFontDatabase>
#include <imgui.h> #include <imgui.h>
@ -61,10 +64,36 @@ std::shared_ptr<util::Font> Font(types::Font font)
return nullptr; return nullptr;
} }
void LoadImageResource(const std::string& urlString) bool LoadImageResource(const std::string& urlString)
{ {
util::TextureAtlas& textureAtlas = util::TextureAtlas::Instance(); util::TextureAtlas& textureAtlas = util::TextureAtlas::Instance();
textureAtlas.CacheTexture(urlString, urlString); return textureAtlas.CacheTexture(urlString, urlString);
}
void LoadImageResources(const std::vector<std::string>& urlStrings)
{
std::mutex m {};
bool textureCached = false;
std::for_each(std::execution::par_unseq,
urlStrings.begin(),
urlStrings.end(),
[&](auto& urlString)
{
bool value = LoadImageResource(urlString);
if (value)
{
std::unique_lock lock {m};
textureCached = true;
}
});
if (textureCached)
{
util::TextureAtlas& textureAtlas = util::TextureAtlas::Instance();
textureAtlas.BuildAtlas(1024, 1024);
}
} }
static void LoadFonts() static void LoadFonts()
@ -90,7 +119,7 @@ static void LoadTextures()
":/res/textures/lines/default-1x7.png"); ":/res/textures/lines/default-1x7.png");
textureAtlas.RegisterTexture("lines/test-pattern", textureAtlas.RegisterTexture("lines/test-pattern",
":/res/textures/lines/test-pattern.png"); ":/res/textures/lines/test-pattern.png");
textureAtlas.BuildAtlas(8, 8); textureAtlas.BuildAtlas(1024, 1024);
} }
} // namespace ResourceManager } // namespace ResourceManager

View file

@ -18,7 +18,8 @@ void Shutdown();
int FontId(types::Font font); int FontId(types::Font font);
std::shared_ptr<util::Font> Font(types::Font font); std::shared_ptr<util::Font> Font(types::Font font);
void LoadImageResource(const std::string& urlString); bool LoadImageResource(const std::string& urlString);
void LoadImageResources(const std::vector<std::string>& urlStrings);
} // namespace ResourceManager } // namespace ResourceManager
} // namespace manager } // namespace manager

View file

@ -5,6 +5,7 @@
#include <shared_mutex> #include <shared_mutex>
#include <unordered_map> #include <unordered_map>
#include <variant>
#if defined(_MSC_VER) #if defined(_MSC_VER)
# pragma warning(push, 0) # pragma warning(push, 0)
@ -111,8 +112,11 @@ void TextureAtlas::BuildAtlas(size_t width, size_t height)
return; return;
} }
std::vector<std::pair<std::string, boost::gil::rgba8_image_t>> images; std::vector<std::pair<
std::vector<stbrp_rect> stbrpRects; std::string,
std::variant<boost::gil::rgba8_image_t, boost::gil::rgba8_image_t*>>>
images;
std::vector<stbrp_rect> stbrpRects;
// Load images // Load images
{ {
@ -145,9 +149,33 @@ void TextureAtlas::BuildAtlas(size_t width, size_t height)
}); });
} }
// TODO: Cached images // Cached images
{
// Take a read lock on the texture cache map. The read lock must persist
// through atlas population, as a pointer to the image is taken and used.
std::shared_lock textureCacheLock(p->textureCacheMutex_);
{
// For each cached texture
for (auto& texture : p->textureCache_)
{
auto& image = texture.second;
if (image.width() > 0u && image.height() > 0u)
{
// Store STB rectangle pack data in a vector
stbrpRects.push_back(
stbrp_rect {0,
static_cast<stbrp_coord>(image.width()),
static_cast<stbrp_coord>(image.height()),
0,
0,
0});
// Store image data in a vector
images.emplace_back(texture.first, &image);
}
}
} }
// Pack images // Pack images
@ -195,8 +223,22 @@ void TextureAtlas::BuildAtlas(size_t width, size_t height)
if (stbrpRects[i].was_packed != 0) if (stbrpRects[i].was_packed != 0)
{ {
// Populate the atlas // Populate the atlas
boost::gil::rgba8c_view_t imageView = boost::gil::rgba8c_view_t imageView;
boost::gil::const_view(images[i].second);
// Retrieve the image
if (std::holds_alternative<boost::gil::rgba8_image_t>(
images[i].second))
{
imageView = boost::gil::const_view(
std::get<boost::gil::rgba8_image_t>(images[i].second));
}
else if (std::holds_alternative<boost::gil::rgba8_image_t*>(
images[i].second))
{
imageView = boost::gil::const_view(
*std::get<boost::gil::rgba8_image_t*>(images[i].second));
}
boost::gil::rgba8_view_t atlasSubView = boost::gil::rgba8_view_t atlasSubView =
boost::gil::subimage_view(atlasView, boost::gil::subimage_view(atlasView,
stbrpRects[i].x, stbrpRects[i].x,