experimental: add octahedron output support

Octahedron output support for cmgen. use —type=octahedron.

This is still fairly experimental.
This commit is contained in:
Mathias Agopian
2018-09-28 17:08:48 -07:00
committed by Mathias Agopian
parent 4177eb14ed
commit 741b1a412d
3 changed files with 74 additions and 2 deletions

View File

@@ -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) {

View File

@@ -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);

View File

@@ -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));