separate skybox/ibl creation from KTX decoding

This commit is contained in:
Nick Fisher
2025-06-11 09:48:17 +08:00
parent 641d92515e
commit 8f1da5e7bd
8 changed files with 604 additions and 391 deletions

View File

@@ -1,6 +1,6 @@
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#endif
#endif
#include <vector>
@@ -17,6 +17,9 @@
#include <filament/image/ColorTransform.h>
#include <filament/backend/DriverEnums.h>
#include <ktxreader/Ktx1Reader.h>
#include <ktxreader/Ktx2Reader.h>
#include "c_api/TTexture.h"
#include "Log.hpp"
@@ -32,61 +35,117 @@ namespace thermion
using namespace filament::backend;
using namespace image;
#endif
inline float to_float(uint8_t v) {
return float(v);
}
EMSCRIPTEN_KEEPALIVE TLinearImage *Image_decode(uint8_t *data, size_t length, const char *name = "image", bool alpha = true)
{
auto start = std::chrono::high_resolution_clock::now();
int width, height, channels;
TRACE("Loading image from buffer of length %lu bytes (alpha : %s)", length, alpha ? "true" : "false");
uint8_t *imgData = stbi_load_from_memory(data, length, &width, &height, &channels, alpha ? 4 : 3);
if (!imgData) {
ERROR("Failed to decode image");
return nullptr;
}
LinearImage *linearImage;
if(alpha) {
linearImage = new LinearImage(toLinearWithAlpha<uint8_t>(
width,
height,
width * 4,
imgData,
to_float, sRGBToLinear<filament::math::float4>));
} else {
linearImage = new LinearImage(toLinear<uint8_t>(
width,
height,
width * 3,
imgData,
to_float, sRGBToLinear<filament::math::float3>));
}
auto end = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
TRACE("Image decoded successfully in %lld ms (%dx%dx%d)", duration.count(), width, height, channels);
if (!linearImage->isValid())
inline float to_float(uint8_t v)
{
Log("Failed to decode image.");
return nullptr;
return float(v);
}
EMSCRIPTEN_KEEPALIVE TLinearImage *Image_decode(uint8_t *data, size_t length, const char *name = "image", bool alpha = true)
{
auto start = std::chrono::high_resolution_clock::now();
int width, height, channels;
TRACE("Loading image from buffer of length %lu bytes (alpha : %s)", length, alpha ? "true" : "false");
uint8_t *imgData = stbi_load_from_memory(data, length, &width, &height, &channels, alpha ? 4 : 3);
if (!imgData)
{
ERROR("Failed to decode image");
return nullptr;
}
LinearImage *linearImage;
if (alpha)
{
linearImage = new LinearImage(toLinearWithAlpha<uint8_t>(
width,
height,
width * 4,
imgData,
to_float, sRGBToLinear<filament::math::float4>));
}
else
{
linearImage = new LinearImage(toLinear<uint8_t>(
width,
height,
width * 3,
imgData,
to_float, sRGBToLinear<filament::math::float3>));
}
auto end = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
TRACE("Image decoded successfully in %lld ms (%dx%dx%d)", duration.count(), width, height, channels);
if (!linearImage->isValid())
{
Log("Failed to decode image.");
return nullptr;
}
return reinterpret_cast<TLinearImage *>(linearImage);
}
EMSCRIPTEN_KEEPALIVE TTexture *Texture_decodeKtx(
TEngine *tEngine,
uint8_t *ktxData,
size_t length,
float *sphericalHarmonics,
uint32_t requestId,
VoidCallback onTextureUploadComplete)
{
auto engine = reinterpret_cast<filament::Engine *>(tEngine);
auto copy = new std::vector<uint8_t>(ktxData, ktxData + length);
image::Ktx1Bundle *bundle =
new image::Ktx1Bundle(static_cast<const uint8_t *>(copy->data()),
static_cast<uint32_t>(length));
filament::math::float3 harmonics[9];
if (sphericalHarmonics)
{
bundle->getSphericalHarmonics(harmonics);
memcpy(sphericalHarmonics, harmonics, 27 * sizeof(float));
}
std::vector<void *> *callbackData = new std::vector<void *>{
reinterpret_cast<void *>(onTextureUploadComplete),
reinterpret_cast<void *>(bundle),
reinterpret_cast<void *>(copy),
reinterpret_cast<void *>(requestId)};
auto *texture =
ktxreader::Ktx1Reader::createTexture(
engine, *bundle, false, [](void *userdata)
{
std::vector<void*>* vec = (std::vector<void*>*)userdata;
void *callbackPtr = vec->at(0);
image::Ktx1Bundle *bundle = reinterpret_cast<image::Ktx1Bundle *>(vec->at(1));
std::vector<uint8_t> *copy = reinterpret_cast<std::vector<uint8_t>*>(vec->at(2));
uintptr_t requestId = (uintptr_t)vec->at(3);
delete vec;
if (callbackPtr)
{
auto callback = ((VoidCallback)callbackPtr);
callback(requestId);
}
delete bundle;
delete copy; },
(void *)callbackData);
return reinterpret_cast<TTexture *>(texture);
}
return reinterpret_cast<TLinearImage *>(linearImage);
}
EMSCRIPTEN_KEEPALIVE float *Image_getBytes(TLinearImage *tLinearImage)
{
@@ -116,191 +175,306 @@ namespace thermion
delete linearImage;
}
::filament::Texture::InternalFormat convertToFilamentFormat(TTextureFormat tFormat) {
switch (tFormat) {
// 8-bits per element
case TEXTUREFORMAT_R8: return ::filament::Texture::InternalFormat::R8;
case TEXTUREFORMAT_R8_SNORM: return ::filament::Texture::InternalFormat::R8_SNORM;
case TEXTUREFORMAT_R8UI: return ::filament::Texture::InternalFormat::R8UI;
case TEXTUREFORMAT_R8I: return ::filament::Texture::InternalFormat::R8I;
case TEXTUREFORMAT_STENCIL8: return ::filament::Texture::InternalFormat::STENCIL8;
// 16-bits per element
case TEXTUREFORMAT_R16F: return ::filament::Texture::InternalFormat::R16F;
case TEXTUREFORMAT_R16UI: return ::filament::Texture::InternalFormat::R16UI;
case TEXTUREFORMAT_R16I: return ::filament::Texture::InternalFormat::R16I;
case TEXTUREFORMAT_RG8: return ::filament::Texture::InternalFormat::RG8;
case TEXTUREFORMAT_RG8_SNORM: return ::filament::Texture::InternalFormat::RG8_SNORM;
case TEXTUREFORMAT_RG8UI: return ::filament::Texture::InternalFormat::RG8UI;
case TEXTUREFORMAT_RG8I: return ::filament::Texture::InternalFormat::RG8I;
case TEXTUREFORMAT_RGB565: return ::filament::Texture::InternalFormat::RGB565;
case TEXTUREFORMAT_RGB9_E5: return ::filament::Texture::InternalFormat::RGB9_E5;
case TEXTUREFORMAT_RGB5_A1: return ::filament::Texture::InternalFormat::RGB5_A1;
case TEXTUREFORMAT_RGBA4: return ::filament::Texture::InternalFormat::RGBA4;
case TEXTUREFORMAT_DEPTH16: return ::filament::Texture::InternalFormat::DEPTH16;
// 24-bits per element
case TEXTUREFORMAT_RGB8: return ::filament::Texture::InternalFormat::RGB8;
case TEXTUREFORMAT_SRGB8: return ::filament::Texture::InternalFormat::SRGB8;
case TEXTUREFORMAT_RGB8_SNORM: return ::filament::Texture::InternalFormat::RGB8_SNORM;
case TEXTUREFORMAT_RGB8UI: return ::filament::Texture::InternalFormat::RGB8UI;
case TEXTUREFORMAT_RGB8I: return ::filament::Texture::InternalFormat::RGB8I;
case TEXTUREFORMAT_DEPTH24: return ::filament::Texture::InternalFormat::DEPTH24;
// 32-bits per element
case TEXTUREFORMAT_R32F: return ::filament::Texture::InternalFormat::R32F;
case TEXTUREFORMAT_R32UI: return ::filament::Texture::InternalFormat::R32UI;
case TEXTUREFORMAT_R32I: return ::filament::Texture::InternalFormat::R32I;
case TEXTUREFORMAT_RG16F: return ::filament::Texture::InternalFormat::RG16F;
case TEXTUREFORMAT_RG16UI: return ::filament::Texture::InternalFormat::RG16UI;
case TEXTUREFORMAT_RG16I: return ::filament::Texture::InternalFormat::RG16I;
case TEXTUREFORMAT_R11F_G11F_B10F: return ::filament::Texture::InternalFormat::R11F_G11F_B10F;
case TEXTUREFORMAT_RGBA8: return ::filament::Texture::InternalFormat::RGBA8;
case TEXTUREFORMAT_SRGB8_A8: return ::filament::Texture::InternalFormat::SRGB8_A8;
case TEXTUREFORMAT_RGBA8_SNORM: return ::filament::Texture::InternalFormat::RGBA8_SNORM;
case TEXTUREFORMAT_UNUSED: return ::filament::Texture::InternalFormat::UNUSED;
case TEXTUREFORMAT_RGB10_A2: return ::filament::Texture::InternalFormat::RGB10_A2;
case TEXTUREFORMAT_RGBA8UI: return ::filament::Texture::InternalFormat::RGBA8UI;
case TEXTUREFORMAT_RGBA8I: return ::filament::Texture::InternalFormat::RGBA8I;
case TEXTUREFORMAT_DEPTH32F: return ::filament::Texture::InternalFormat::DEPTH32F;
case TEXTUREFORMAT_DEPTH24_STENCIL8: return ::filament::Texture::InternalFormat::DEPTH24_STENCIL8;
case TEXTUREFORMAT_DEPTH32F_STENCIL8: return ::filament::Texture::InternalFormat::DEPTH32F_STENCIL8;
// 48-bits per element
case TEXTUREFORMAT_RGB16F: return ::filament::Texture::InternalFormat::RGB16F;
case TEXTUREFORMAT_RGB16UI: return ::filament::Texture::InternalFormat::RGB16UI;
case TEXTUREFORMAT_RGB16I: return ::filament::Texture::InternalFormat::RGB16I;
// 64-bits per element
case TEXTUREFORMAT_RG32F: return ::filament::Texture::InternalFormat::RG32F;
case TEXTUREFORMAT_RG32UI: return ::filament::Texture::InternalFormat::RG32UI;
case TEXTUREFORMAT_RG32I: return ::filament::Texture::InternalFormat::RG32I;
case TEXTUREFORMAT_RGBA16F: return ::filament::Texture::InternalFormat::RGBA16F;
case TEXTUREFORMAT_RGBA16UI: return ::filament::Texture::InternalFormat::RGBA16UI;
case TEXTUREFORMAT_RGBA16I: return ::filament::Texture::InternalFormat::RGBA16I;
// 96-bits per element
case TEXTUREFORMAT_RGB32F: return ::filament::Texture::InternalFormat::RGB32F;
case TEXTUREFORMAT_RGB32UI: return ::filament::Texture::InternalFormat::RGB32UI;
case TEXTUREFORMAT_RGB32I: return ::filament::Texture::InternalFormat::RGB32I;
// 128-bits per element
case TEXTUREFORMAT_RGBA32F: return ::filament::Texture::InternalFormat::RGBA32F;
case TEXTUREFORMAT_RGBA32UI: return ::filament::Texture::InternalFormat::RGBA32UI;
case TEXTUREFORMAT_RGBA32I: return ::filament::Texture::InternalFormat::RGBA32I;
// Compressed formats
case TEXTUREFORMAT_EAC_R11: return ::filament::Texture::InternalFormat::EAC_R11;
case TEXTUREFORMAT_EAC_R11_SIGNED: return ::filament::Texture::InternalFormat::EAC_R11_SIGNED;
case TEXTUREFORMAT_EAC_RG11: return ::filament::Texture::InternalFormat::EAC_RG11;
case TEXTUREFORMAT_EAC_RG11_SIGNED: return ::filament::Texture::InternalFormat::EAC_RG11_SIGNED;
case TEXTUREFORMAT_ETC2_RGB8: return ::filament::Texture::InternalFormat::ETC2_RGB8;
case TEXTUREFORMAT_ETC2_SRGB8: return ::filament::Texture::InternalFormat::ETC2_SRGB8;
case TEXTUREFORMAT_ETC2_RGB8_A1: return ::filament::Texture::InternalFormat::ETC2_RGB8_A1;
case TEXTUREFORMAT_ETC2_SRGB8_A1: return ::filament::Texture::InternalFormat::ETC2_SRGB8_A1;
case TEXTUREFORMAT_ETC2_EAC_RGBA8: return ::filament::Texture::InternalFormat::ETC2_EAC_RGBA8;
case TEXTUREFORMAT_ETC2_EAC_SRGBA8: return ::filament::Texture::InternalFormat::ETC2_EAC_SRGBA8;
// DXT formats
case TEXTUREFORMAT_DXT1_RGB: return ::filament::Texture::InternalFormat::DXT1_RGB;
case TEXTUREFORMAT_DXT1_RGBA: return ::filament::Texture::InternalFormat::DXT1_RGBA;
case TEXTUREFORMAT_DXT3_RGBA: return ::filament::Texture::InternalFormat::DXT3_RGBA;
case TEXTUREFORMAT_DXT5_RGBA: return ::filament::Texture::InternalFormat::DXT5_RGBA;
case TEXTUREFORMAT_DXT1_SRGB: return ::filament::Texture::InternalFormat::DXT1_SRGB;
case TEXTUREFORMAT_DXT1_SRGBA: return ::filament::Texture::InternalFormat::DXT1_SRGBA;
case TEXTUREFORMAT_DXT3_SRGBA: return ::filament::Texture::InternalFormat::DXT3_SRGBA;
case TEXTUREFORMAT_DXT5_SRGBA: return ::filament::Texture::InternalFormat::DXT5_SRGBA;
// ASTC formats
case TEXTUREFORMAT_RGBA_ASTC_4x4: return ::filament::Texture::InternalFormat::RGBA_ASTC_4x4;
case TEXTUREFORMAT_RGBA_ASTC_5x4: return ::filament::Texture::InternalFormat::RGBA_ASTC_5x4;
case TEXTUREFORMAT_RGBA_ASTC_5x5: return ::filament::Texture::InternalFormat::RGBA_ASTC_5x5;
case TEXTUREFORMAT_RGBA_ASTC_6x5: return ::filament::Texture::InternalFormat::RGBA_ASTC_6x5;
case TEXTUREFORMAT_RGBA_ASTC_6x6: return ::filament::Texture::InternalFormat::RGBA_ASTC_6x6;
case TEXTUREFORMAT_RGBA_ASTC_8x5: return ::filament::Texture::InternalFormat::RGBA_ASTC_8x5;
case TEXTUREFORMAT_RGBA_ASTC_8x6: return ::filament::Texture::InternalFormat::RGBA_ASTC_8x6;
case TEXTUREFORMAT_RGBA_ASTC_8x8: return ::filament::Texture::InternalFormat::RGBA_ASTC_8x8;
case TEXTUREFORMAT_RGBA_ASTC_10x5: return ::filament::Texture::InternalFormat::RGBA_ASTC_10x5;
case TEXTUREFORMAT_RGBA_ASTC_10x6: return ::filament::Texture::InternalFormat::RGBA_ASTC_10x6;
case TEXTUREFORMAT_RGBA_ASTC_10x8: return ::filament::Texture::InternalFormat::RGBA_ASTC_10x8;
case TEXTUREFORMAT_RGBA_ASTC_10x10: return ::filament::Texture::InternalFormat::RGBA_ASTC_10x10;
case TEXTUREFORMAT_RGBA_ASTC_12x10: return ::filament::Texture::InternalFormat::RGBA_ASTC_12x10;
case TEXTUREFORMAT_RGBA_ASTC_12x12: return ::filament::Texture::InternalFormat::RGBA_ASTC_12x12;
case TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_4x4: return ::filament::Texture::InternalFormat::SRGB8_ALPHA8_ASTC_4x4;
case TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_5x4: return ::filament::Texture::InternalFormat::SRGB8_ALPHA8_ASTC_5x4;
case TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_5x5: return ::filament::Texture::InternalFormat::SRGB8_ALPHA8_ASTC_5x5;
case TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_6x5: return ::filament::Texture::InternalFormat::SRGB8_ALPHA8_ASTC_6x5;
case TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_6x6: return ::filament::Texture::InternalFormat::SRGB8_ALPHA8_ASTC_6x6;
case TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_8x5: return ::filament::Texture::InternalFormat::SRGB8_ALPHA8_ASTC_8x5;
case TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_8x6: return ::filament::Texture::InternalFormat::SRGB8_ALPHA8_ASTC_8x6;
case TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_8x8: return ::filament::Texture::InternalFormat::SRGB8_ALPHA8_ASTC_8x8;
case TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_10x5: return ::filament::Texture::InternalFormat::SRGB8_ALPHA8_ASTC_10x5;
case TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_10x6: return ::filament::Texture::InternalFormat::SRGB8_ALPHA8_ASTC_10x6;
case TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_10x8: return ::filament::Texture::InternalFormat::SRGB8_ALPHA8_ASTC_10x8;
case TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_10x10:return ::filament::Texture::InternalFormat::SRGB8_ALPHA8_ASTC_10x10;
case TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_12x10:return ::filament::Texture::InternalFormat::SRGB8_ALPHA8_ASTC_12x10;
case TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_12x12:return ::filament::Texture::InternalFormat::SRGB8_ALPHA8_ASTC_12x12;
// RGTC formats
case TEXTUREFORMAT_RED_RGTC1: return ::filament::Texture::InternalFormat::RED_RGTC1;
case TEXTUREFORMAT_SIGNED_RED_RGTC1: return ::filament::Texture::InternalFormat::SIGNED_RED_RGTC1;
case TEXTUREFORMAT_RED_GREEN_RGTC2: return ::filament::Texture::InternalFormat::RED_GREEN_RGTC2;
case TEXTUREFORMAT_SIGNED_RED_GREEN_RGTC2: return ::filament::Texture::InternalFormat::SIGNED_RED_GREEN_RGTC2;
// BPTC formats
case TEXTUREFORMAT_RGB_BPTC_SIGNED_FLOAT: return ::filament::Texture::InternalFormat::RGB_BPTC_SIGNED_FLOAT;
case TEXTUREFORMAT_RGB_BPTC_UNSIGNED_FLOAT:return ::filament::Texture::InternalFormat::RGB_BPTC_UNSIGNED_FLOAT;
case TEXTUREFORMAT_RGBA_BPTC_UNORM: return ::filament::Texture::InternalFormat::RGBA_BPTC_UNORM;
case TEXTUREFORMAT_SRGB_ALPHA_BPTC_UNORM: return ::filament::Texture::InternalFormat::SRGB_ALPHA_BPTC_UNORM;
default:
// Fallback to a common format if an unknown format is provided
return ::filament::Texture::InternalFormat::RGBA8;
::filament::Texture::InternalFormat convertToFilamentFormat(TTextureFormat tFormat)
{
switch (tFormat)
{
// 8-bits per element
case TEXTUREFORMAT_R8:
return ::filament::Texture::InternalFormat::R8;
case TEXTUREFORMAT_R8_SNORM:
return ::filament::Texture::InternalFormat::R8_SNORM;
case TEXTUREFORMAT_R8UI:
return ::filament::Texture::InternalFormat::R8UI;
case TEXTUREFORMAT_R8I:
return ::filament::Texture::InternalFormat::R8I;
case TEXTUREFORMAT_STENCIL8:
return ::filament::Texture::InternalFormat::STENCIL8;
// 16-bits per element
case TEXTUREFORMAT_R16F:
return ::filament::Texture::InternalFormat::R16F;
case TEXTUREFORMAT_R16UI:
return ::filament::Texture::InternalFormat::R16UI;
case TEXTUREFORMAT_R16I:
return ::filament::Texture::InternalFormat::R16I;
case TEXTUREFORMAT_RG8:
return ::filament::Texture::InternalFormat::RG8;
case TEXTUREFORMAT_RG8_SNORM:
return ::filament::Texture::InternalFormat::RG8_SNORM;
case TEXTUREFORMAT_RG8UI:
return ::filament::Texture::InternalFormat::RG8UI;
case TEXTUREFORMAT_RG8I:
return ::filament::Texture::InternalFormat::RG8I;
case TEXTUREFORMAT_RGB565:
return ::filament::Texture::InternalFormat::RGB565;
case TEXTUREFORMAT_RGB9_E5:
return ::filament::Texture::InternalFormat::RGB9_E5;
case TEXTUREFORMAT_RGB5_A1:
return ::filament::Texture::InternalFormat::RGB5_A1;
case TEXTUREFORMAT_RGBA4:
return ::filament::Texture::InternalFormat::RGBA4;
case TEXTUREFORMAT_DEPTH16:
return ::filament::Texture::InternalFormat::DEPTH16;
// 24-bits per element
case TEXTUREFORMAT_RGB8:
return ::filament::Texture::InternalFormat::RGB8;
case TEXTUREFORMAT_SRGB8:
return ::filament::Texture::InternalFormat::SRGB8;
case TEXTUREFORMAT_RGB8_SNORM:
return ::filament::Texture::InternalFormat::RGB8_SNORM;
case TEXTUREFORMAT_RGB8UI:
return ::filament::Texture::InternalFormat::RGB8UI;
case TEXTUREFORMAT_RGB8I:
return ::filament::Texture::InternalFormat::RGB8I;
case TEXTUREFORMAT_DEPTH24:
return ::filament::Texture::InternalFormat::DEPTH24;
// 32-bits per element
case TEXTUREFORMAT_R32F:
return ::filament::Texture::InternalFormat::R32F;
case TEXTUREFORMAT_R32UI:
return ::filament::Texture::InternalFormat::R32UI;
case TEXTUREFORMAT_R32I:
return ::filament::Texture::InternalFormat::R32I;
case TEXTUREFORMAT_RG16F:
return ::filament::Texture::InternalFormat::RG16F;
case TEXTUREFORMAT_RG16UI:
return ::filament::Texture::InternalFormat::RG16UI;
case TEXTUREFORMAT_RG16I:
return ::filament::Texture::InternalFormat::RG16I;
case TEXTUREFORMAT_R11F_G11F_B10F:
return ::filament::Texture::InternalFormat::R11F_G11F_B10F;
case TEXTUREFORMAT_RGBA8:
return ::filament::Texture::InternalFormat::RGBA8;
case TEXTUREFORMAT_SRGB8_A8:
return ::filament::Texture::InternalFormat::SRGB8_A8;
case TEXTUREFORMAT_RGBA8_SNORM:
return ::filament::Texture::InternalFormat::RGBA8_SNORM;
case TEXTUREFORMAT_UNUSED:
return ::filament::Texture::InternalFormat::UNUSED;
case TEXTUREFORMAT_RGB10_A2:
return ::filament::Texture::InternalFormat::RGB10_A2;
case TEXTUREFORMAT_RGBA8UI:
return ::filament::Texture::InternalFormat::RGBA8UI;
case TEXTUREFORMAT_RGBA8I:
return ::filament::Texture::InternalFormat::RGBA8I;
case TEXTUREFORMAT_DEPTH32F:
return ::filament::Texture::InternalFormat::DEPTH32F;
case TEXTUREFORMAT_DEPTH24_STENCIL8:
return ::filament::Texture::InternalFormat::DEPTH24_STENCIL8;
case TEXTUREFORMAT_DEPTH32F_STENCIL8:
return ::filament::Texture::InternalFormat::DEPTH32F_STENCIL8;
// 48-bits per element
case TEXTUREFORMAT_RGB16F:
return ::filament::Texture::InternalFormat::RGB16F;
case TEXTUREFORMAT_RGB16UI:
return ::filament::Texture::InternalFormat::RGB16UI;
case TEXTUREFORMAT_RGB16I:
return ::filament::Texture::InternalFormat::RGB16I;
// 64-bits per element
case TEXTUREFORMAT_RG32F:
return ::filament::Texture::InternalFormat::RG32F;
case TEXTUREFORMAT_RG32UI:
return ::filament::Texture::InternalFormat::RG32UI;
case TEXTUREFORMAT_RG32I:
return ::filament::Texture::InternalFormat::RG32I;
case TEXTUREFORMAT_RGBA16F:
return ::filament::Texture::InternalFormat::RGBA16F;
case TEXTUREFORMAT_RGBA16UI:
return ::filament::Texture::InternalFormat::RGBA16UI;
case TEXTUREFORMAT_RGBA16I:
return ::filament::Texture::InternalFormat::RGBA16I;
// 96-bits per element
case TEXTUREFORMAT_RGB32F:
return ::filament::Texture::InternalFormat::RGB32F;
case TEXTUREFORMAT_RGB32UI:
return ::filament::Texture::InternalFormat::RGB32UI;
case TEXTUREFORMAT_RGB32I:
return ::filament::Texture::InternalFormat::RGB32I;
// 128-bits per element
case TEXTUREFORMAT_RGBA32F:
return ::filament::Texture::InternalFormat::RGBA32F;
case TEXTUREFORMAT_RGBA32UI:
return ::filament::Texture::InternalFormat::RGBA32UI;
case TEXTUREFORMAT_RGBA32I:
return ::filament::Texture::InternalFormat::RGBA32I;
// Compressed formats
case TEXTUREFORMAT_EAC_R11:
return ::filament::Texture::InternalFormat::EAC_R11;
case TEXTUREFORMAT_EAC_R11_SIGNED:
return ::filament::Texture::InternalFormat::EAC_R11_SIGNED;
case TEXTUREFORMAT_EAC_RG11:
return ::filament::Texture::InternalFormat::EAC_RG11;
case TEXTUREFORMAT_EAC_RG11_SIGNED:
return ::filament::Texture::InternalFormat::EAC_RG11_SIGNED;
case TEXTUREFORMAT_ETC2_RGB8:
return ::filament::Texture::InternalFormat::ETC2_RGB8;
case TEXTUREFORMAT_ETC2_SRGB8:
return ::filament::Texture::InternalFormat::ETC2_SRGB8;
case TEXTUREFORMAT_ETC2_RGB8_A1:
return ::filament::Texture::InternalFormat::ETC2_RGB8_A1;
case TEXTUREFORMAT_ETC2_SRGB8_A1:
return ::filament::Texture::InternalFormat::ETC2_SRGB8_A1;
case TEXTUREFORMAT_ETC2_EAC_RGBA8:
return ::filament::Texture::InternalFormat::ETC2_EAC_RGBA8;
case TEXTUREFORMAT_ETC2_EAC_SRGBA8:
return ::filament::Texture::InternalFormat::ETC2_EAC_SRGBA8;
// DXT formats
case TEXTUREFORMAT_DXT1_RGB:
return ::filament::Texture::InternalFormat::DXT1_RGB;
case TEXTUREFORMAT_DXT1_RGBA:
return ::filament::Texture::InternalFormat::DXT1_RGBA;
case TEXTUREFORMAT_DXT3_RGBA:
return ::filament::Texture::InternalFormat::DXT3_RGBA;
case TEXTUREFORMAT_DXT5_RGBA:
return ::filament::Texture::InternalFormat::DXT5_RGBA;
case TEXTUREFORMAT_DXT1_SRGB:
return ::filament::Texture::InternalFormat::DXT1_SRGB;
case TEXTUREFORMAT_DXT1_SRGBA:
return ::filament::Texture::InternalFormat::DXT1_SRGBA;
case TEXTUREFORMAT_DXT3_SRGBA:
return ::filament::Texture::InternalFormat::DXT3_SRGBA;
case TEXTUREFORMAT_DXT5_SRGBA:
return ::filament::Texture::InternalFormat::DXT5_SRGBA;
// ASTC formats
case TEXTUREFORMAT_RGBA_ASTC_4x4:
return ::filament::Texture::InternalFormat::RGBA_ASTC_4x4;
case TEXTUREFORMAT_RGBA_ASTC_5x4:
return ::filament::Texture::InternalFormat::RGBA_ASTC_5x4;
case TEXTUREFORMAT_RGBA_ASTC_5x5:
return ::filament::Texture::InternalFormat::RGBA_ASTC_5x5;
case TEXTUREFORMAT_RGBA_ASTC_6x5:
return ::filament::Texture::InternalFormat::RGBA_ASTC_6x5;
case TEXTUREFORMAT_RGBA_ASTC_6x6:
return ::filament::Texture::InternalFormat::RGBA_ASTC_6x6;
case TEXTUREFORMAT_RGBA_ASTC_8x5:
return ::filament::Texture::InternalFormat::RGBA_ASTC_8x5;
case TEXTUREFORMAT_RGBA_ASTC_8x6:
return ::filament::Texture::InternalFormat::RGBA_ASTC_8x6;
case TEXTUREFORMAT_RGBA_ASTC_8x8:
return ::filament::Texture::InternalFormat::RGBA_ASTC_8x8;
case TEXTUREFORMAT_RGBA_ASTC_10x5:
return ::filament::Texture::InternalFormat::RGBA_ASTC_10x5;
case TEXTUREFORMAT_RGBA_ASTC_10x6:
return ::filament::Texture::InternalFormat::RGBA_ASTC_10x6;
case TEXTUREFORMAT_RGBA_ASTC_10x8:
return ::filament::Texture::InternalFormat::RGBA_ASTC_10x8;
case TEXTUREFORMAT_RGBA_ASTC_10x10:
return ::filament::Texture::InternalFormat::RGBA_ASTC_10x10;
case TEXTUREFORMAT_RGBA_ASTC_12x10:
return ::filament::Texture::InternalFormat::RGBA_ASTC_12x10;
case TEXTUREFORMAT_RGBA_ASTC_12x12:
return ::filament::Texture::InternalFormat::RGBA_ASTC_12x12;
case TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_4x4:
return ::filament::Texture::InternalFormat::SRGB8_ALPHA8_ASTC_4x4;
case TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_5x4:
return ::filament::Texture::InternalFormat::SRGB8_ALPHA8_ASTC_5x4;
case TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_5x5:
return ::filament::Texture::InternalFormat::SRGB8_ALPHA8_ASTC_5x5;
case TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_6x5:
return ::filament::Texture::InternalFormat::SRGB8_ALPHA8_ASTC_6x5;
case TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_6x6:
return ::filament::Texture::InternalFormat::SRGB8_ALPHA8_ASTC_6x6;
case TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_8x5:
return ::filament::Texture::InternalFormat::SRGB8_ALPHA8_ASTC_8x5;
case TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_8x6:
return ::filament::Texture::InternalFormat::SRGB8_ALPHA8_ASTC_8x6;
case TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_8x8:
return ::filament::Texture::InternalFormat::SRGB8_ALPHA8_ASTC_8x8;
case TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_10x5:
return ::filament::Texture::InternalFormat::SRGB8_ALPHA8_ASTC_10x5;
case TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_10x6:
return ::filament::Texture::InternalFormat::SRGB8_ALPHA8_ASTC_10x6;
case TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_10x8:
return ::filament::Texture::InternalFormat::SRGB8_ALPHA8_ASTC_10x8;
case TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_10x10:
return ::filament::Texture::InternalFormat::SRGB8_ALPHA8_ASTC_10x10;
case TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_12x10:
return ::filament::Texture::InternalFormat::SRGB8_ALPHA8_ASTC_12x10;
case TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_12x12:
return ::filament::Texture::InternalFormat::SRGB8_ALPHA8_ASTC_12x12;
// RGTC formats
case TEXTUREFORMAT_RED_RGTC1:
return ::filament::Texture::InternalFormat::RED_RGTC1;
case TEXTUREFORMAT_SIGNED_RED_RGTC1:
return ::filament::Texture::InternalFormat::SIGNED_RED_RGTC1;
case TEXTUREFORMAT_RED_GREEN_RGTC2:
return ::filament::Texture::InternalFormat::RED_GREEN_RGTC2;
case TEXTUREFORMAT_SIGNED_RED_GREEN_RGTC2:
return ::filament::Texture::InternalFormat::SIGNED_RED_GREEN_RGTC2;
// BPTC formats
case TEXTUREFORMAT_RGB_BPTC_SIGNED_FLOAT:
return ::filament::Texture::InternalFormat::RGB_BPTC_SIGNED_FLOAT;
case TEXTUREFORMAT_RGB_BPTC_UNSIGNED_FLOAT:
return ::filament::Texture::InternalFormat::RGB_BPTC_UNSIGNED_FLOAT;
case TEXTUREFORMAT_RGBA_BPTC_UNORM:
return ::filament::Texture::InternalFormat::RGBA_BPTC_UNORM;
case TEXTUREFORMAT_SRGB_ALPHA_BPTC_UNORM:
return ::filament::Texture::InternalFormat::SRGB_ALPHA_BPTC_UNORM;
default:
// Fallback to a common format if an unknown format is provided
return ::filament::Texture::InternalFormat::RGBA8;
}
}
EMSCRIPTEN_KEEPALIVE TTexture *Texture_build(
TEngine *tEngine,
uint32_t width,
uint32_t height,
uint32_t depth,
uint8_t levels,
TEngine *tEngine,
uint32_t width,
uint32_t height,
uint32_t depth,
uint8_t levels,
uint16_t tUsage,
intptr_t import,
TTextureSamplerType tSamplerType,
TTextureFormat tFormat
)
TTextureSamplerType tSamplerType,
TTextureFormat tFormat)
{
TRACE("Creating texture %dx%d (depth %d), sampler type %d, format %d tUsage %d, %d levels", width, height, depth, static_cast<int>(tSamplerType), static_cast<int>(tFormat), tUsage, levels);
auto *engine = reinterpret_cast<::filament::Engine *>(tEngine);
auto format = convertToFilamentFormat(tFormat);
auto samplerType = static_cast<::filament::Texture::Sampler>(static_cast<int>(tSamplerType));
auto usage = static_cast<TextureUsage>(tUsage);
auto builder = ::filament::Texture::Builder()
.width(width)
.height(height)
.depth(depth)
.levels(levels)
.sampler(samplerType)
.format(format)
.usage(usage);
if(import) {
.width(width)
.height(height)
.depth(depth)
.levels(levels)
.sampler(samplerType)
.format(format)
.usage(usage);
if (import)
{
TRACE("Importing texture with handle : %d", import);
builder.import(import);
}
auto *texture = builder
.build(*engine);
if(texture) {
.build(*engine);
if (texture)
{
TRACE("Texture successfully created with %d levels", texture->getLevels());
} else {
}
else
{
Log("Error: failed to created texture");
}
return reinterpret_cast<TTexture *>(texture);
}
EMSCRIPTEN_KEEPALIVE size_t Texture_getLevels(TTexture *tTexture) {
EMSCRIPTEN_KEEPALIVE size_t Texture_getLevels(TTexture *tTexture)
{
auto texture = reinterpret_cast<filament::Texture *>(tTexture);
return texture->getLevels();
}
@@ -365,14 +539,14 @@ namespace thermion
switch (bufferFormat)
{
case PixelBufferDescriptor::PixelDataFormat::RGB:
case PixelBufferDescriptor::PixelDataFormat::RGBA:
case PixelBufferDescriptor::PixelDataFormat::RGB_INTEGER:
case PixelBufferDescriptor::PixelDataFormat::RGBA_INTEGER:
break;
default:
Log("Unsupported buffer format type : %d", bufferFormat);
return false;
case PixelBufferDescriptor::PixelDataFormat::RGB:
case PixelBufferDescriptor::PixelDataFormat::RGBA:
case PixelBufferDescriptor::PixelDataFormat::RGB_INTEGER:
case PixelBufferDescriptor::PixelDataFormat::RGBA_INTEGER:
break;
default:
Log("Unsupported buffer format type : %d", bufferFormat);
return false;
}
// the texture upload is async, so we need to copy the buffer
@@ -380,7 +554,7 @@ namespace thermion
std::copy(data, data + size, buffer->begin());
filament::Texture::PixelBufferDescriptor::Callback freeCallback = [](void *buf, size_t,
void *data)
void *data)
{
delete reinterpret_cast<std::vector<uint8_t> *>(data);
};
@@ -396,7 +570,7 @@ namespace thermion
0, // stride
freeCallback,
buffer);
texture->setImage(*engine, level, std::move(pbd));
return true;
}
@@ -457,9 +631,8 @@ namespace thermion
std::copy(data, data + size, buffer->begin());
filament::Texture::PixelBufferDescriptor::Callback freeCallback = [](void *buf, size_t,
void *data)
void *data)
{
delete reinterpret_cast<std::vector<uint8_t> *>(data);
};
@@ -489,22 +662,26 @@ namespace thermion
return true;
}
EMSCRIPTEN_KEEPALIVE uint32_t Texture_getWidth(TTexture *tTexture, uint32_t level) {
auto *texture = reinterpret_cast<filament::Texture *>(tTexture);
return texture->getWidth();
EMSCRIPTEN_KEEPALIVE uint32_t Texture_getWidth(TTexture *tTexture, uint32_t level)
{
auto *texture = reinterpret_cast<filament::Texture *>(tTexture);
return texture->getWidth();
}
EMSCRIPTEN_KEEPALIVE uint32_t Texture_getHeight(TTexture *tTexture, uint32_t level) {
EMSCRIPTEN_KEEPALIVE uint32_t Texture_getHeight(TTexture *tTexture, uint32_t level)
{
auto *texture = reinterpret_cast<filament::Texture *>(tTexture);
return texture->getHeight();
}
EMSCRIPTEN_KEEPALIVE uint32_t Texture_getDepth(TTexture *tTexture, uint32_t level) {
EMSCRIPTEN_KEEPALIVE uint32_t Texture_getDepth(TTexture *tTexture, uint32_t level)
{
auto *texture = reinterpret_cast<filament::Texture *>(tTexture);
return texture->getDepth();
}
EMSCRIPTEN_KEEPALIVE void Texture_generateMipMaps(TTexture *tTexture, TEngine *tEngine) {
EMSCRIPTEN_KEEPALIVE void Texture_generateMipMaps(TTexture *tTexture, TEngine *tEngine)
{
auto *texture = reinterpret_cast<filament::Texture *>(tTexture);
auto *engine = reinterpret_cast<filament::Engine *>(tEngine);
texture->generateMipmaps(*engine);
@@ -545,15 +722,19 @@ namespace thermion
TSamplerCompareFunc compareFunc)
{
if(compareMode == COMPARE_MODE_NONE) {
if (compareMode == COMPARE_MODE_NONE)
{
TRACE("COMPARE MODE NONE");
} else if(compareMode == COMPARE_MODE_COMPARE_TO_TEXTURE) {
}
else if (compareMode == COMPARE_MODE_COMPARE_TO_TEXTURE)
{
TRACE("COMPARE MODE COMPARE TO TEXTURE");
} else {
}
else
{
TRACE("UNKNWON COMPARE MODE");
}
filament::TextureSampler::CompareMode mode = static_cast<filament::TextureSampler::CompareMode>(static_cast<int>(compareMode));
filament::TextureSampler::CompareFunc func = static_cast<filament::TextureSampler::CompareFunc>(static_cast<int>(compareFunc));