diff --git a/thermion_dart/lib/src/bindings/src/thermion_dart_ffi.g.dart b/thermion_dart/lib/src/bindings/src/thermion_dart_ffi.g.dart index 027f09db..cde3c2ec 100644 --- a/thermion_dart/lib/src/bindings/src/thermion_dart_ffi.g.dart +++ b/thermion_dart/lib/src/bindings/src/thermion_dart_ffi.g.dart @@ -729,6 +729,23 @@ external void Texture_generateMipMaps( ffi.Pointer tEngine, ); +@ffi.Native< + ffi.Pointer Function( + ffi.Pointer, + ffi.Pointer, + ffi.Size, + ffi.Pointer, + ffi.Uint32, + VoidCallback)>(isLeaf: true) +external ffi.Pointer Texture_decodeKtx( + ffi.Pointer tEngine, + ffi.Pointer ktxData, + int length, + ffi.Pointer sphericalHarmonics, + int requestId, + VoidCallback onTextureUploadComplete, +); + @ffi.Native< ffi.Pointer Function( ffi.Uint32, ffi.Uint32, ffi.Uint32)>(isLeaf: true) @@ -1558,30 +1575,20 @@ external ffi.Pointer Engine_createScene( @ffi.Native< ffi.Pointer Function( - ffi.Pointer, - ffi.Pointer, - ffi.Size, - ffi.Pointer>)>(isLeaf: true) + ffi.Pointer, ffi.Pointer)>(isLeaf: true) external ffi.Pointer Engine_buildSkybox( ffi.Pointer tEngine, - ffi.Pointer ktxData, - int length, - ffi.Pointer> onTextureUploadComplete, + ffi.Pointer tTexture, ); @ffi.Native< - ffi.Pointer Function( - ffi.Pointer, - ffi.Pointer, - ffi.Size, - ffi.Float, - ffi.Pointer>)>(isLeaf: true) + ffi.Pointer Function(ffi.Pointer, + ffi.Pointer, ffi.Float, ffi.Pointer)>(isLeaf: true) external ffi.Pointer Engine_buildIndirectLight( ffi.Pointer tEngine, - ffi.Pointer ktxData, - int length, + ffi.Pointer tTexture, double intensity, - ffi.Pointer> onTextureUploadComplete, + ffi.Pointer harmonics, ); @ffi.Native, ffi.Pointer)>( @@ -1887,6 +1894,28 @@ external void Texture_generateMipMapsRenderThread( VoidCallback onComplete, ); +@ffi.Native< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Size, + ffi.Pointer, + ffi.Uint32, + VoidCallback, + ffi.Pointer< + ffi.NativeFunction)>>)>( + isLeaf: true) +external void Texture_decodeKtxRenderThread( + ffi.Pointer tEngine, + ffi.Pointer ktxData, + int length, + ffi.Pointer sphericalHarmonics, + int requestId, + VoidCallback onTextureUploadComplete, + ffi.Pointer)>> + onComplete, +); + @ffi.Native< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Uint32, VoidCallback)>(isLeaf: true) @@ -1936,40 +1965,36 @@ external void Engine_executeRenderThread( ); @ffi.Native< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Size, - ffi.Pointer< - ffi.NativeFunction)>>, - ffi.Pointer>)>(isLeaf: true) + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer< + ffi.NativeFunction)>>)>( + isLeaf: true) external void Engine_buildSkyboxRenderThread( ffi.Pointer tEngine, - ffi.Pointer skyboxData, - int length, + ffi.Pointer tTexture, ffi.Pointer)>> onComplete, - ffi.Pointer> onTextureUploadComplete, ); @ffi.Native< ffi.Void Function( ffi.Pointer, - ffi.Pointer, - ffi.Size, + ffi.Pointer, ffi.Float, + ffi.Pointer, ffi.Pointer< - ffi.NativeFunction)>>, - ffi.Pointer>)>(isLeaf: true) + ffi.NativeFunction< + ffi.Void Function(ffi.Pointer)>>)>(isLeaf: true) external void Engine_buildIndirectLightRenderThread( ffi.Pointer tEngine, - ffi.Pointer iblData, - int length, + ffi.Pointer tTexture, double intensity, + ffi.Pointer harmonics, ffi.Pointer< ffi.NativeFunction)>> onComplete, - ffi.Pointer> onTextureUploadComplete, ); @ffi.Native< @@ -3045,6 +3070,13 @@ external void RenderableManager_setPriority( int priority, ); +@ffi.Native, EntityId)>( + isLeaf: true) +external Aabb3 RenderableManager_getBoundingBox( + ffi.Pointer tRenderableManager, + int entityId, +); + @ffi.Native< ffi.Pointer Function( ffi.Pointer, @@ -3462,6 +3494,9 @@ external bool AnimationManager_setGltfAnimationFrame( int frame, ); +typedef VoidCallbackFunction = ffi.Void Function(ffi.Int32 requestId); +typedef DartVoidCallbackFunction = void Function(int requestId); +typedef VoidCallback = ffi.Pointer>; typedef EntityId = ffi.Int32; typedef DartEntityId = int; @@ -4094,9 +4129,6 @@ sealed class TBackend { static const BACKEND_NOOP = 4; } -typedef VoidCallbackFunction = ffi.Void Function(ffi.Int32 requestId); -typedef DartVoidCallbackFunction = void Function(int requestId); -typedef VoidCallback = ffi.Pointer>; typedef FilamentRenderCallbackFunction = ffi.Void Function( ffi.Pointer owner); typedef DartFilamentRenderCallbackFunction = void Function( diff --git a/thermion_dart/lib/src/viewer/src/ffi/src/thermion_viewer_ffi.dart b/thermion_dart/lib/src/viewer/src/ffi/src/thermion_viewer_ffi.dart index 67d0671c..bc05bec1 100644 --- a/thermion_dart/lib/src/viewer/src/ffi/src/thermion_viewer_ffi.dart +++ b/thermion_dart/lib/src/viewer/src/ffi/src/thermion_viewer_ffi.dart @@ -1,5 +1,6 @@ import 'dart:async'; import 'package:thermion_dart/src/filament/src/implementation/background_image.dart'; +import 'package:thermion_dart/src/filament/src/implementation/ffi_texture.dart'; import '../../../../filament/src/implementation/ffi_asset.dart'; import 'package:thermion_dart/src/filament/src/implementation/ffi_filament_app.dart'; import '../../../../filament/src/implementation/ffi_scene.dart'; @@ -232,56 +233,83 @@ class ThermionViewerFFI extends ThermionViewer { throw UnimplementedError(); } + Future? _skyboxTextureUploadComplete; + FFITexture? _skyboxTexture; + Pointer? _skybox; + /// /// /// @override Future loadSkybox(String skyboxPath) async { + await removeSkybox(); + var data = await FilamentApp.instance!.loadResource(skyboxPath); - skybox = await withPointerCallback((cb) { - Engine_buildSkyboxRenderThread( - app.engine, - data.address, - data.length, - cb, - nullptr, - ); + final completer = Completer(); + + _skyboxTextureUploadComplete = + withVoidCallback((requestId, onTextureUploadComplete) async { + var skyboxTexturePointer = await withPointerCallback((cb) { + Texture_decodeKtxRenderThread(app.engine, data.address, data.length, + nullptr, requestId, onTextureUploadComplete, cb); + }); + _skyboxTexture = FFITexture(app.engine, skyboxTexturePointer); + + _skybox = await withPointerCallback((cb) { + Engine_buildSkyboxRenderThread(app.engine, _skyboxTexture!.pointer, cb); + }); + Scene_setSkybox(scene.scene, _skybox!); + completer.complete(); + }).then((_) async { + _skyboxTextureUploadComplete = null; }); - Scene_setSkybox(scene.scene, skybox!); + await completer.future; } - Pointer? indirectLight; - - Pointer? skybox; + Pointer? _iblTexture; + Pointer? _indirectLight; + Future? _iblTextureUploadComplete; /// /// /// @override Future loadIbl(String lightingPath, {double intensity = 30000}) async { - late Pointer stackPtr; - if (FILAMENT_WASM) { - //stackPtr = stackSave(); - } - var data = await FilamentApp.instance!.loadResource(lightingPath); + await removeIbl(); - indirectLight = await withPointerCallback((cb) { - Engine_buildIndirectLightRenderThread( - app.engine, - data.address, - data.length, - intensity, - cb, - nullptr, - ); - }); - if (FILAMENT_WASM) { - //stackRestore(stackPtr); + final completer = Completer(); + _iblTextureUploadComplete = + withVoidCallback((requestId, onTextureUploadComplete) async { + late Pointer stackPtr; + if (FILAMENT_WASM) { + //stackPtr = stackSave(); + } + + var data = await FilamentApp.instance!.loadResource(lightingPath); + + var harmonics = Float32List(27); + + _iblTexture = await withPointerCallback((cb) { + Texture_decodeKtxRenderThread(app.engine, data.address, data.length, + harmonics.address, requestId, onTextureUploadComplete, cb); + }); + + _indirectLight = await withPointerCallback((cb) { + Engine_buildIndirectLightRenderThread( + app.engine, _iblTexture!, intensity, harmonics.address, cb); + }); + if (FILAMENT_WASM) { + //stackRestore(stackPtr); + data.free(); + } data.free(); - } - data.free(); - Scene_setIndirectLight(scene.scene, indirectLight!); + Scene_setIndirectLight(scene.scene, _indirectLight!); + completer.complete(); + }).then((_) { + _iblTextureUploadComplete = null; + }); + await completer.future; } /// @@ -289,7 +317,7 @@ class ThermionViewerFFI extends ThermionViewer { /// @override Future rotateIbl(Matrix3 rotationMatrix) async { - if (indirectLight == null) { + if (_indirectLight == null) { throw Exception("No IBL loaded"); } @@ -298,7 +326,7 @@ class ThermionViewerFFI extends ThermionViewer { //stackPtr = stackSave(); } - IndirectLight_setRotation(indirectLight!, rotationMatrix.storage.address); + IndirectLight_setRotation(_indirectLight!, rotationMatrix.storage.address); if (FILAMENT_WASM) { //stackRestore(stackPtr); @@ -315,17 +343,23 @@ class ThermionViewerFFI extends ThermionViewer { throw ViewerDisposedException(); } - if (skybox != null) { + if (_skyboxTextureUploadComplete != null) { + await _skyboxTextureUploadComplete; + _skyboxTextureUploadComplete = null; + } + + if (_skybox != null) { await withVoidCallback( (requestId, cb) => Engine_destroySkyboxRenderThread( app.engine, - skybox!, + _skybox!, requestId, cb, ), ); - skybox = null; } + _skybox = null; + _skyboxTexture = null; } /// @@ -333,17 +367,22 @@ class ThermionViewerFFI extends ThermionViewer { /// @override Future removeIbl() async { - if (indirectLight != null) { + if (_iblTextureUploadComplete != null) { + await _iblTextureUploadComplete!; + _iblTextureUploadComplete = null; + } + if (_indirectLight != null) { Scene_setIndirectLight(scene.scene, nullptr); await withVoidCallback( (requestId, cb) => Engine_destroyIndirectLightRenderThread( app.engine, - indirectLight!, + _indirectLight!, requestId, cb, ), ); - indirectLight = null; + _indirectLight = null; + _iblTexture = null; } } diff --git a/thermion_dart/native/include/c_api/TEngine.h b/thermion_dart/native/include/c_api/TEngine.h index 1d8fbfd8..6da0a1fd 100644 --- a/thermion_dart/native/include/c_api/TEngine.h +++ b/thermion_dart/native/include/c_api/TEngine.h @@ -57,8 +57,8 @@ EMSCRIPTEN_KEEPALIVE TMaterial *Engine_buildMaterial(TEngine *tEngine, const uin EMSCRIPTEN_KEEPALIVE void Engine_destroyMaterial(TEngine *tEngine, TMaterial *tMaterial); EMSCRIPTEN_KEEPALIVE void Engine_destroyMaterialInstance(TEngine *tEngine, TMaterialInstance *tMaterialInstance); EMSCRIPTEN_KEEPALIVE TScene *Engine_createScene(TEngine *tEngine); -EMSCRIPTEN_KEEPALIVE TSkybox *Engine_buildSkybox(TEngine *tEngine, uint8_t* ktxData, size_t length, void(*onTextureUploadComplete)()); -EMSCRIPTEN_KEEPALIVE TIndirectLight *Engine_buildIndirectLight(TEngine *tEngine, uint8_t* ktxData, size_t length, float intensity, void(*onTextureUploadComplete)()); +EMSCRIPTEN_KEEPALIVE TSkybox *Engine_buildSkybox(TEngine *tEngine, TTexture* tTexture); +EMSCRIPTEN_KEEPALIVE TIndirectLight *Engine_buildIndirectLight(TEngine *tEngine, TTexture* tTexture, float intensity, float *harmonics); EMSCRIPTEN_KEEPALIVE void Engine_destroySkybox(TEngine *tEngine, TSkybox *tSkybox); EMSCRIPTEN_KEEPALIVE void Engine_destroyIndirectLight(TEngine *tEngine, TIndirectLight *tIndirectLight); EMSCRIPTEN_KEEPALIVE EntityId EntityManager_createEntity(TEntityManager *tEntityManager); diff --git a/thermion_dart/native/include/c_api/TTexture.h b/thermion_dart/native/include/c_api/TTexture.h index 360d3beb..2e708fe2 100644 --- a/thermion_dart/native/include/c_api/TTexture.h +++ b/thermion_dart/native/include/c_api/TTexture.h @@ -260,7 +260,14 @@ EMSCRIPTEN_KEEPALIVE uint32_t Texture_getHeight(TTexture *tTexture, uint32_t lev EMSCRIPTEN_KEEPALIVE uint32_t Texture_getDepth(TTexture *tTexture, uint32_t level); EMSCRIPTEN_KEEPALIVE TTextureUsage Texture_getUsage(TTexture *tTexture, uint32_t level); EMSCRIPTEN_KEEPALIVE void Texture_generateMipMaps(TTexture *tTexture, TEngine *tEngine); - +EMSCRIPTEN_KEEPALIVE TTexture* Texture_decodeKtx( + TEngine *tEngine, + uint8_t *ktxData, + size_t length, + float *sphericalHarmonics, + uint32_t requestId, + VoidCallback onTextureUploadComplete +); EMSCRIPTEN_KEEPALIVE TLinearImage *Image_createEmpty(uint32_t width,uint32_t height,uint32_t channel); EMSCRIPTEN_KEEPALIVE TLinearImage *Image_decode(uint8_t* data, size_t length, const char* name, bool alpha); EMSCRIPTEN_KEEPALIVE float *Image_getBytes(TLinearImage *tLinearImage); diff --git a/thermion_dart/native/include/c_api/ThermionDartRenderThreadApi.h b/thermion_dart/native/include/c_api/ThermionDartRenderThreadApi.h index 872f27d6..fd246315 100644 --- a/thermion_dart/native/include/c_api/ThermionDartRenderThreadApi.h +++ b/thermion_dart/native/include/c_api/ThermionDartRenderThreadApi.h @@ -1,5 +1,7 @@ #pragma once +#include "APIBoundaryTypes.h" + #include "TEngine.h" #include "TView.h" #include "TTexture.h" @@ -11,7 +13,6 @@ namespace thermion extern "C" { #endif - typedef void (*VoidCallback)(int32_t requestId); typedef int32_t EntityId; typedef void (*FilamentRenderCallback)(void *const owner); @@ -59,14 +60,15 @@ namespace thermion void (*onComplete)(TTexture*) ); void Texture_generateMipMapsRenderThread(TTexture *tTexture, TEngine *tEngine, uint32_t requestId, VoidCallback onComplete); + void Texture_decodeKtxRenderThread(TEngine *tEngine, uint8_t *ktxData, size_t length, float *sphericalHarmonics, uint32_t requestId, VoidCallback onTextureUploadComplete, void (*onComplete)(TTexture *)); void Engine_destroyTextureRenderThread(TEngine *engine, TTexture* tTexture, uint32_t requestId, VoidCallback onComplete); void Engine_createFenceRenderThread(TEngine *tEngine, void (*onComplete)(TFence*)); void Engine_destroyFenceRenderThread(TEngine *tEngine, TFence *tFence, uint32_t requestId, VoidCallback onComplete); void Engine_flushAndWaitRenderThread(TEngine *tEngine, uint32_t requestId, VoidCallback onComplete); void Engine_executeRenderThread(TEngine *tEngine, uint32_t requestId, VoidCallback onComplete); - void Engine_buildSkyboxRenderThread(TEngine *tEngine, uint8_t *skyboxData, size_t length, void (*onComplete)(TSkybox *), void (*onTextureUploadComplete)()); - void Engine_buildIndirectLightRenderThread(TEngine *tEngine, uint8_t *iblData, size_t length, float intensity, void (*onComplete)(TIndirectLight *), void (*onTextureUploadComplete)()); + void Engine_buildSkyboxRenderThread(TEngine *tEngine, TTexture *tTexture, void (*onComplete)(TSkybox *)); + void Engine_buildIndirectLightRenderThread(TEngine *tEngine, TTexture *tTexture, float intensity, float *harmonics, void (*onComplete)(TIndirectLight *)); void Renderer_setClearOptionsRenderThread(TRenderer *tRenderer, double clearR, double clearG, double clearB, double clearA, uint8_t clearStencil, bool clear, bool discard, uint32_t requestId, VoidCallback onComplete); void Renderer_beginFrameRenderThread(TRenderer *tRenderer, TSwapChain *tSwapChain, uint64_t frameTimeInNanos, void (*onComplete)(bool)); diff --git a/thermion_dart/native/src/c_api/TEngine.cpp b/thermion_dart/native/src/c_api/TEngine.cpp index e8bc00e5..fb22b303 100644 --- a/thermion_dart/native/src/c_api/TEngine.cpp +++ b/thermion_dart/native/src/c_api/TEngine.cpp @@ -303,40 +303,11 @@ namespace thermion return reinterpret_cast(scene); } - EMSCRIPTEN_KEEPALIVE TSkybox *Engine_buildSkybox(TEngine *tEngine, uint8_t *ktxData, size_t length, void (*onTextureUploadComplete)()) + EMSCRIPTEN_KEEPALIVE TSkybox *Engine_buildSkybox(TEngine *tEngine, TTexture *tTexture) { auto *engine = reinterpret_cast(tEngine); - auto copy = new std::vector(ktxData, ktxData + length); - image::Ktx1Bundle *skyboxBundle = - new image::Ktx1Bundle(static_cast(copy->data()), - static_cast(length)); - - std::vector *callbackData = new std::vector{ - reinterpret_cast(onTextureUploadComplete), - reinterpret_cast(skyboxBundle), - reinterpret_cast(copy)}; - - auto *texture = - ktxreader::Ktx1Reader::createTexture( - engine, *skyboxBundle, false, [](void *userdata) - { - std::vector* vec = (std::vector*)userdata; - - void *callbackPtr = vec->at(0); - image::Ktx1Bundle *skyboxBundle = reinterpret_cast(vec->at(1)); - std::vector *copy = reinterpret_cast*>(vec->at(2)); - - delete vec; - - if (callbackPtr) - { - void (*callback)(void) = (void (*)(void))callbackPtr; - callback(); - } - delete skyboxBundle; - delete copy; - }, - (void *)callbackData); + auto *texture = reinterpret_cast(tTexture); + auto *skybox = filament::Skybox::Builder() .environment(texture) @@ -345,48 +316,17 @@ namespace thermion return reinterpret_cast(skybox); } - EMSCRIPTEN_KEEPALIVE TIndirectLight *Engine_buildIndirectLight(TEngine *tEngine, uint8_t *ktxData, size_t length, float intensity, void (*onTextureUploadComplete)()) + EMSCRIPTEN_KEEPALIVE TIndirectLight *Engine_buildIndirectLight(TEngine *tEngine, TTexture *tTexture, float intensity, float *harmonics) { auto *engine = reinterpret_cast(tEngine); - auto copy = new std::vector(ktxData, ktxData + length); + auto *texture = reinterpret_cast(tTexture); - image::Ktx1Bundle *iblBundle = - new image::Ktx1Bundle(static_cast(copy->data()), - static_cast(length)); - filament::math::float3 harmonics[9]; - iblBundle->getSphericalHarmonics(harmonics); + filament::math::float3 sphericalHarmonics[9]; + memcpy(sphericalHarmonics, harmonics, 27 * sizeof(float)); - - std::vector *callbackData = new std::vector{ - reinterpret_cast(onTextureUploadComplete), - reinterpret_cast(iblBundle), - reinterpret_cast(copy)}; - - auto *texture = - ktxreader::Ktx1Reader::createTexture( - engine, *iblBundle, false, [](void *userdata) - { - std::vector* vec = (std::vector*)userdata; - - void *callbackPtr = vec->at(0); - image::Ktx1Bundle *iblBundle = reinterpret_cast(vec->at(1)); - std::vector *copy = reinterpret_cast*>(vec->at(2)); - - delete vec; - - if (callbackPtr) - { - void (*callback)(void) = (void (*)(void))callbackPtr; - callback(); - } - delete iblBundle; - delete copy; - }, - - (void *)callbackData); auto *indirectLight = filament::IndirectLight::Builder() .reflections(texture) - .irradiance(3, harmonics) + .irradiance(3, sphericalHarmonics) .intensity(intensity) .build(*engine); return reinterpret_cast(indirectLight); diff --git a/thermion_dart/native/src/c_api/TTexture.cpp b/thermion_dart/native/src/c_api/TTexture.cpp index cdb0431f..e8a7e28f 100644 --- a/thermion_dart/native/src/c_api/TTexture.cpp +++ b/thermion_dart/native/src/c_api/TTexture.cpp @@ -1,6 +1,6 @@ #ifdef __EMSCRIPTEN__ #include -#endif +#endif #include @@ -17,6 +17,9 @@ #include #include +#include +#include + #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( - width, - height, - width * 4, - imgData, - to_float, sRGBToLinear)); - } else { - linearImage = new LinearImage(toLinear( - width, - height, - width * 3, - imgData, - to_float, sRGBToLinear)); - } - - auto end = std::chrono::high_resolution_clock::now(); - auto duration = std::chrono::duration_cast(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( + width, + height, + width * 4, + imgData, + to_float, sRGBToLinear)); + } + else + { + linearImage = new LinearImage(toLinear( + width, + height, + width * 3, + imgData, + to_float, sRGBToLinear)); + } + + auto end = std::chrono::high_resolution_clock::now(); + auto duration = std::chrono::duration_cast(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(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(tEngine); + + auto copy = new std::vector(ktxData, ktxData + length); + image::Ktx1Bundle *bundle = + new image::Ktx1Bundle(static_cast(copy->data()), + static_cast(length)); + + filament::math::float3 harmonics[9]; + if (sphericalHarmonics) + { + bundle->getSphericalHarmonics(harmonics); + memcpy(sphericalHarmonics, harmonics, 27 * sizeof(float)); + } + + std::vector *callbackData = new std::vector{ + reinterpret_cast(onTextureUploadComplete), + reinterpret_cast(bundle), + reinterpret_cast(copy), + reinterpret_cast(requestId)}; + + auto *texture = + ktxreader::Ktx1Reader::createTexture( + engine, *bundle, false, [](void *userdata) + { + std::vector* vec = (std::vector*)userdata; + + void *callbackPtr = vec->at(0); + image::Ktx1Bundle *bundle = reinterpret_cast(vec->at(1)); + std::vector *copy = reinterpret_cast*>(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(texture); } - - return reinterpret_cast(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(tSamplerType), static_cast(tFormat), tUsage, levels); auto *engine = reinterpret_cast<::filament::Engine *>(tEngine); auto format = convertToFilamentFormat(tFormat); auto samplerType = static_cast<::filament::Texture::Sampler>(static_cast(tSamplerType)); auto usage = static_cast(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(texture); } - EMSCRIPTEN_KEEPALIVE size_t Texture_getLevels(TTexture *tTexture) { + EMSCRIPTEN_KEEPALIVE size_t Texture_getLevels(TTexture *tTexture) + { auto texture = reinterpret_cast(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 *>(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 *>(data); }; @@ -489,22 +662,26 @@ namespace thermion return true; } - EMSCRIPTEN_KEEPALIVE uint32_t Texture_getWidth(TTexture *tTexture, uint32_t level) { - auto *texture = reinterpret_cast(tTexture); - return texture->getWidth(); + EMSCRIPTEN_KEEPALIVE uint32_t Texture_getWidth(TTexture *tTexture, uint32_t level) + { + auto *texture = reinterpret_cast(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(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(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(tTexture); auto *engine = reinterpret_cast(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(static_cast(compareMode)); filament::TextureSampler::CompareFunc func = static_cast(static_cast(compareFunc)); diff --git a/thermion_dart/native/src/c_api/ThermionDartRenderThreadApi.cpp b/thermion_dart/native/src/c_api/ThermionDartRenderThreadApi.cpp index 086b112d..7a9a9ffd 100644 --- a/thermion_dart/native/src/c_api/ThermionDartRenderThreadApi.cpp +++ b/thermion_dart/native/src/c_api/ThermionDartRenderThreadApi.cpp @@ -350,23 +350,23 @@ extern "C" #endif } - EMSCRIPTEN_KEEPALIVE void Engine_buildSkyboxRenderThread(TEngine *tEngine, uint8_t *skyboxData, size_t length, void (*onComplete)(TSkybox *), void (*onTextureUploadComplete)()) + EMSCRIPTEN_KEEPALIVE void Engine_buildSkyboxRenderThread(TEngine *tEngine, TTexture *tTexture, void (*onComplete)(TSkybox *)) { std::packaged_task lambda( [=]() mutable { - auto *skybox = Engine_buildSkybox(tEngine, skyboxData, length, onTextureUploadComplete); + auto *skybox = Engine_buildSkybox(tEngine, tTexture); PROXY(onComplete(skybox)); }); auto fut = _renderThread->add_task(lambda); } - EMSCRIPTEN_KEEPALIVE void Engine_buildIndirectLightRenderThread(TEngine *tEngine, uint8_t *iblData, size_t length, float intensity, void (*onComplete)(TIndirectLight *), void (*onTextureUploadComplete)()) + EMSCRIPTEN_KEEPALIVE void Engine_buildIndirectLightRenderThread(TEngine *tEngine, TTexture *tTexture, float intensity, float *harmonics, void (*onComplete)(TIndirectLight *)) { std::packaged_task lambda( [=]() mutable { - auto *indirectLight = Engine_buildIndirectLight(tEngine, iblData, length, intensity, onTextureUploadComplete); + auto *indirectLight = Engine_buildIndirectLight(tEngine, tTexture, intensity, harmonics); PROXY(onComplete(indirectLight)); }); auto fut = _renderThread->add_task(lambda); @@ -861,6 +861,18 @@ extern "C" auto fut = _renderThread->add_task(lambda); } + EMSCRIPTEN_KEEPALIVE void Texture_decodeKtxRenderThread( + TEngine *tEngine, uint8_t *ktxData, size_t length, float *sphericalHarmonics, uint32_t requestId, VoidCallback onTextureUploadComplete, void (*onComplete)(TTexture *)) { + std::packaged_task lambda( + [=]() mutable + { + auto *texture = Texture_decodeKtx(tEngine, ktxData, length, sphericalHarmonics, requestId, onTextureUploadComplete); + PROXY(onComplete(texture)); + }); + auto fut = _renderThread->add_task(lambda); + } + + EMSCRIPTEN_KEEPALIVE void Texture_loadImageRenderThread(TEngine *tEngine, TTexture *tTexture, TLinearImage *tImage, TPixelDataFormat bufferFormat, TPixelDataType pixelDataType, int level,