Browse Source

Improve OpenEXR image loading

master
C. J. Howard 2 years ago
parent
commit
2c3827f403
2 changed files with 90 additions and 12 deletions
  1. +14
    -0
      src/game/state/nuptial-flight.cpp
  2. +76
    -12
      src/resources/image-loader.cpp

+ 14
- 0
src/game/state/nuptial-flight.cpp View File

@ -38,6 +38,7 @@
#include "render/passes/clear-pass.hpp"
#include "render/passes/ground-pass.hpp"
#include "state-machine.hpp"
#include "scene/ambient-light.hpp"
#include "config.hpp"
namespace game {
@ -112,6 +113,19 @@ nuptial_flight::nuptial_flight(game::context& ctx):
ctx.astronomy_system->set_observer_location(double3{observer.elevation, observer.latitude, observer.longitude});
}
/*
scene::ambient_light* light = new scene::ambient_light();
light->set_color(float3{1, 1, 1} * 10000.0f);
ctx.surface_scene->add_object(light);
*/
// Create color checker
{
entity::archetype* color_checker_archetype = ctx.resource_manager->load<entity::archetype>("color-checker.ent");
auto color_checker_eid = color_checker_archetype->create(*ctx.entity_registry);
entity::command::warp_to(*ctx.entity_registry, color_checker_eid, {0, 0, 0});
}
// Setup camera
setup_camera();

+ 76
- 12
src/resources/image-loader.cpp View File

@ -41,30 +41,94 @@ image* resource_loader::load(resource_manager* resource_manager, PHYSFS_F
if (path.extension() == ".exr")
{
// Load OpenEXR with TinyEXR
float* pixels = nullptr;
int width = 0;
int height = 0;
int status = TINYEXR_SUCCESS;
const char* error = nullptr;
int status = LoadEXRFromMemory(&pixels, &width, &height, buffer, size, &error);
// Read EXR version
EXRVersion exr_version;
status = ParseEXRVersionFromMemory(&exr_version, buffer, size);
if (status != TINYEXR_SUCCESS)
{
delete[] buffer;
throw std::runtime_error("TinyEXR parse version error (" + std::to_string(status) + "): invalid EXR file");
}
// Check if image is multipart
if (exr_version.multipart)
{
throw std::runtime_error("OpenEXR multipart images not supported");
}
// Read EXR header
EXRHeader exr_header;
InitEXRHeader(&exr_header);
status = ParseEXRHeaderFromMemory(&exr_header, &exr_version, buffer, size, &error);
if (status != TINYEXR_SUCCESS)
{
std::string error_string(error);
FreeEXRErrorMessage(error);
throw std::runtime_error("TinyEXR error (" + std::to_string(status) + "): " + error_string);
delete[] buffer;
throw std::runtime_error("TinyEXR parse header error (" + std::to_string(status) + "): " + error_string);
}
// Check if image is tiled
if (exr_header.tiled)
{
FreeEXRHeader(&exr_header);
delete[] buffer;
throw std::runtime_error("OpenEXR tiled images not supported");
}
// Read half channels as float
for (int i = 0; i < exr_header.num_channels; ++i)
{
if (exr_header.pixel_types[i] == TINYEXR_PIXELTYPE_HALF)
{
exr_header.requested_pixel_types[i] = TINYEXR_PIXELTYPE_FLOAT;
}
}
// Read EXR data
EXRImage exr_image;
InitEXRImage(&exr_image);
status = LoadEXRImageFromMemory(&exr_image, &exr_header, buffer, size, &error);
if (status != TINYEXR_SUCCESS)
{
std::string error_string(error);
FreeEXRErrorMessage(error);
FreeEXRHeader(&exr_header);
delete[] buffer;
throw std::runtime_error("TinyEXR load error (" + std::to_string(status) + "): " + error_string);
}
// Free file buffer
delete[] buffer;
// Create image
std::size_t component_size = sizeof(float);
image = new ::image();
image->format(component_size, 4);
image->resize(static_cast<unsigned int>(width), static_cast<unsigned int>(height));
std::memcpy(image->get_pixels(), pixels, image->get_size());
image->format(sizeof(float), exr_image.num_channels);
image->resize(static_cast<unsigned int>(exr_image.width), static_cast<unsigned int>(exr_image.height));
// Fill image pixels
float* component = static_cast<float*>(image->get_pixels());
for (int y = exr_image.height - 1; y >= 0; --y)
{
int row_offset = y * exr_image.width;
for (int x = 0; x < exr_image.width; ++x)
{
int pixel_index = row_offset + x;
for (int c = exr_image.num_channels - 1; c >= 0; --c)
{
*(component++) = reinterpret_cast<float**>(exr_image.images)[c][pixel_index];
}
}
}
// Free loaded pixels
free(pixels);
// Free EXR data
FreeEXRImage(&exr_image);
FreeEXRHeader(&exr_header);
}
else
{

Loading…
Cancel
Save