Skip to content

Commit 741b1a4

Browse files
committed
experimental: add octahedron output support
Octahedron output support for cmgen. use —type=octahedron. This is still fairly experimental.
1 parent 4177eb1 commit 741b1a4

File tree

3 files changed

+74
-2
lines changed

3 files changed

+74
-2
lines changed

tools/cmgen/src/CubemapUtils.cpp

+37
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <math/mat4.h>
2222

2323
#include <algorithm>
24+
#include <cmath>
2425

2526
#include <string.h>
2627

@@ -138,6 +139,42 @@ void CubemapUtils::cubemapToEquirectangular(Image& dst, const Cubemap& src) {
138139
js.reset();
139140
}
140141

142+
void CubemapUtils::cubemapToOctahedron(Image& dst, const Cubemap& src) {
143+
const double w = dst.getWidth();
144+
const double h = dst.getHeight();
145+
auto parallelJobTask = [&](size_t j0, size_t count) {
146+
for (size_t j = j0; j < j0 + count; j++) {
147+
for (size_t i = 0; i < w; i++) {
148+
float3 c = 0;
149+
const size_t numSamples = 64; // TODO: how to chose numsamples
150+
for (size_t sample = 0; sample < numSamples; sample++) {
151+
const double2 u = hammersley(uint32_t(sample), 1.0f / numSamples);
152+
double x = 2.0 * (i + u.x) / w - 1.0;
153+
double z = 2.0 * (j + u.y) / h - 1.0;
154+
double y;
155+
if (std::abs(z) > (1.0 - std::abs(x))) {
156+
double u = x < 0 ? std::abs(z) - 1 : 1 - std::abs(z);
157+
double v = z < 0 ? std::abs(x) - 1 : 1 - std::abs(x);
158+
x = u;
159+
z = v;
160+
y = (std::abs(x) + std::abs(z)) - 1.0;
161+
} else {
162+
y = 1.0 - (std::abs(x) + std::abs(z));
163+
}
164+
c += src.filterAt({x, y, z});
165+
}
166+
Cubemap::writeAt(dst.getPixelRef(i, j), c * (1.0 / numSamples));
167+
}
168+
}
169+
};
170+
171+
JobSystem& js = getJobSystem();
172+
auto job = jobs::parallel_for(js, nullptr, 0, uint32_t(h),
173+
std::ref(parallelJobTask), jobs::CountSplitter<1, 8>());
174+
js.runAndWait(job);
175+
js.reset();
176+
}
177+
141178
void CubemapUtils::crossToCubemap(Cubemap& dst, const Image& src) {
142179
process<EmptyState>(dst,
143180
[&](EmptyState&, size_t iy, Cubemap::Face f, Cubemap::Texel* data, size_t dimension) {

tools/cmgen/src/CubemapUtils.h

+2
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ class CubemapUtils {
5151

5252
static void cubemapToEquirectangular(Image& dst, const Cubemap& src);
5353

54+
static void cubemapToOctahedron(Image& dst, const Cubemap& src);
55+
5456
// Convert h or v cross Image to a Cubemap
5557
static void crossToCubemap(Cubemap& dst, const Image& src);
5658

tools/cmgen/src/cmgen.cpp

+35-2
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ static const size_t DFG_LUT_DEFAULT_SIZE = 128;
5151
static const size_t IBL_DEFAULT_SIZE = 256;
5252

5353
enum class OutputType {
54-
FACES, KTX, EQUIRECT
54+
FACES, KTX, EQUIRECT, OCTAHEDRON
5555
};
5656

5757
static image::ImageEncoder::Format g_format = image::ImageEncoder::Format::PNG;
@@ -140,7 +140,7 @@ static void printUsage(char* name) {
140140
" Print copyright and license information\n\n"
141141
" --quiet, -q\n"
142142
" Quiet mode. Suppress all non-error output\n\n"
143-
" --type=[faces|equirect|ktx], -t [cubemap|equirect|ktx]\n"
143+
" --type=[faces|equirect|octahedron|ktx], -t [cubemap|equirect|octahedron|ktx]\n"
144144
" Specify output type (default: cubemap)\n\n"
145145
" --format=[exr|hdr|psd|rgbm|png|dds|ktx], -f [exr|hdr|psd|rgbm|png|dds|ktx]\n"
146146
" Specify output file format. ktx implies -type=ktx.\n\n"
@@ -261,6 +261,10 @@ static int handleCommandLineArgments(int argc, char* argv[]) {
261261
g_type = OutputType::EQUIRECT;
262262
type_specified = true;
263263
}
264+
if (arg == "octahedron") {
265+
g_type = OutputType::OCTAHEDRON;
266+
type_specified = true;
267+
}
264268
break;
265269
case 'f':
266270
if (arg == "png") {
@@ -758,6 +762,16 @@ void iblMipmapPrefilter(const utils::Path& iname,
758762
continue;
759763
}
760764

765+
if (g_type == OutputType::OCTAHEDRON) {
766+
size_t dim = dst.getDimensions();
767+
std::unique_ptr<uint8_t[]> buf(new uint8_t[dim * dim * sizeof(float3)]);
768+
Image image(std::move(buf), dim, dim, dim * sizeof(float3), sizeof(float3));
769+
CubemapUtils::cubemapToOctahedron(image, dst);
770+
std::string filename = outputDir + ("is_m" + std::to_string(level) + ext);
771+
saveImage(filename, g_format, image, g_compression);
772+
continue;
773+
}
774+
761775
for (size_t i = 0; i < 6; i++) {
762776
Cubemap::Face face = (Cubemap::Face)i;
763777
std::string filename = outputDir
@@ -850,6 +864,15 @@ void iblRoughnessPrefilter(const utils::Path& iname,
850864
continue;
851865
}
852866

867+
if (g_type == OutputType::OCTAHEDRON) {
868+
std::unique_ptr<uint8_t[]> buf(new uint8_t[dim * dim * sizeof(float3)]);
869+
Image image(std::move(buf), dim, dim, dim * sizeof(float3), sizeof(float3));
870+
CubemapUtils::cubemapToOctahedron(image, dst);
871+
std::string filename = outputDir + ("m" + std::to_string(level) + ext);
872+
saveImage(filename, g_format, image, g_compression);
873+
continue;
874+
}
875+
853876
for (size_t j = 0; j < 6; j++) {
854877
Cubemap::Face face = (Cubemap::Face) j;
855878
std::string filename = outputDir
@@ -1017,6 +1040,16 @@ void extractCubemapFaces(const utils::Path& iname, const Cubemap& cm, const util
10171040
return;
10181041
}
10191042

1043+
if (g_type == OutputType::OCTAHEDRON) {
1044+
size_t dim = cm.getDimensions();
1045+
std::unique_ptr<uint8_t[]> buf(new uint8_t[dim * dim * sizeof(float3)]);
1046+
Image image(std::move(buf), dim, dim, dim * sizeof(float3), sizeof(float3));
1047+
CubemapUtils::cubemapToOctahedron(image, cm);
1048+
std::string filename = outputDir + ("skybox" + ext);
1049+
saveImage(filename, g_format, image, g_compression);
1050+
return;
1051+
}
1052+
10201053
for (size_t i = 0; i < 6; i++) {
10211054
Cubemap::Face face = (Cubemap::Face) i;
10221055
std::string filename(outputDir + (CubemapUtils::getFaceName(face) + ext));

0 commit comments

Comments
 (0)