Skip to content

Commit

Permalink
Handle skybox loading error.
Browse files Browse the repository at this point in the history
  • Loading branch information
stripe2933 committed Feb 21, 2025
1 parent 37a42db commit 0b30eb7
Showing 1 changed file with 40 additions and 26 deletions.
66 changes: 40 additions & 26 deletions impl/MainApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -877,13 +877,13 @@ void vk_gltf_viewer::MainApp::closeGltf() {
}

void vk_gltf_viewer::MainApp::loadEqmap(const std::filesystem::path &eqmapPath) {
const auto [eqmapImageExtent, eqmapStagingBuffer] = [&]() {
const auto loadResult = [&]() -> std::expected<std::pair<vk::Extent2D, vku::MappedBuffer>, std::string> {
if (auto extension = eqmapPath.extension(); extension == ".hdr") {
int width, height;
std::unique_ptr<float[]> data; // It should be freed after copying to the staging buffer, therefore declared as unique_ptr.
data.reset(stbi_loadf(PATH_C_STR(eqmapPath), &width, &height, nullptr, 4));
if (!data) {
throw std::runtime_error { std::format("Failed to load image: {}", stbi_failure_reason()) };
return std::unexpected { std::format("Failed to load image: {}", stbi_failure_reason()) };
}

return std::pair {
Expand All @@ -896,36 +896,50 @@ void vk_gltf_viewer::MainApp::loadEqmap(const std::filesystem::path &eqmapPath)
};
} // After this scope, data will be automatically freed.
else if (extension == ".exr") {
Imf::InputFile file { PATH_C_STR(eqmapPath), static_cast<int>(std::thread::hardware_concurrency()) };

const Imath::Box2i dw = file.header().dataWindow();
const vk::Extent2D eqmapExtent {
static_cast<std::uint32_t>(dw.max.x - dw.min.x + 1),
static_cast<std::uint32_t>(dw.max.y - dw.min.y + 1),
};
return [&]() -> std::expected<Imf::InputFile, std::string> {
try {
return Imf::InputFile { PATH_C_STR(eqmapPath), static_cast<int>(std::thread::hardware_concurrency()) };
}
catch (const Iex::InputExc &err) {
return std::unexpected { err.message() };
}
}().transform([this](Imf::InputFile file) {
const Imath::Box2i dw = file.header().dataWindow();
const vk::Extent2D eqmapExtent {
static_cast<std::uint32_t>(dw.max.x - dw.min.x + 1),
static_cast<std::uint32_t>(dw.max.y - dw.min.y + 1),
};

vku::MappedBuffer buffer { gpu.allocator, vk::BufferCreateInfo {
{},
blockSize(vk::Format::eR32G32B32A32Sfloat) * eqmapExtent.width * eqmapExtent.height,
vk::BufferUsageFlagBits::eTransferSrc,
} };
const std::span data = buffer.asRange<glm::vec4>();
vku::MappedBuffer buffer { gpu.allocator, vk::BufferCreateInfo {
{},
blockSize(vk::Format::eR32G32B32A32Sfloat) * eqmapExtent.width * eqmapExtent.height,
vk::BufferUsageFlagBits::eTransferSrc,
} };
const std::span data = buffer.asRange<glm::vec4>();

// Create frame buffers for each channel.
// Note: Alpha channel will be ignored.
Imf::FrameBuffer frameBuffer;
const std::size_t rowBytes = eqmapExtent.width * sizeof(glm::vec4);
frameBuffer.insert("R", Imf::Slice { Imf::FLOAT, reinterpret_cast<char*>(&data[0].x), sizeof(glm::vec4), rowBytes });
frameBuffer.insert("G", Imf::Slice { Imf::FLOAT, reinterpret_cast<char*>(&data[0].y), sizeof(glm::vec4), rowBytes });
frameBuffer.insert("B", Imf::Slice { Imf::FLOAT, reinterpret_cast<char*>(&data[0].z), sizeof(glm::vec4), rowBytes });
// Create frame buffers for each channel.
// Note: Alpha channel will be ignored.
Imf::FrameBuffer frameBuffer;
const std::size_t rowBytes = eqmapExtent.width * sizeof(glm::vec4);
frameBuffer.insert("R", Imf::Slice { Imf::FLOAT, reinterpret_cast<char*>(&data[0].x), sizeof(glm::vec4), rowBytes });
frameBuffer.insert("G", Imf::Slice { Imf::FLOAT, reinterpret_cast<char*>(&data[0].y), sizeof(glm::vec4), rowBytes });
frameBuffer.insert("B", Imf::Slice { Imf::FLOAT, reinterpret_cast<char*>(&data[0].z), sizeof(glm::vec4), rowBytes });

file.readPixels(frameBuffer, dw.min.y, dw.max.y);
file.readPixels(frameBuffer, dw.min.y, dw.max.y);

return std::pair { eqmapExtent, std::move(buffer) };
return std::pair { eqmapExtent, std::move(buffer) };
});
}
else {
return std::unexpected { "Unknown file format: only HDR and EXR are supported." };
}

throw std::runtime_error { "Unknown file format: only HDR and EXR are supported." };
}();
if (!loadResult) {
std::ignore = NMB::show("Skybox Loading Error", loadResult.error().c_str(), NMB::Icon::ICON_ERROR);
return;
}

const auto &[eqmapImageExtent, eqmapStagingBuffer] = *loadResult;

std::uint32_t eqmapImageMipLevels = 0;
for (std::uint32_t mipWidth = eqmapImageExtent.width; mipWidth > 512; mipWidth >>= 1, ++eqmapImageMipLevels);
Expand Down

0 comments on commit 0b30eb7

Please sign in to comment.