experimental: add octahedron output support
Octahedron output support for cmgen. use —type=octahedron. This is still fairly experimental.
This commit is contained in:
committed by
Mathias Agopian
parent
4177eb14ed
commit
741b1a412d
@@ -21,6 +21,7 @@
|
||||
#include <math/mat4.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
@@ -138,6 +139,42 @@ void CubemapUtils::cubemapToEquirectangular(Image& dst, const Cubemap& src) {
|
||||
js.reset();
|
||||
}
|
||||
|
||||
void CubemapUtils::cubemapToOctahedron(Image& dst, const Cubemap& src) {
|
||||
const double w = dst.getWidth();
|
||||
const double h = dst.getHeight();
|
||||
auto parallelJobTask = [&](size_t j0, size_t count) {
|
||||
for (size_t j = j0; j < j0 + count; j++) {
|
||||
for (size_t i = 0; i < w; i++) {
|
||||
float3 c = 0;
|
||||
const size_t numSamples = 64; // TODO: how to chose numsamples
|
||||
for (size_t sample = 0; sample < numSamples; sample++) {
|
||||
const double2 u = hammersley(uint32_t(sample), 1.0f / numSamples);
|
||||
double x = 2.0 * (i + u.x) / w - 1.0;
|
||||
double z = 2.0 * (j + u.y) / h - 1.0;
|
||||
double y;
|
||||
if (std::abs(z) > (1.0 - std::abs(x))) {
|
||||
double u = x < 0 ? std::abs(z) - 1 : 1 - std::abs(z);
|
||||
double v = z < 0 ? std::abs(x) - 1 : 1 - std::abs(x);
|
||||
x = u;
|
||||
z = v;
|
||||
y = (std::abs(x) + std::abs(z)) - 1.0;
|
||||
} else {
|
||||
y = 1.0 - (std::abs(x) + std::abs(z));
|
||||
}
|
||||
c += src.filterAt({x, y, z});
|
||||
}
|
||||
Cubemap::writeAt(dst.getPixelRef(i, j), c * (1.0 / numSamples));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
JobSystem& js = getJobSystem();
|
||||
auto job = jobs::parallel_for(js, nullptr, 0, uint32_t(h),
|
||||
std::ref(parallelJobTask), jobs::CountSplitter<1, 8>());
|
||||
js.runAndWait(job);
|
||||
js.reset();
|
||||
}
|
||||
|
||||
void CubemapUtils::crossToCubemap(Cubemap& dst, const Image& src) {
|
||||
process<EmptyState>(dst,
|
||||
[&](EmptyState&, size_t iy, Cubemap::Face f, Cubemap::Texel* data, size_t dimension) {
|
||||
|
||||
@@ -51,6 +51,8 @@ public:
|
||||
|
||||
static void cubemapToEquirectangular(Image& dst, const Cubemap& src);
|
||||
|
||||
static void cubemapToOctahedron(Image& dst, const Cubemap& src);
|
||||
|
||||
// Convert h or v cross Image to a Cubemap
|
||||
static void crossToCubemap(Cubemap& dst, const Image& src);
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ static const size_t DFG_LUT_DEFAULT_SIZE = 128;
|
||||
static const size_t IBL_DEFAULT_SIZE = 256;
|
||||
|
||||
enum class OutputType {
|
||||
FACES, KTX, EQUIRECT
|
||||
FACES, KTX, EQUIRECT, OCTAHEDRON
|
||||
};
|
||||
|
||||
static image::ImageEncoder::Format g_format = image::ImageEncoder::Format::PNG;
|
||||
@@ -140,7 +140,7 @@ static void printUsage(char* name) {
|
||||
" Print copyright and license information\n\n"
|
||||
" --quiet, -q\n"
|
||||
" Quiet mode. Suppress all non-error output\n\n"
|
||||
" --type=[faces|equirect|ktx], -t [cubemap|equirect|ktx]\n"
|
||||
" --type=[faces|equirect|octahedron|ktx], -t [cubemap|equirect|octahedron|ktx]\n"
|
||||
" Specify output type (default: cubemap)\n\n"
|
||||
" --format=[exr|hdr|psd|rgbm|png|dds|ktx], -f [exr|hdr|psd|rgbm|png|dds|ktx]\n"
|
||||
" Specify output file format. ktx implies -type=ktx.\n\n"
|
||||
@@ -261,6 +261,10 @@ static int handleCommandLineArgments(int argc, char* argv[]) {
|
||||
g_type = OutputType::EQUIRECT;
|
||||
type_specified = true;
|
||||
}
|
||||
if (arg == "octahedron") {
|
||||
g_type = OutputType::OCTAHEDRON;
|
||||
type_specified = true;
|
||||
}
|
||||
break;
|
||||
case 'f':
|
||||
if (arg == "png") {
|
||||
@@ -758,6 +762,16 @@ void iblMipmapPrefilter(const utils::Path& iname,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (g_type == OutputType::OCTAHEDRON) {
|
||||
size_t dim = dst.getDimensions();
|
||||
std::unique_ptr<uint8_t[]> buf(new uint8_t[dim * dim * sizeof(float3)]);
|
||||
Image image(std::move(buf), dim, dim, dim * sizeof(float3), sizeof(float3));
|
||||
CubemapUtils::cubemapToOctahedron(image, dst);
|
||||
std::string filename = outputDir + ("is_m" + std::to_string(level) + ext);
|
||||
saveImage(filename, g_format, image, g_compression);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < 6; i++) {
|
||||
Cubemap::Face face = (Cubemap::Face)i;
|
||||
std::string filename = outputDir
|
||||
@@ -850,6 +864,15 @@ void iblRoughnessPrefilter(const utils::Path& iname,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (g_type == OutputType::OCTAHEDRON) {
|
||||
std::unique_ptr<uint8_t[]> buf(new uint8_t[dim * dim * sizeof(float3)]);
|
||||
Image image(std::move(buf), dim, dim, dim * sizeof(float3), sizeof(float3));
|
||||
CubemapUtils::cubemapToOctahedron(image, dst);
|
||||
std::string filename = outputDir + ("m" + std::to_string(level) + ext);
|
||||
saveImage(filename, g_format, image, g_compression);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (size_t j = 0; j < 6; j++) {
|
||||
Cubemap::Face face = (Cubemap::Face) j;
|
||||
std::string filename = outputDir
|
||||
@@ -1017,6 +1040,16 @@ void extractCubemapFaces(const utils::Path& iname, const Cubemap& cm, const util
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_type == OutputType::OCTAHEDRON) {
|
||||
size_t dim = cm.getDimensions();
|
||||
std::unique_ptr<uint8_t[]> buf(new uint8_t[dim * dim * sizeof(float3)]);
|
||||
Image image(std::move(buf), dim, dim, dim * sizeof(float3), sizeof(float3));
|
||||
CubemapUtils::cubemapToOctahedron(image, cm);
|
||||
std::string filename = outputDir + ("skybox" + ext);
|
||||
saveImage(filename, g_format, image, g_compression);
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < 6; i++) {
|
||||
Cubemap::Face face = (Cubemap::Face) i;
|
||||
std::string filename(outputDir + (CubemapUtils::getFaceName(face) + ext));
|
||||
|
||||
Reference in New Issue
Block a user