diff --git a/thermion_dart/lib/src/viewer/src/ffi/src/ffi_texture.dart b/thermion_dart/lib/src/viewer/src/ffi/src/ffi_texture.dart new file mode 100644 index 00000000..746d6ffd --- /dev/null +++ b/thermion_dart/lib/src/viewer/src/ffi/src/ffi_texture.dart @@ -0,0 +1,133 @@ +import 'dart:typed_data'; + +import 'package:thermion_dart/src/viewer/src/ffi/src/callbacks.dart'; +import 'package:thermion_dart/thermion_dart.dart'; + +class FFITexture extends Texture { + final Pointer _engine; + final Pointer pointer; + + FFITexture(this._engine, this.pointer); + + Future setLinearImage(covariant FFILinearImage image, PixelDataFormat format, + PixelDataType type) async { + final result = Texture_loadImage( + _engine, + pointer, + image.pointer, + TPixelDataFormat.values[format.index], + TPixelDataType.values[type.index]); + if (!result) { + throw Exception("Failed to set linear image"); + } + } + + @override + Future dispose() { + // TODO: implement dispose + throw UnimplementedError(); + } + + @override + Future generateMipmaps() { + // TODO: implement generateMipmaps + throw UnimplementedError(); + } + + @override + Future getDepth([int level = 0]) { + // TODO: implement getDepth + throw UnimplementedError(); + } + + @override + Future getFormat() { + // TODO: implement getFormat + throw UnimplementedError(); + } + + @override + Future getHeight([int level = 0]) { + // TODO: implement getHeight + throw UnimplementedError(); + } + + @override + Future getLevels() { + // TODO: implement getLevels + throw UnimplementedError(); + } + + @override + Future getTarget() { + // TODO: implement getTarget + throw UnimplementedError(); + } + + @override + Future getWidth([int level = 0]) { + // TODO: implement getWidth + throw UnimplementedError(); + } + + @override + Future setExternalImage(externalImage) { + // TODO: implement setExternalImage + throw UnimplementedError(); + } + + @override + Future setImage( + int level, Uint8List buffer, PixelDataFormat format, PixelDataType type) { + // TODO: implement setImage + throw UnimplementedError(); + } + + @override + Future setImage3D( + int level, + int xOffset, + int yOffset, + int zOffset, + int width, + int height, + int depth, + Uint8List buffer, + PixelDataFormat format, + PixelDataType type) { + // TODO: implement setImage3D + throw UnimplementedError(); + } + + @override + Future setSubImage(int level, int xOffset, int yOffset, int width, int height, + Uint8List buffer, PixelDataFormat format, PixelDataType type) { + // TODO: implement setSubImage + throw UnimplementedError(); + } +} + +class FFILinearImage extends LinearImage { + final Pointer pointer; + + FFILinearImage(this.pointer); + + Future destroy() async { + Image_destroy(this.pointer); + } + + @override + Future getChannels() async { + return Image_getChannels(pointer); + } + + @override + Future getHeight() async { + return Image_getHeight(pointer); + } + + @override + Future getWidth() async { + return Image_getWidth(pointer); + } +} diff --git a/thermion_dart/lib/src/viewer/src/ffi/src/thermion_dart.g.dart b/thermion_dart/lib/src/viewer/src/ffi/src/thermion_dart.g.dart index d9cb7ee4..dbde8b74 100644 --- a/thermion_dart/lib/src/viewer/src/ffi/src/thermion_dart.g.dart +++ b/thermion_dart/lib/src/viewer/src/ffi/src/thermion_dart.g.dart @@ -95,6 +95,16 @@ external void MaterialInstance_setParameterInt( int value, ); +@ffi.Native< + ffi.Void Function(ffi.Pointer, ffi.Pointer, + ffi.Pointer, ffi.Pointer)>(isLeaf: true) +external void MaterialInstance_setParameterTexture( + ffi.Pointer materialInstance, + ffi.Pointer propertyName, + ffi.Pointer texture, + ffi.Pointer sampler, +); + @ffi.Native, ffi.UnsignedInt)>( symbol: "MaterialInstance_setDepthFunc", isLeaf: true) external void _MaterialInstance_setDepthFunc( @@ -471,53 +481,6 @@ external ffi.Pointer Viewer_getEngine( ffi.Pointer viewer, ); -@ffi.Native Function(ffi.Pointer, EntityId)>( - isLeaf: true) -external ffi.Pointer Engine_getCameraComponent( - ffi.Pointer tEngine, - int entityId, -); - -@ffi.Native Function(ffi.Pointer)>( - isLeaf: true) -external ffi.Pointer Engine_getTransformManager( - ffi.Pointer engine, -); - -@ffi.Native Function(ffi.Pointer)>( - isLeaf: true) -external ffi.Pointer Engine_getRenderableManager( - ffi.Pointer engine, -); - -@ffi.Native Function(ffi.Pointer)>( - isLeaf: true) -external ffi.Pointer Engine_getLightManager( - ffi.Pointer engine, -); - -@ffi.Native Function(ffi.Pointer)>( - isLeaf: true) -external ffi.Pointer Engine_getEntityManager( - ffi.Pointer engine, -); - -@ffi.Native< - ffi.Pointer Function( - ffi.Pointer, ffi.Pointer, ffi.Size)>(isLeaf: true) -external ffi.Pointer Engine_buildMaterial( - ffi.Pointer tEngine, - ffi.Pointer materialData, - int length, -); - -@ffi.Native, ffi.Pointer)>( - isLeaf: true) -external void Engine_destroyMaterial( - ffi.Pointer tEngine, - ffi.Pointer tMaterial, -); - @ffi.Native)>(isLeaf: true) external void clear_background_image( ffi.Pointer viewer, @@ -927,6 +890,65 @@ external ffi.Pointer NameComponentManager_getName( int entity, ); +@ffi.Native< + ffi.Bool Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.UnsignedInt, + ffi.UnsignedInt)>(symbol: "Texture_loadImage", isLeaf: true) +external bool _Texture_loadImage( + ffi.Pointer tEngine, + ffi.Pointer tTexture, + ffi.Pointer tImage, + int bufferFormat, + int pixelDataType, +); + +bool Texture_loadImage( + ffi.Pointer tEngine, + ffi.Pointer tTexture, + ffi.Pointer tImage, + TPixelDataFormat bufferFormat, + TPixelDataType pixelDataType, +) => + _Texture_loadImage( + tEngine, + tTexture, + tImage, + bufferFormat.value, + pixelDataType.value, + ); + +@ffi.Native< + ffi.Pointer Function( + ffi.Pointer, ffi.Size, ffi.Pointer)>(isLeaf: true) +external ffi.Pointer Image_decode( + ffi.Pointer data, + int length, + ffi.Pointer name, +); + +@ffi.Native)>(isLeaf: true) +external void Image_destroy( + ffi.Pointer tLinearImage, +); + +@ffi.Native)>(isLeaf: true) +external int Image_getWidth( + ffi.Pointer tLinearImage, +); + +@ffi.Native)>(isLeaf: true) +external int Image_getHeight( + ffi.Pointer tLinearImage, +); + +@ffi.Native)>(isLeaf: true) +external int Image_getChannels( + ffi.Pointer tLinearImage, +); + @ffi.Native< ffi.Void Function(ffi.Pointer, ffi.Uint32, ffi.Uint32, GizmoPickCallback)>(isLeaf: true) @@ -1428,6 +1450,48 @@ external void Engine_destroyMaterialRenderThread( ffi.Pointer> onComplete, ); +@ffi.Native< + ffi.Void Function( + ffi.Pointer, + ffi.Uint32, + ffi.Uint32, + ffi.Uint8, + ffi.UnsignedInt, + ffi.UnsignedInt, + ffi.Pointer< + ffi.NativeFunction)>>)>( + symbol: "Engine_buildTextureRenderThread", isLeaf: true) +external void _Engine_buildTextureRenderThread( + ffi.Pointer engine, + int width, + int height, + int levels, + int sampler, + int format, + ffi.Pointer)>> + onComplete, +); + +void Engine_buildTextureRenderThread( + ffi.Pointer engine, + int width, + int height, + int levels, + TTextureSamplerType sampler, + TTextureFormat format, + ffi.Pointer)>> + onComplete, +) => + _Engine_buildTextureRenderThread( + engine, + width, + height, + levels, + sampler.value, + format.value, + onComplete, + ); + @ffi.Native< ffi.Void Function( ffi.Pointer, @@ -2344,6 +2408,87 @@ external bool RenderableManager_getFogEnabled( int entityId, ); +@ffi.Native Function(ffi.Pointer, EntityId)>( + isLeaf: true) +external ffi.Pointer Engine_getCameraComponent( + ffi.Pointer tEngine, + int entityId, +); + +@ffi.Native Function(ffi.Pointer)>( + isLeaf: true) +external ffi.Pointer Engine_getTransformManager( + ffi.Pointer engine, +); + +@ffi.Native Function(ffi.Pointer)>( + isLeaf: true) +external ffi.Pointer Engine_getRenderableManager( + ffi.Pointer engine, +); + +@ffi.Native Function(ffi.Pointer)>( + isLeaf: true) +external ffi.Pointer Engine_getLightManager( + ffi.Pointer engine, +); + +@ffi.Native Function(ffi.Pointer)>( + isLeaf: true) +external ffi.Pointer Engine_getEntityManager( + ffi.Pointer engine, +); + +@ffi.Native< + ffi.Pointer Function( + ffi.Pointer, + ffi.Uint32, + ffi.Uint32, + ffi.Uint8, + ffi.UnsignedInt, + ffi.UnsignedInt)>(symbol: "Engine_buildTexture", isLeaf: true) +external ffi.Pointer _Engine_buildTexture( + ffi.Pointer engine, + int width, + int height, + int levels, + int sampler, + int format, +); + +ffi.Pointer Engine_buildTexture( + ffi.Pointer engine, + int width, + int height, + int levels, + TTextureSamplerType sampler, + TTextureFormat format, +) => + _Engine_buildTexture( + engine, + width, + height, + levels, + sampler.value, + format.value, + ); + +@ffi.Native< + ffi.Pointer Function( + ffi.Pointer, ffi.Pointer, ffi.Size)>(isLeaf: true) +external ffi.Pointer Engine_buildMaterial( + ffi.Pointer tEngine, + ffi.Pointer materialData, + int length, +); + +@ffi.Native, ffi.Pointer)>( + isLeaf: true) +external void Engine_destroyMaterial( + ffi.Pointer tEngine, + ffi.Pointer tMaterial, +); + @ffi.Native, ffi.Pointer)>( isLeaf: true) external void SceneAsset_addToScene( @@ -2688,6 +2833,12 @@ final class TRenderableManager extends ffi.Opaque {} final class TRenderableInstance extends ffi.Opaque {} +final class TTexture extends ffi.Opaque {} + +final class TTextureSampler extends ffi.Opaque {} + +final class TLinearImage extends ffi.Opaque {} + final class TMaterialKey extends ffi.Struct { @ffi.Bool() external bool doubleSided; @@ -3085,6 +3236,366 @@ typedef DartPickCallbackFunction = void Function( double fragY, double fragZ); +enum TTextureSamplerType { + SAMPLER_2D(0), + SAMPLER_CUBEMAP(1), + SAMPLER_EXTERNAL(2), + SAMPLER_3D(3), + SAMPLER_2D_ARRAY(4); + + final int value; + const TTextureSamplerType(this.value); + + static TTextureSamplerType fromValue(int value) => switch (value) { + 0 => SAMPLER_2D, + 1 => SAMPLER_CUBEMAP, + 2 => SAMPLER_EXTERNAL, + 3 => SAMPLER_3D, + 4 => SAMPLER_2D_ARRAY, + _ => + throw ArgumentError("Unknown value for TTextureSamplerType: $value"), + }; +} + +enum TTextureFormat { + TEXTUREFORMAT_R8(0), + TEXTUREFORMAT_R8_SNORM(1), + TEXTUREFORMAT_R8UI(2), + TEXTUREFORMAT_R8I(3), + TEXTUREFORMAT_STENCIL8(4), + TEXTUREFORMAT_R16F(5), + TEXTUREFORMAT_R16UI(6), + TEXTUREFORMAT_R16I(7), + TEXTUREFORMAT_RG8(8), + TEXTUREFORMAT_RG8_SNORM(9), + TEXTUREFORMAT_RG8UI(10), + TEXTUREFORMAT_RG8I(11), + TEXTUREFORMAT_RGB565(12), + TEXTUREFORMAT_RGB9_E5(13), + TEXTUREFORMAT_RGB5_A1(14), + TEXTUREFORMAT_RGBA4(15), + TEXTUREFORMAT_DEPTH16(16), + TEXTUREFORMAT_RGB8(17), + TEXTUREFORMAT_SRGB8(18), + TEXTUREFORMAT_RGB8_SNORM(19), + TEXTUREFORMAT_RGB8UI(20), + TEXTUREFORMAT_RGB8I(21), + TEXTUREFORMAT_DEPTH24(22), + TEXTUREFORMAT_R32F(23), + TEXTUREFORMAT_R32UI(24), + TEXTUREFORMAT_R32I(25), + TEXTUREFORMAT_RG16F(26), + TEXTUREFORMAT_RG16UI(27), + TEXTUREFORMAT_RG16I(28), + TEXTUREFORMAT_R11F_G11F_B10F(29), + TEXTUREFORMAT_RGBA8(30), + TEXTUREFORMAT_SRGB8_A8(31), + TEXTUREFORMAT_RGBA8_SNORM(32), + TEXTUREFORMAT_UNUSED(33), + TEXTUREFORMAT_RGB10_A2(34), + TEXTUREFORMAT_RGBA8UI(35), + TEXTUREFORMAT_RGBA8I(36), + TEXTUREFORMAT_DEPTH32F(37), + TEXTUREFORMAT_DEPTH24_STENCIL8(38), + TEXTUREFORMAT_DEPTH32F_STENCIL8(39), + TEXTUREFORMAT_RGB16F(40), + TEXTUREFORMAT_RGB16UI(41), + TEXTUREFORMAT_RGB16I(42), + TEXTUREFORMAT_RG32F(43), + TEXTUREFORMAT_RG32UI(44), + TEXTUREFORMAT_RG32I(45), + TEXTUREFORMAT_RGBA16F(46), + TEXTUREFORMAT_RGBA16UI(47), + TEXTUREFORMAT_RGBA16I(48), + TEXTUREFORMAT_RGB32F(49), + TEXTUREFORMAT_RGB32UI(50), + TEXTUREFORMAT_RGB32I(51), + TEXTUREFORMAT_RGBA32F(52), + TEXTUREFORMAT_RGBA32UI(53), + TEXTUREFORMAT_RGBA32I(54), + TEXTUREFORMAT_EAC_R11(55), + TEXTUREFORMAT_EAC_R11_SIGNED(56), + TEXTUREFORMAT_EAC_RG11(57), + TEXTUREFORMAT_EAC_RG11_SIGNED(58), + TEXTUREFORMAT_ETC2_RGB8(59), + TEXTUREFORMAT_ETC2_SRGB8(60), + TEXTUREFORMAT_ETC2_RGB8_A1(61), + TEXTUREFORMAT_ETC2_SRGB8_A1(62), + TEXTUREFORMAT_ETC2_EAC_RGBA8(63), + TEXTUREFORMAT_ETC2_EAC_SRGBA8(64), + TEXTUREFORMAT_DXT1_RGB(65), + TEXTUREFORMAT_DXT1_RGBA(66), + TEXTUREFORMAT_DXT3_RGBA(67), + TEXTUREFORMAT_DXT5_RGBA(68), + TEXTUREFORMAT_DXT1_SRGB(69), + TEXTUREFORMAT_DXT1_SRGBA(70), + TEXTUREFORMAT_DXT3_SRGBA(71), + TEXTUREFORMAT_DXT5_SRGBA(72), + TEXTUREFORMAT_RGBA_ASTC_4x4(73), + TEXTUREFORMAT_RGBA_ASTC_5x4(74), + TEXTUREFORMAT_RGBA_ASTC_5x5(75), + TEXTUREFORMAT_RGBA_ASTC_6x5(76), + TEXTUREFORMAT_RGBA_ASTC_6x6(77), + TEXTUREFORMAT_RGBA_ASTC_8x5(78), + TEXTUREFORMAT_RGBA_ASTC_8x6(79), + TEXTUREFORMAT_RGBA_ASTC_8x8(80), + TEXTUREFORMAT_RGBA_ASTC_10x5(81), + TEXTUREFORMAT_RGBA_ASTC_10x6(82), + TEXTUREFORMAT_RGBA_ASTC_10x8(83), + TEXTUREFORMAT_RGBA_ASTC_10x10(84), + TEXTUREFORMAT_RGBA_ASTC_12x10(85), + TEXTUREFORMAT_RGBA_ASTC_12x12(86), + TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_4x4(87), + TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_5x4(88), + TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_5x5(89), + TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_6x5(90), + TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_6x6(91), + TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_8x5(92), + TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_8x6(93), + TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_8x8(94), + TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_10x5(95), + TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_10x6(96), + TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_10x8(97), + TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_10x10(98), + TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_12x10(99), + TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_12x12(100), + TEXTUREFORMAT_RED_RGTC1(101), + TEXTUREFORMAT_SIGNED_RED_RGTC1(102), + TEXTUREFORMAT_RED_GREEN_RGTC2(103), + TEXTUREFORMAT_SIGNED_RED_GREEN_RGTC2(104), + TEXTUREFORMAT_RGB_BPTC_SIGNED_FLOAT(105), + TEXTUREFORMAT_RGB_BPTC_UNSIGNED_FLOAT(106), + TEXTUREFORMAT_RGBA_BPTC_UNORM(107), + TEXTUREFORMAT_SRGB_ALPHA_BPTC_UNORM(108); + + final int value; + const TTextureFormat(this.value); + + static TTextureFormat fromValue(int value) => switch (value) { + 0 => TEXTUREFORMAT_R8, + 1 => TEXTUREFORMAT_R8_SNORM, + 2 => TEXTUREFORMAT_R8UI, + 3 => TEXTUREFORMAT_R8I, + 4 => TEXTUREFORMAT_STENCIL8, + 5 => TEXTUREFORMAT_R16F, + 6 => TEXTUREFORMAT_R16UI, + 7 => TEXTUREFORMAT_R16I, + 8 => TEXTUREFORMAT_RG8, + 9 => TEXTUREFORMAT_RG8_SNORM, + 10 => TEXTUREFORMAT_RG8UI, + 11 => TEXTUREFORMAT_RG8I, + 12 => TEXTUREFORMAT_RGB565, + 13 => TEXTUREFORMAT_RGB9_E5, + 14 => TEXTUREFORMAT_RGB5_A1, + 15 => TEXTUREFORMAT_RGBA4, + 16 => TEXTUREFORMAT_DEPTH16, + 17 => TEXTUREFORMAT_RGB8, + 18 => TEXTUREFORMAT_SRGB8, + 19 => TEXTUREFORMAT_RGB8_SNORM, + 20 => TEXTUREFORMAT_RGB8UI, + 21 => TEXTUREFORMAT_RGB8I, + 22 => TEXTUREFORMAT_DEPTH24, + 23 => TEXTUREFORMAT_R32F, + 24 => TEXTUREFORMAT_R32UI, + 25 => TEXTUREFORMAT_R32I, + 26 => TEXTUREFORMAT_RG16F, + 27 => TEXTUREFORMAT_RG16UI, + 28 => TEXTUREFORMAT_RG16I, + 29 => TEXTUREFORMAT_R11F_G11F_B10F, + 30 => TEXTUREFORMAT_RGBA8, + 31 => TEXTUREFORMAT_SRGB8_A8, + 32 => TEXTUREFORMAT_RGBA8_SNORM, + 33 => TEXTUREFORMAT_UNUSED, + 34 => TEXTUREFORMAT_RGB10_A2, + 35 => TEXTUREFORMAT_RGBA8UI, + 36 => TEXTUREFORMAT_RGBA8I, + 37 => TEXTUREFORMAT_DEPTH32F, + 38 => TEXTUREFORMAT_DEPTH24_STENCIL8, + 39 => TEXTUREFORMAT_DEPTH32F_STENCIL8, + 40 => TEXTUREFORMAT_RGB16F, + 41 => TEXTUREFORMAT_RGB16UI, + 42 => TEXTUREFORMAT_RGB16I, + 43 => TEXTUREFORMAT_RG32F, + 44 => TEXTUREFORMAT_RG32UI, + 45 => TEXTUREFORMAT_RG32I, + 46 => TEXTUREFORMAT_RGBA16F, + 47 => TEXTUREFORMAT_RGBA16UI, + 48 => TEXTUREFORMAT_RGBA16I, + 49 => TEXTUREFORMAT_RGB32F, + 50 => TEXTUREFORMAT_RGB32UI, + 51 => TEXTUREFORMAT_RGB32I, + 52 => TEXTUREFORMAT_RGBA32F, + 53 => TEXTUREFORMAT_RGBA32UI, + 54 => TEXTUREFORMAT_RGBA32I, + 55 => TEXTUREFORMAT_EAC_R11, + 56 => TEXTUREFORMAT_EAC_R11_SIGNED, + 57 => TEXTUREFORMAT_EAC_RG11, + 58 => TEXTUREFORMAT_EAC_RG11_SIGNED, + 59 => TEXTUREFORMAT_ETC2_RGB8, + 60 => TEXTUREFORMAT_ETC2_SRGB8, + 61 => TEXTUREFORMAT_ETC2_RGB8_A1, + 62 => TEXTUREFORMAT_ETC2_SRGB8_A1, + 63 => TEXTUREFORMAT_ETC2_EAC_RGBA8, + 64 => TEXTUREFORMAT_ETC2_EAC_SRGBA8, + 65 => TEXTUREFORMAT_DXT1_RGB, + 66 => TEXTUREFORMAT_DXT1_RGBA, + 67 => TEXTUREFORMAT_DXT3_RGBA, + 68 => TEXTUREFORMAT_DXT5_RGBA, + 69 => TEXTUREFORMAT_DXT1_SRGB, + 70 => TEXTUREFORMAT_DXT1_SRGBA, + 71 => TEXTUREFORMAT_DXT3_SRGBA, + 72 => TEXTUREFORMAT_DXT5_SRGBA, + 73 => TEXTUREFORMAT_RGBA_ASTC_4x4, + 74 => TEXTUREFORMAT_RGBA_ASTC_5x4, + 75 => TEXTUREFORMAT_RGBA_ASTC_5x5, + 76 => TEXTUREFORMAT_RGBA_ASTC_6x5, + 77 => TEXTUREFORMAT_RGBA_ASTC_6x6, + 78 => TEXTUREFORMAT_RGBA_ASTC_8x5, + 79 => TEXTUREFORMAT_RGBA_ASTC_8x6, + 80 => TEXTUREFORMAT_RGBA_ASTC_8x8, + 81 => TEXTUREFORMAT_RGBA_ASTC_10x5, + 82 => TEXTUREFORMAT_RGBA_ASTC_10x6, + 83 => TEXTUREFORMAT_RGBA_ASTC_10x8, + 84 => TEXTUREFORMAT_RGBA_ASTC_10x10, + 85 => TEXTUREFORMAT_RGBA_ASTC_12x10, + 86 => TEXTUREFORMAT_RGBA_ASTC_12x12, + 87 => TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_4x4, + 88 => TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_5x4, + 89 => TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_5x5, + 90 => TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_6x5, + 91 => TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_6x6, + 92 => TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_8x5, + 93 => TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_8x6, + 94 => TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_8x8, + 95 => TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_10x5, + 96 => TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_10x6, + 97 => TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_10x8, + 98 => TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_10x10, + 99 => TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_12x10, + 100 => TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_12x12, + 101 => TEXTUREFORMAT_RED_RGTC1, + 102 => TEXTUREFORMAT_SIGNED_RED_RGTC1, + 103 => TEXTUREFORMAT_RED_GREEN_RGTC2, + 104 => TEXTUREFORMAT_SIGNED_RED_GREEN_RGTC2, + 105 => TEXTUREFORMAT_RGB_BPTC_SIGNED_FLOAT, + 106 => TEXTUREFORMAT_RGB_BPTC_UNSIGNED_FLOAT, + 107 => TEXTUREFORMAT_RGBA_BPTC_UNORM, + 108 => TEXTUREFORMAT_SRGB_ALPHA_BPTC_UNORM, + _ => throw ArgumentError("Unknown value for TTextureFormat: $value"), + }; +} + +/// ! Pixel Data Format +enum TPixelDataFormat { + /// !< One Red channel, float + PIXELDATAFORMAT_R(0), + + /// !< One Red channel, integer + PIXELDATAFORMAT_R_INTEGER(1), + + /// !< Two Red and Green channels, float + PIXELDATAFORMAT_RG(2), + + /// !< Two Red and Green channels, integer + PIXELDATAFORMAT_RG_INTEGER(3), + + /// !< Three Red, Green and Blue channels, float + PIXELDATAFORMAT_RGB(4), + + /// !< Three Red, Green and Blue channels, integer + PIXELDATAFORMAT_RGB_INTEGER(5), + + /// !< Four Red, Green, Blue and Alpha channels, float + PIXELDATAFORMAT_RGBA(6), + + /// !< Four Red, Green, Blue and Alpha channels, integer + PIXELDATAFORMAT_RGBA_INTEGER(7), + PIXELDATAFORMAT_UNUSED(8), + + /// !< Depth, 16-bit or 24-bits usually + PIXELDATAFORMAT_DEPTH_COMPONENT(9), + + /// !< Two Depth (24-bits) + Stencil (8-bits) channels + PIXELDATAFORMAT_DEPTH_STENCIL(10), + PIXELDATAFORMAT_ALPHA(11); + + final int value; + const TPixelDataFormat(this.value); + + static TPixelDataFormat fromValue(int value) => switch (value) { + 0 => PIXELDATAFORMAT_R, + 1 => PIXELDATAFORMAT_R_INTEGER, + 2 => PIXELDATAFORMAT_RG, + 3 => PIXELDATAFORMAT_RG_INTEGER, + 4 => PIXELDATAFORMAT_RGB, + 5 => PIXELDATAFORMAT_RGB_INTEGER, + 6 => PIXELDATAFORMAT_RGBA, + 7 => PIXELDATAFORMAT_RGBA_INTEGER, + 8 => PIXELDATAFORMAT_UNUSED, + 9 => PIXELDATAFORMAT_DEPTH_COMPONENT, + 10 => PIXELDATAFORMAT_DEPTH_STENCIL, + 11 => PIXELDATAFORMAT_ALPHA, + _ => throw ArgumentError("Unknown value for TPixelDataFormat: $value"), + }; +} + +enum TPixelDataType { + /// !< unsigned byte + PIXELDATATYPE_UBYTE(0), + + /// !< signed byte + PIXELDATATYPE_BYTE(1), + + /// !< unsigned short (16-bit) + PIXELDATATYPE_USHORT(2), + + /// !< signed short (16-bit) + PIXELDATATYPE_SHORT(3), + + /// !< unsigned int (32-bit) + PIXELDATATYPE_UINT(4), + + /// !< signed int (32-bit) + PIXELDATATYPE_INT(5), + + /// !< half-float (16-bit float) + PIXELDATATYPE_HALF(6), + + /// !< float (32-bits float) + PIXELDATATYPE_FLOAT(7), + + /// !< compressed pixels, @see CompressedPixelDataType + PIXELDATATYPE_COMPRESSED(8), + + /// !< three low precision floating-point numbers + PIXELDATATYPE_UINT_10F_11F_11F_REV(9), + + /// !< unsigned int (16-bit), encodes 3 RGB channels + PIXELDATATYPE_USHORT_565(10), + + /// !< unsigned normalized 10 bits RGB, 2 bits alpha + PIXELDATATYPE_UINT_2_10_10_10_REV(11); + + final int value; + const TPixelDataType(this.value); + + static TPixelDataType fromValue(int value) => switch (value) { + 0 => PIXELDATATYPE_UBYTE, + 1 => PIXELDATATYPE_BYTE, + 2 => PIXELDATATYPE_USHORT, + 3 => PIXELDATATYPE_SHORT, + 4 => PIXELDATATYPE_UINT, + 5 => PIXELDATATYPE_INT, + 6 => PIXELDATATYPE_HALF, + 7 => PIXELDATATYPE_FLOAT, + 8 => PIXELDATATYPE_COMPRESSED, + 9 => PIXELDATATYPE_UINT_10F_11F_11F_REV, + 10 => PIXELDATATYPE_USHORT_565, + 11 => PIXELDATATYPE_UINT_2_10_10_10_REV, + _ => throw ArgumentError("Unknown value for TPixelDataType: $value"), + }; +} + enum TGizmoAxis { X(0), Y(1), 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 a2634457..5305e077 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 @@ -6,6 +6,7 @@ import 'package:animation_tools_dart/animation_tools_dart.dart'; import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_asset.dart'; import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_gizmo.dart'; import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_material.dart'; +import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_texture.dart'; import 'package:vector_math/vector_math_64.dart'; import 'package:vector_math/vector_math_64.dart' as v64; import '../../../../utils/src/matrix.dart'; @@ -1676,7 +1677,8 @@ class ThermionViewerFFI extends ThermionViewer { throw Exception("Failed to create geometry"); } - print(" is shadow caster : ${RenderableManager_isShadowCaster(_renderableManager!, SceneAsset_getEntity(assetPtr))} is shadow recevier : ${RenderableManager_isShadowReceiver(_renderableManager!, SceneAsset_getEntity(assetPtr))} " ); + print( + " is shadow caster : ${RenderableManager_isShadowCaster(_renderableManager!, SceneAsset_getEntity(assetPtr))} is shadow recevier : ${RenderableManager_isShadowReceiver(_renderableManager!, SceneAsset_getEntity(assetPtr))} "); var asset = FFIAsset( assetPtr, _sceneManager!, _engine!, _unlitMaterialProvider!, this); @@ -1818,7 +1820,7 @@ class ThermionViewerFFI extends ThermionViewer { /// /// /// - Future unproject(ThermionEntity entity, Uint8List input, + Future project(ThermionEntity entity, Uint8List input, int inputWidth, int inputHeight, int outWidth, int outHeight) async { final outPtr = Uint8List(outWidth * outHeight * 4); await withVoidCallback((callback) { @@ -1837,24 +1839,58 @@ class ThermionViewerFFI extends ThermionViewer { return outPtr.buffer.asUint8List(); } - Future createTexture(Uint8List data) async { - var ptr = create_texture(_sceneManager!, data.address, data.length); - return ThermionFFITexture(ptr); + /// + /// + /// + Future createTexture(int width, int height, + {int levels = 1, + TextureSamplerType textureSamplerType = TextureSamplerType.SAMPLER_2D, + TextureFormat textureFormat = TextureFormat.RGBA16F}) async { + final texturePtr = await withPointerCallback((cb) { + Engine_buildTextureRenderThread( + _engine!, + width, + height, + levels, + TTextureSamplerType.values[textureSamplerType.index], + TTextureFormat.values[textureFormat.index], + cb); + }); + if (texturePtr == nullptr) { + throw Exception("Failed to create texture"); + } + return FFITexture( + _engine!, + texturePtr, + ); } - Future applyTexture(ThermionFFITexture texture, ThermionEntity entity, + Future decodeImage(Uint8List data) async { + final name = "image"; + var ptr = Image_decode( + data.address, + data.length, + name.toNativeUtf8().cast(), + ); + if (ptr == nullptr) { + throw Exception("Failed to decode image"); + } + return FFILinearImage(ptr); + } + + Future applyTexture(FFITexture texture, ThermionEntity entity, {int materialIndex = 0, String parameterName = "baseColorMap"}) async { using(parameterName.toNativeUtf8(), (namePtr) async { - apply_texture_to_material(_sceneManager!, entity, texture.pointer, - namePtr.cast(), materialIndex); + apply_texture_to_material(_sceneManager!, entity, + texture.pointer.cast(), namePtr.cast(), materialIndex); }); } /// /// /// - Future destroyTexture(ThermionFFITexture texture) async { - destroy_texture(_sceneManager!, texture.pointer); + Future destroyTexture(FFITexture texture) async { + destroy_texture(_sceneManager!, texture.pointer.cast()); } /// @@ -2137,12 +2173,6 @@ class ThermionViewerFFI extends ThermionViewer { } } -class ThermionFFITexture extends ThermionTexture { - final Pointer pointer; - - ThermionFFITexture(this.pointer); -} - class FFIRenderTarget extends RenderTarget { final Pointer renderTarget; final Pointer viewer; diff --git a/thermion_dart/lib/src/viewer/src/shared_types/texture.dart b/thermion_dart/lib/src/viewer/src/shared_types/texture.dart index 1279e39d..3d8f9f88 100644 --- a/thermion_dart/lib/src/viewer/src/shared_types/texture.dart +++ b/thermion_dart/lib/src/viewer/src/shared_types/texture.dart @@ -1,3 +1,348 @@ -abstract class ThermionTexture { - -} \ No newline at end of file +import 'dart:typed_data'; + +import 'package:thermion_dart/thermion_dart.dart'; + +/// Defines the type of sampler to use with a texture +enum TextureSamplerType { + /// 2D texture + SAMPLER_2D, + + /// Cubemap texture + SAMPLER_CUBEMAP, + + /// External texture (video/camera) + SAMPLER_EXTERNAL, + + /// 3D texture + SAMPLER_3D, + + /// 2D array texture + SAMPLER_2D_ARRAY +} + +/// Defines internal texture formats +enum TextureFormat { + // 8-bits per element + R8, // R 8-bits + R8_SNORM, // R 8-bits (signed normalized) + R8UI, // R 8-bits (unsigned integer) + R8I, // R 8-bits (signed integer) + STENCIL8, // Stencil 8-bits + + // 16-bits per element + R16F, // R 16-bits (float) + R16UI, // R 16-bits (unsigned integer) + R16I, // R 16-bits (signed integer) + RG8, // RG 8-bits each + RG8_SNORM, // RG 8-bits each (signed normalized) + RG8UI, // RG 8-bits each (unsigned integer) + RG8I, // RG 8-bits each (signed integer) + RGB565, // RGB 5-6-5 bits + RGB9_E5, // RGB9_E5 format + RGB5_A1, // RGB 5 bits each, A 1 bit + RGBA4, // RGBA 4 bits each + DEPTH16, // Depth 16-bits + + // 24-bits per element + RGB8, // RGB 8-bits each + SRGB8, // RGB 8-bits each (sRGB color space) + RGB8_SNORM, // RGB 8-bits each (signed normalized) + RGB8UI, // RGB 8-bits each (unsigned integer) + RGB8I, // RGB 8-bits each (signed integer) + DEPTH24, // Depth 24-bits + + // 32-bits per element + R32F, // R 32-bits (float) + R32UI, // R 32-bits (unsigned integer) + R32I, // R 32-bits (signed integer) + RG16F, // RG 16-bits each (float) + RG16UI, // RG 16-bits each (unsigned integer) + RG16I, // RG 16-bits each (signed integer) + R11F_G11F_B10F, // R11F_G11F_B10F format + RGBA8, // RGBA 8-bits each + SRGB8_A8, // RGB 8-bits each (sRGB), A 8-bits + RGBA8_SNORM, // RGBA 8-bits each (signed normalized) + UNUSED, // used to be rgbm + RGB10_A2, // RGB 10-bits each, A 2-bits + RGBA8UI, // RGBA 8-bits each (unsigned integer) + RGBA8I, // RGBA 8-bits each (signed integer) + DEPTH32F, // Depth 32-bits (float) + DEPTH24_STENCIL8, // Depth 24-bits, Stencil 8-bits + DEPTH32F_STENCIL8, // Depth 32-bits (float), Stencil 8-bits + + // 48-bits per element + RGB16F, // RGB 16-bits each (float) + RGB16UI, // RGB 16-bits each (unsigned integer) + RGB16I, // RGB 16-bits each (signed integer) + + // 64-bits per element + RG32F, // RG 32-bits each (float) + RG32UI, // RG 32-bits each (unsigned integer) + RG32I, // RG 32-bits each (signed integer) + RGBA16F, // RGBA 16-bits each (float) + RGBA16UI, // RGBA 16-bits each (unsigned integer) + RGBA16I, // RGBA 16-bits each (signed integer) + + // 96-bits per element + RGB32F, // RGB 32-bits each (float) + RGB32UI, // RGB 32-bits each (unsigned integer) + RGB32I, // RGB 32-bits each (signed integer) + + // 128-bits per element + RGBA32F, // RGBA 32-bits each (float) + RGBA32UI, // RGBA 32-bits each (unsigned integer) + RGBA32I, // RGBA 32-bits each (signed integer) + + // Compressed formats + EAC_R11, // EAC R11 (compressed) + EAC_R11_SIGNED, // EAC R11 (compressed, signed) + EAC_RG11, // EAC RG11 (compressed) + EAC_RG11_SIGNED, // EAC RG11 (compressed, signed) + ETC2_RGB8, // ETC2 RGB8 (compressed) + ETC2_SRGB8, // ETC2 RGB8 (compressed, sRGB) + ETC2_RGB8_A1, // ETC2 RGB8A1 (compressed) + ETC2_SRGB8_A1, // ETC2 RGB8A1 (compressed, sRGB) + ETC2_EAC_RGBA8, // ETC2 RGBA8 (compressed) + ETC2_EAC_SRGBA8, // ETC2 RGBA8 (compressed, sRGB) + + // DXT formats + DXT1_RGB, // DXT1 RGB (compressed) + DXT1_RGBA, // DXT1 RGBA (compressed) + DXT3_RGBA, // DXT3 RGBA (compressed) + DXT5_RGBA, // DXT5 RGBA (compressed) + DXT1_SRGB, // DXT1 sRGB (compressed) + DXT1_SRGBA, // DXT1 sRGBA (compressed) + DXT3_SRGBA, // DXT3 sRGBA (compressed) + DXT5_SRGBA, // DXT5 sRGBA (compressed) + + // ASTC formats + RGBA_ASTC_4x4, // ASTC 4x4 RGBA (compressed) + RGBA_ASTC_5x4, // ASTC 5x4 RGBA (compressed) + RGBA_ASTC_5x5, // ASTC 5x5 RGBA (compressed) + RGBA_ASTC_6x5, // ASTC 6x5 RGBA (compressed) + RGBA_ASTC_6x6, // ASTC 6x6 RGBA (compressed) + RGBA_ASTC_8x5, // ASTC 8x5 RGBA (compressed) + RGBA_ASTC_8x6, // ASTC 8x6 RGBA (compressed) + RGBA_ASTC_8x8, // ASTC 8x8 RGBA (compressed) + RGBA_ASTC_10x5, // ASTC 10x5 RGBA (compressed) + RGBA_ASTC_10x6, // ASTC 10x6 RGBA (compressed) + RGBA_ASTC_10x8, // ASTC 10x8 RGBA (compressed) + RGBA_ASTC_10x10, // ASTC 10x10 RGBA (compressed) + RGBA_ASTC_12x10, // ASTC 12x10 RGBA (compressed) + RGBA_ASTC_12x12, // ASTC 12x12 RGBA (compressed) + SRGB8_ALPHA8_ASTC_4x4, // ASTC 4x4 sRGBA (compressed) + SRGB8_ALPHA8_ASTC_5x4, // ASTC 5x4 sRGBA (compressed) + SRGB8_ALPHA8_ASTC_5x5, // ASTC 5x5 sRGBA (compressed) + SRGB8_ALPHA8_ASTC_6x5, // ASTC 6x5 sRGBA (compressed) + SRGB8_ALPHA8_ASTC_6x6, // ASTC 6x6 sRGBA (compressed) + SRGB8_ALPHA8_ASTC_8x5, // ASTC 8x5 sRGBA (compressed) + SRGB8_ALPHA8_ASTC_8x6, // ASTC 8x6 sRGBA (compressed) + SRGB8_ALPHA8_ASTC_8x8, // ASTC 8x8 sRGBA (compressed) + SRGB8_ALPHA8_ASTC_10x5, // ASTC 10x5 sRGBA (compressed) + SRGB8_ALPHA8_ASTC_10x6, // ASTC 10x6 sRGBA (compressed) + SRGB8_ALPHA8_ASTC_10x8, // ASTC 10x8 sRGBA (compressed) + SRGB8_ALPHA8_ASTC_10x10, // ASTC 10x10 sRGBA (compressed) + SRGB8_ALPHA8_ASTC_12x10, // ASTC 12x10 sRGBA (compressed) + SRGB8_ALPHA8_ASTC_12x12, // ASTC 12x12 sRGBA (compressed) + + // RGTC formats + RED_RGTC1, // BC4 unsigned + SIGNED_RED_RGTC1, // BC4 signed + RED_GREEN_RGTC2, // BC5 unsigned + SIGNED_RED_GREEN_RGTC2, // BC5 signed + + // BPTC formats + RGB_BPTC_SIGNED_FLOAT, // BC6H signed + RGB_BPTC_UNSIGNED_FLOAT, // BC6H unsigned + RGBA_BPTC_UNORM, // BC7 + SRGB_ALPHA_BPTC_UNORM, // BC7 sRGB +} + +/// Defines texture usage flags that affect memory allocation +enum TextureUsage { + /// Default texture usage, optimized for general use + DEFAULT, + + /// Optimized for textures that will be used as color attachments + COLOR_ATTACHMENT, + + /// Optimized for textures that will be used as depth attachments + DEPTH_ATTACHMENT, + + /// Optimized for textures that will be sampled from shaders + SAMPLEABLE +} + +/// Defines texture filter types for magnification and minification +enum TextureFilter { + /// Nearest neighbor sampling (pixelated look) + NEAREST, + + /// Linear interpolation between texels + LINEAR, + + /// Nearest neighbor filtering but uses mipmaps for minification + NEAREST_MIPMAP_NEAREST, + + /// Linear filtering and uses nearest mipmap level + LINEAR_MIPMAP_NEAREST, + + /// Nearest filtering but linearly interpolates between mipmap levels + NEAREST_MIPMAP_LINEAR, + + /// Linear filtering and linear interpolation between mipmap levels (best quality) + LINEAR_MIPMAP_LINEAR +} + +/// Defines texture wrapping modes for when texture coordinates exceed [0,1] +enum TextureWrapMode { + /// Repeats the texture (tiles) + REPEAT, + + /// Mirrors the texture at each repeat + MIRRORED_REPEAT, + + /// Clamps texture coordinates to edge, extending edge pixels + CLAMP_TO_EDGE, + + /// Clamps to border color (usually transparent or black) + CLAMP_TO_BORDER +} + +/// Defines swizzle operations for texture components +enum TextureSwizzle { + /// Use the component as is + CHANNEL_0, + + /// Use the red channel + CHANNEL_R, + + /// Use the green channel + CHANNEL_G, + + /// Use the blue channel + CHANNEL_B, + + /// Use the alpha channel + CHANNEL_A, + + /// Use value 0 + ZERO, + + /// Use value 1 + ONE +} + +/// Defines the texture sampler configuration +abstract class TextureSampler { + /// Creates a new texture sampler with specified filtering and wrapping modes + Future create(TextureFilter minFilter, + TextureFilter magFilter, TextureWrapMode wrapS, TextureWrapMode wrapT, + [TextureWrapMode wrapR = TextureWrapMode.CLAMP_TO_EDGE]); + + /// Creates a texture sampler with comparison mode for shadow mapping + Future createComparisonSampler( + TextureFilter minFilter, + TextureFilter magFilter, + TextureWrapMode wrapS, + TextureWrapMode wrapT, + SamplerCompareFunction compareMode, + [TextureWrapMode wrapR = TextureWrapMode.CLAMP_TO_EDGE]); + + /// Disposes the sampler resources + Future dispose(); +} + +/// Defines a texture object +abstract class Texture { + /// Returns the width of the texture at the specified mipmap level + Future getWidth([int level = 0]); + + /// Returns the height of the texture at the specified mipmap level + Future getHeight([int level = 0]); + + /// Returns the depth of the texture at the specified mipmap level (for 3D textures) + Future getDepth([int level = 0]); + + /// Returns the number of mipmap levels this texture has + Future getLevels(); + + /// Returns the sampler type of this texture + Future getTarget(); + + /// Returns the internal format of this texture + Future getFormat(); + + Future setLinearImage(covariant LinearImage image, PixelDataFormat format, PixelDataType type); + + /// Sets the image data for a 2D texture or a texture level + Future setImage( + int level, Uint8List buffer, PixelDataFormat format, PixelDataType type); + + /// Sets the image data for a region of a 2D texture + Future setSubImage(int level, int xOffset, int yOffset, int width, int height, + Uint8List buffer, PixelDataFormat format, PixelDataType type); + + /// Sets the image data for a 3D texture or cubemap + Future setImage3D( + int level, + int xOffset, + int yOffset, + int zOffset, + int width, + int height, + int depth, + Uint8List buffer, + PixelDataFormat format, + PixelDataType type); + + /// Sets an external image (like a video or camera frame) as the texture source + Future setExternalImage(dynamic externalImage); + + /// Generates mipmaps automatically for the texture + Future generateMipmaps(); + + /// Disposes the texture resources + Future dispose(); +} + +enum PixelDataFormat { + R, /// One Red channel, float + R_INTEGER, /// One Red channel, integer + RG, /// Two Red and Green channels, float + RG_INTEGER, /// Two Red and Green channels, integer + RGB, /// Three Red, Green and Blue channels, float + RGB_INTEGER, /// Three Red, Green and Blue channels, integer + RGBA, /// Four Red, Green, Blue and Alpha channels, float + RGBA_INTEGER, /// Four Red, Green, Blue and Alpha channels, integer + UNUSED, /// Used to be rgbm + DEPTH_COMPONENT, /// Depth, 16-bit or 24-bits usually + DEPTH_STENCIL, /// Two Depth (24-bits) + Stencil (8-bits) channels + ALPHA /// One Alpha channel, float +} + +/// Pixel Data Type +enum PixelDataType { + UBYTE, /// Unsigned byte + BYTE, /// Signed byte + USHORT, /// Unsigned short (16-bit) + SHORT, /// Signed short (16-bit) + UINT, /// Unsigned int (32-bit) + INT, /// Signed int (32-bit) + HALF, /// Half-float (16-bit float) + FLOAT, /// Float (32-bits float) + COMPRESSED, /// Compressed pixels, see CompressedPixelDataType + UINT_10F_11F_11F_REV, /// Three low precision floating-point numbers + USHORT_565, /// Unsigned int (16-bit), encodes 3 RGB channels + UINT_2_10_10_10_REV, /// Unsigned normalized 10 bits RGB, 2 bits alpha +} + +@deprecated +typedef ThermionTexture = Texture; + +abstract class LinearImage { + Future destroy(); + Future getWidth(); + Future getHeight(); + Future getChannels(); +} diff --git a/thermion_dart/lib/src/viewer/src/thermion_viewer_base.dart b/thermion_dart/lib/src/viewer/src/thermion_viewer_base.dart index d3b0e460..b02ff454 100644 --- a/thermion_dart/lib/src/viewer/src/thermion_viewer_base.dart +++ b/thermion_dart/lib/src/viewer/src/thermion_viewer_base.dart @@ -773,9 +773,16 @@ abstract class ThermionViewer { Future removeGridOverlay(); /// - /// Decodes the specified image data and creates a texture. /// - Future createTexture(Uint8List data); + /// + Future createTexture(int width, int height, + {TextureSamplerType textureSamplerType = TextureSamplerType.SAMPLER_2D, + TextureFormat textureFormat = TextureFormat.RGBA16F}); + + /// + /// Decodes the specified image data. + /// + Future decodeImage(Uint8List data); /// /// diff --git a/thermion_dart/native/include/c_api/APIBoundaryTypes.h b/thermion_dart/native/include/c_api/APIBoundaryTypes.h index fe955556..02c55f74 100644 --- a/thermion_dart/native/include/c_api/APIBoundaryTypes.h +++ b/thermion_dart/native/include/c_api/APIBoundaryTypes.h @@ -31,6 +31,9 @@ extern "C" typedef struct TMaterialProvider TMaterialProvider; typedef struct TRenderableManager TRenderableManager; typedef struct TRenderableInstance TRenderableInstance; + typedef struct TTexture TTexture; + typedef struct TTextureSampler TTextureSampler; + typedef struct TLinearImage TLinearImage; struct TMaterialKey { bool doubleSided; diff --git a/thermion_dart/native/include/c_api/TEngine.h b/thermion_dart/native/include/c_api/TEngine.h index 9f313670..33eb4e16 100644 --- a/thermion_dart/native/include/c_api/TEngine.h +++ b/thermion_dart/native/include/c_api/TEngine.h @@ -4,7 +4,7 @@ #include "APIExport.h" #include "APIBoundaryTypes.h" #include "TMaterialInstance.h" - +#include "TTexture.h" #include "ResourceBuffer.hpp" #include "MathUtils.hpp" @@ -13,12 +13,21 @@ extern "C" { #endif + + EMSCRIPTEN_KEEPALIVE TCamera *Engine_getCameraComponent(TEngine* tEngine, EntityId entityId); EMSCRIPTEN_KEEPALIVE TTransformManager *Engine_getTransformManager(TEngine *engine); EMSCRIPTEN_KEEPALIVE TRenderableManager *Engine_getRenderableManager(TEngine *engine); EMSCRIPTEN_KEEPALIVE TLightManager *Engine_getLightManager(TEngine *engine); EMSCRIPTEN_KEEPALIVE TEntityManager *Engine_getEntityManager(TEngine *engine); +EMSCRIPTEN_KEEPALIVE TTexture *Engine_buildTexture(TEngine *engine, + uint32_t width, + uint32_t height, + uint8_t levels, + TTextureSamplerType sampler, + TTextureFormat format); + EMSCRIPTEN_KEEPALIVE TMaterial *Engine_buildMaterial(TEngine *tEngine, const uint8_t* materialData, size_t length); EMSCRIPTEN_KEEPALIVE void Engine_destroyMaterial(TEngine *tEngine, TMaterial *tMaterial); diff --git a/thermion_dart/native/include/c_api/TMaterialInstance.h b/thermion_dart/native/include/c_api/TMaterialInstance.h index bc794fdc..7165633d 100644 --- a/thermion_dart/native/include/c_api/TMaterialInstance.h +++ b/thermion_dart/native/include/c_api/TMaterialInstance.h @@ -78,6 +78,7 @@ extern "C" EMSCRIPTEN_KEEPALIVE void MaterialInstance_setParameterFloat2(TMaterialInstance *materialInstance, const char *name, double x, double y); EMSCRIPTEN_KEEPALIVE void MaterialInstance_setParameterFloat(TMaterialInstance *materialInstance, const char *name, double value); EMSCRIPTEN_KEEPALIVE void MaterialInstance_setParameterInt(TMaterialInstance *materialInstance, const char *name, int value); + EMSCRIPTEN_KEEPALIVE void MaterialInstance_setParameterTexture(TMaterialInstance *materialInstance, const char *propertyName, TTexture *texture, TTextureSampler *sampler); EMSCRIPTEN_KEEPALIVE void MaterialInstance_setDepthFunc(TMaterialInstance *materialInstance, TSamplerCompareFunc depthFunc); EMSCRIPTEN_KEEPALIVE void MaterialInstance_setStencilOpStencilFail( diff --git a/thermion_dart/native/include/c_api/TTexture.h b/thermion_dart/native/include/c_api/TTexture.h new file mode 100644 index 00000000..98d12a70 --- /dev/null +++ b/thermion_dart/native/include/c_api/TTexture.h @@ -0,0 +1,206 @@ +#ifndef _T_TEXTURE_H +#define _T_TEXTURE_H + +#include "APIExport.h" +#include "APIBoundaryTypes.h" +#include "TMaterialInstance.h" + +#include "ResourceBuffer.hpp" +#include "MathUtils.hpp" + +#ifdef __cplusplus +extern "C" +{ +#endif + +enum TTextureSamplerType +{ + SAMPLER_2D = 0, // 2D texture + SAMPLER_CUBEMAP, // Cubemap texture + SAMPLER_EXTERNAL, // External texture (video/camera) + SAMPLER_3D, // 3D texture + SAMPLER_2D_ARRAY // 2D array texture +}; + +enum TTextureFormat +{ + // 8-bits per element + TEXTUREFORMAT_R8 = 0, // R 8-bits + TEXTUREFORMAT_R8_SNORM, // R 8-bits (signed normalized) + TEXTUREFORMAT_R8UI, // R 8-bits (unsigned integer) + TEXTUREFORMAT_R8I, // R 8-bits (signed integer) + TEXTUREFORMAT_STENCIL8, // Stencil 8-bits + + // 16-bits per element + TEXTUREFORMAT_R16F, // R 16-bits (float) + TEXTUREFORMAT_R16UI, // R 16-bits (unsigned integer) + TEXTUREFORMAT_R16I, // R 16-bits (signed integer) + TEXTUREFORMAT_RG8, // RG 8-bits each + TEXTUREFORMAT_RG8_SNORM, // RG 8-bits each (signed normalized) + TEXTUREFORMAT_RG8UI, // RG 8-bits each (unsigned integer) + TEXTUREFORMAT_RG8I, // RG 8-bits each (signed integer) + TEXTUREFORMAT_RGB565, // RGB 5-6-5 bits + TEXTUREFORMAT_RGB9_E5, // RGB9_E5 format + TEXTUREFORMAT_RGB5_A1, // RGB 5 bits each, A 1 bit + TEXTUREFORMAT_RGBA4, // RGBA 4 bits each + TEXTUREFORMAT_DEPTH16, // Depth 16-bits + + // 24-bits per element + TEXTUREFORMAT_RGB8, // RGB 8-bits each + TEXTUREFORMAT_SRGB8, // RGB 8-bits each (sRGB color space) + TEXTUREFORMAT_RGB8_SNORM, // RGB 8-bits each (signed normalized) + TEXTUREFORMAT_RGB8UI, // RGB 8-bits each (unsigned integer) + TEXTUREFORMAT_RGB8I, // RGB 8-bits each (signed integer) + TEXTUREFORMAT_DEPTH24, // Depth 24-bits + + // 32-bits per element + TEXTUREFORMAT_R32F, // R 32-bits (float) + TEXTUREFORMAT_R32UI, // R 32-bits (unsigned integer) + TEXTUREFORMAT_R32I, // R 32-bits (signed integer) + TEXTUREFORMAT_RG16F, // RG 16-bits each (float) + TEXTUREFORMAT_RG16UI, // RG 16-bits each (unsigned integer) + TEXTUREFORMAT_RG16I, // RG 16-bits each (signed integer) + TEXTUREFORMAT_R11F_G11F_B10F, // R11F_G11F_B10F format + TEXTUREFORMAT_RGBA8, // RGBA 8-bits each + TEXTUREFORMAT_SRGB8_A8, // RGB 8-bits each (sRGB), A 8-bits + TEXTUREFORMAT_RGBA8_SNORM, // RGBA 8-bits each (signed normalized) + TEXTUREFORMAT_UNUSED, // used to be rgbm + TEXTUREFORMAT_RGB10_A2, // RGB 10-bits each, A 2-bits + TEXTUREFORMAT_RGBA8UI, // RGBA 8-bits each (unsigned integer) + TEXTUREFORMAT_RGBA8I, // RGBA 8-bits each (signed integer) + TEXTUREFORMAT_DEPTH32F, // Depth 32-bits (float) + TEXTUREFORMAT_DEPTH24_STENCIL8, // Depth 24-bits, Stencil 8-bits + TEXTUREFORMAT_DEPTH32F_STENCIL8, // Depth 32-bits (float), Stencil 8-bits + + // 48-bits per element + TEXTUREFORMAT_RGB16F, // RGB 16-bits each (float) + TEXTUREFORMAT_RGB16UI, // RGB 16-bits each (unsigned integer) + TEXTUREFORMAT_RGB16I, // RGB 16-bits each (signed integer) + + // 64-bits per element + TEXTUREFORMAT_RG32F, // RG 32-bits each (float) + TEXTUREFORMAT_RG32UI, // RG 32-bits each (unsigned integer) + TEXTUREFORMAT_RG32I, // RG 32-bits each (signed integer) + TEXTUREFORMAT_RGBA16F, // RGBA 16-bits each (float) + TEXTUREFORMAT_RGBA16UI, // RGBA 16-bits each (unsigned integer) + TEXTUREFORMAT_RGBA16I, // RGBA 16-bits each (signed integer) + + // 96-bits per element + TEXTUREFORMAT_RGB32F, // RGB 32-bits each (float) + TEXTUREFORMAT_RGB32UI, // RGB 32-bits each (unsigned integer) + TEXTUREFORMAT_RGB32I, // RGB 32-bits each (signed integer) + + // 128-bits per element + TEXTUREFORMAT_RGBA32F, // RGBA 32-bits each (float) + TEXTUREFORMAT_RGBA32UI, // RGBA 32-bits each (unsigned integer) + TEXTUREFORMAT_RGBA32I, // RGBA 32-bits each (signed integer) + + // Compressed formats + TEXTUREFORMAT_EAC_R11, // EAC R11 (compressed) + TEXTUREFORMAT_EAC_R11_SIGNED, // EAC R11 (compressed, signed) + TEXTUREFORMAT_EAC_RG11, // EAC RG11 (compressed) + TEXTUREFORMAT_EAC_RG11_SIGNED, // EAC RG11 (compressed, signed) + TEXTUREFORMAT_ETC2_RGB8, // ETC2 RGB8 (compressed) + TEXTUREFORMAT_ETC2_SRGB8, // ETC2 RGB8 (compressed, sRGB) + TEXTUREFORMAT_ETC2_RGB8_A1, // ETC2 RGB8A1 (compressed) + TEXTUREFORMAT_ETC2_SRGB8_A1, // ETC2 RGB8A1 (compressed, sRGB) + TEXTUREFORMAT_ETC2_EAC_RGBA8, // ETC2 RGBA8 (compressed) + TEXTUREFORMAT_ETC2_EAC_SRGBA8, // ETC2 RGBA8 (compressed, sRGB) + + // DXT formats + TEXTUREFORMAT_DXT1_RGB, // DXT1 RGB (compressed) + TEXTUREFORMAT_DXT1_RGBA, // DXT1 RGBA (compressed) + TEXTUREFORMAT_DXT3_RGBA, // DXT3 RGBA (compressed) + TEXTUREFORMAT_DXT5_RGBA, // DXT5 RGBA (compressed) + TEXTUREFORMAT_DXT1_SRGB, // DXT1 sRGB (compressed) + TEXTUREFORMAT_DXT1_SRGBA, // DXT1 sRGBA (compressed) + TEXTUREFORMAT_DXT3_SRGBA, // DXT3 sRGBA (compressed) + TEXTUREFORMAT_DXT5_SRGBA, // DXT5 sRGBA (compressed) + + // ASTC formats + TEXTUREFORMAT_RGBA_ASTC_4x4, // ASTC 4x4 RGBA (compressed) + TEXTUREFORMAT_RGBA_ASTC_5x4, // ASTC 5x4 RGBA (compressed) + TEXTUREFORMAT_RGBA_ASTC_5x5, // ASTC 5x5 RGBA (compressed) + TEXTUREFORMAT_RGBA_ASTC_6x5, // ASTC 6x5 RGBA (compressed) + TEXTUREFORMAT_RGBA_ASTC_6x6, // ASTC 6x6 RGBA (compressed) + TEXTUREFORMAT_RGBA_ASTC_8x5, // ASTC 8x5 RGBA (compressed) + TEXTUREFORMAT_RGBA_ASTC_8x6, // ASTC 8x6 RGBA (compressed) + TEXTUREFORMAT_RGBA_ASTC_8x8, // ASTC 8x8 RGBA (compressed) + TEXTUREFORMAT_RGBA_ASTC_10x5, // ASTC 10x5 RGBA (compressed) + TEXTUREFORMAT_RGBA_ASTC_10x6, // ASTC 10x6 RGBA (compressed) + TEXTUREFORMAT_RGBA_ASTC_10x8, // ASTC 10x8 RGBA (compressed) + TEXTUREFORMAT_RGBA_ASTC_10x10, // ASTC 10x10 RGBA (compressed) + TEXTUREFORMAT_RGBA_ASTC_12x10, // ASTC 12x10 RGBA (compressed) + TEXTUREFORMAT_RGBA_ASTC_12x12, // ASTC 12x12 RGBA (compressed) + TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_4x4, // ASTC 4x4 sRGBA (compressed) + TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_5x4, // ASTC 5x4 sRGBA (compressed) + TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_5x5, // ASTC 5x5 sRGBA (compressed) + TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_6x5, // ASTC 6x5 sRGBA (compressed) + TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_6x6, // ASTC 6x6 sRGBA (compressed) + TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_8x5, // ASTC 8x5 sRGBA (compressed) + TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_8x6, // ASTC 8x6 sRGBA (compressed) + TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_8x8, // ASTC 8x8 sRGBA (compressed) + TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_10x5, // ASTC 10x5 sRGBA (compressed) + TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_10x6, // ASTC 10x6 sRGBA (compressed) + TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_10x8, // ASTC 10x8 sRGBA (compressed) + TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_10x10, // ASTC 10x10 sRGBA (compressed) + TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_12x10, // ASTC 12x10 sRGBA (compressed) + TEXTUREFORMAT_SRGB8_ALPHA8_ASTC_12x12, // ASTC 12x12 sRGBA (compressed) + + // RGTC formats + TEXTUREFORMAT_RED_RGTC1, // BC4 unsigned + TEXTUREFORMAT_SIGNED_RED_RGTC1, // BC4 signed + TEXTUREFORMAT_RED_GREEN_RGTC2, // BC5 unsigned + TEXTUREFORMAT_SIGNED_RED_GREEN_RGTC2, // BC5 signed + + // BPTC formats + TEXTUREFORMAT_RGB_BPTC_SIGNED_FLOAT, // BC6H signed + TEXTUREFORMAT_RGB_BPTC_UNSIGNED_FLOAT, // BC6H unsigned + TEXTUREFORMAT_RGBA_BPTC_UNORM, // BC7 + TEXTUREFORMAT_SRGB_ALPHA_BPTC_UNORM // BC7 sRGB +}; + +//! Pixel Data Format +enum TPixelDataFormat { + PIXELDATAFORMAT_R, //!< One Red channel, float + PIXELDATAFORMAT_R_INTEGER, //!< One Red channel, integer + PIXELDATAFORMAT_RG, //!< Two Red and Green channels, float + PIXELDATAFORMAT_RG_INTEGER, //!< Two Red and Green channels, integer + PIXELDATAFORMAT_RGB, //!< Three Red, Green and Blue channels, float + PIXELDATAFORMAT_RGB_INTEGER, //!< Three Red, Green and Blue channels, integer + PIXELDATAFORMAT_RGBA, //!< Four Red, Green, Blue and Alpha channels, float + PIXELDATAFORMAT_RGBA_INTEGER, //!< Four Red, Green, Blue and Alpha channels, integer + PIXELDATAFORMAT_UNUSED, // used to be rgbm + PIXELDATAFORMAT_DEPTH_COMPONENT, //!< Depth, 16-bit or 24-bits usually + PIXELDATAFORMAT_DEPTH_STENCIL, //!< Two Depth (24-bits) + Stencil (8-bits) channels + PIXELDATAFORMAT_ALPHA //! One Alpha channel, float +}; + +enum TPixelDataType { + PIXELDATATYPE_UBYTE, //!< unsigned byte + PIXELDATATYPE_BYTE, //!< signed byte + PIXELDATATYPE_USHORT, //!< unsigned short (16-bit) + PIXELDATATYPE_SHORT, //!< signed short (16-bit) + PIXELDATATYPE_UINT, //!< unsigned int (32-bit) + PIXELDATATYPE_INT, //!< signed int (32-bit) + PIXELDATATYPE_HALF, //!< half-float (16-bit float) + PIXELDATATYPE_FLOAT, //!< float (32-bits float) + PIXELDATATYPE_COMPRESSED, //!< compressed pixels, @see CompressedPixelDataType + PIXELDATATYPE_UINT_10F_11F_11F_REV, //!< three low precision floating-point numbers + PIXELDATATYPE_USHORT_565, //!< unsigned int (16-bit), encodes 3 RGB channels + PIXELDATATYPE_UINT_2_10_10_10_REV, //!< unsigned normalized 10 bits RGB, 2 bits alpha +}; + +EMSCRIPTEN_KEEPALIVE bool Texture_loadImage(TEngine *tEngine, TTexture *tTexture, TLinearImage *tImage, TPixelDataFormat bufferFormat, TPixelDataType pixelDataType); +EMSCRIPTEN_KEEPALIVE TLinearImage* Image_decode(uint8_t* data, size_t length, const char* name = "image"); +EMSCRIPTEN_KEEPALIVE void Image_destroy(TLinearImage* tLinearImage); +EMSCRIPTEN_KEEPALIVE uint32_t Image_getWidth(TLinearImage* tLinearImage); +EMSCRIPTEN_KEEPALIVE uint32_t Image_getHeight(TLinearImage* tLinearImage); +EMSCRIPTEN_KEEPALIVE uint32_t Image_getChannels(TLinearImage* tLinearImage); + + +#ifdef __cplusplus +} +#endif + +#endif // _T_TEXTURE_H \ No newline at end of file diff --git a/thermion_dart/native/include/c_api/ThermionDartRenderThreadApi.h b/thermion_dart/native/include/c_api/ThermionDartRenderThreadApi.h index fe9ddce5..31aa56db 100644 --- a/thermion_dart/native/include/c_api/ThermionDartRenderThreadApi.h +++ b/thermion_dart/native/include/c_api/ThermionDartRenderThreadApi.h @@ -3,6 +3,7 @@ #include "ThermionDartApi.h" #include "TView.h" +#include "TTexture.h" #include "TMaterialProvider.h" #ifdef __cplusplus @@ -46,6 +47,14 @@ namespace thermion EMSCRIPTEN_KEEPALIVE void Engine_buildMaterialRenderThread(TEngine *tEngine, const uint8_t *materialData, size_t length, void (*onComplete)(TMaterial *)); EMSCRIPTEN_KEEPALIVE void Engine_destroyMaterialRenderThread(TEngine *tEngine, TMaterial *tMaterial, void (*onComplete)()); + EMSCRIPTEN_KEEPALIVE void Engine_buildTextureRenderThread(TEngine *engine, + uint32_t width, + uint32_t height, + uint8_t levels, + TTextureSamplerType sampler, + TTextureFormat format, + void (*onComplete)(TTexture*) + ); EMSCRIPTEN_KEEPALIVE void Material_createInstanceRenderThread(TMaterial *tMaterial, void (*onComplete)(TMaterialInstance *)); diff --git a/thermion_dart/native/src/c_api/TEngine.cpp b/thermion_dart/native/src/c_api/TEngine.cpp index 3d52ea0a..6f08793e 100644 --- a/thermion_dart/native/src/c_api/TEngine.cpp +++ b/thermion_dart/native/src/c_api/TEngine.cpp @@ -1,9 +1,10 @@ #include "c_api/TEngine.h" - #include #include #include +#include +#include #include #include @@ -79,6 +80,170 @@ namespace thermion engine->destroy(material); } + ::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 *Engine_buildTexture(TEngine *tEngine, + uint32_t width, + uint32_t height, + uint8_t levels, + TTextureSamplerType tSamplerType, + TTextureFormat tFormat) + { + auto *engine = reinterpret_cast(tEngine); + auto format = convertToFilamentFormat(tFormat); + auto samplerType = static_cast<::filament::Texture::Sampler>(static_cast(tSamplerType)); + auto *texture = Texture::Builder() + .width(width) + .height(height) + .levels(levels) + .sampler(samplerType) + .format(format) + .build(*engine); + Log("Created texture %d x %d, format %d", texture->getWidth(), texture->getHeight(), texture->getFormat()); + return reinterpret_cast(texture); + } + #ifdef __cplusplus } } diff --git a/thermion_dart/native/src/c_api/TMaterialInstance.cpp b/thermion_dart/native/src/c_api/TMaterialInstance.cpp index 65594e3b..207ee270 100644 --- a/thermion_dart/native/src/c_api/TMaterialInstance.cpp +++ b/thermion_dart/native/src/c_api/TMaterialInstance.cpp @@ -14,10 +14,11 @@ namespace thermion { #endif - EMSCRIPTEN_KEEPALIVE TMaterialInstance *Material_createInstance(TMaterial *tMaterial) { - auto *material = reinterpret_cast(tMaterial); + EMSCRIPTEN_KEEPALIVE TMaterialInstance *Material_createInstance(TMaterial *tMaterial) + { + auto *material = reinterpret_cast(tMaterial); auto *instance = material->createInstance(); - return reinterpret_cast(instance); + return reinterpret_cast(instance); } EMSCRIPTEN_KEEPALIVE bool MaterialInstance_isStencilWriteEnabled(TMaterialInstance *tMaterialInstance) @@ -60,6 +61,14 @@ namespace thermion reinterpret_cast<::filament::MaterialInstance *>(materialInstance)->setParameter(propertyName, value); } + EMSCRIPTEN_KEEPALIVE void MaterialInstance_setParameterTexture(TMaterialInstance *tMaterialInstance, const char *propertyName, TTexture* tTexture, TTextureSampler* tSampler) { + auto *materialInstance = reinterpret_cast<::filament::MaterialInstance *>(tMaterialInstance); + auto texture = reinterpret_cast<::filament::Texture*>(tTexture); + auto sampler = reinterpret_cast<::filament::TextureSampler*>(tSampler); + materialInstance->setParameter(propertyName, texture, *sampler); + } + + EMSCRIPTEN_KEEPALIVE void MaterialInstance_setDepthFunc(TMaterialInstance *tMaterialInstance, TSamplerCompareFunc tDepthFunc) { auto *materialInstance = reinterpret_cast<::filament::MaterialInstance *>(tMaterialInstance); @@ -109,7 +118,6 @@ namespace thermion auto *materialInstance = reinterpret_cast<::filament::MaterialInstance *>(tMaterialInstance); auto face = static_cast(tFace); materialInstance->setStencilReferenceValue(value, face); - } EMSCRIPTEN_KEEPALIVE void MaterialInstance_setStencilWrite(TMaterialInstance *materialInstance, bool enabled) diff --git a/thermion_dart/native/src/c_api/TTexture.cpp b/thermion_dart/native/src/c_api/TTexture.cpp new file mode 100644 index 00000000..a5f86ae7 --- /dev/null +++ b/thermion_dart/native/src/c_api/TTexture.cpp @@ -0,0 +1,101 @@ +#include "c_api/TTexture.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Log.hpp" + +#ifdef __cplusplus +namespace thermion +{ + extern "C" + { + using namespace filament::backend; + +#endif + + EMSCRIPTEN_KEEPALIVE TLinearImage* Image_decode(uint8_t* data, size_t length, const char* name = "image") { + std::istringstream stream(std::string(reinterpret_cast(data), length)); + + auto *linearImage = new image::LinearImage(::image::ImageDecoder::decode(stream, name, ::image::ImageDecoder::ColorSpace::SRGB)); + + if (!linearImage->isValid()) + { + Log("Failed to decode image."); + return nullptr; + } + return reinterpret_cast(linearImage); + + } + + EMSCRIPTEN_KEEPALIVE uint32_t Image_getWidth(TLinearImage* tLinearImage) { + auto *linearImage = reinterpret_cast<::image::LinearImage*>(tLinearImage); + return linearImage->getWidth(); + } + EMSCRIPTEN_KEEPALIVE uint32_t Image_getHeight(TLinearImage* tLinearImage) { + auto *linearImage = reinterpret_cast<::image::LinearImage*>(tLinearImage); + return linearImage->getHeight(); + } + EMSCRIPTEN_KEEPALIVE uint32_t Image_getChannels(TLinearImage* tLinearImage) { + auto *linearImage = reinterpret_cast<::image::LinearImage*>(tLinearImage); + return linearImage->getChannels(); + } + + EMSCRIPTEN_KEEPALIVE void Image_destroy(TLinearImage* tLinearImage) { + auto *linearImage = reinterpret_cast<::image::LinearImage*>(tLinearImage); + delete linearImage; + } + + EMSCRIPTEN_KEEPALIVE bool Texture_loadImage(TEngine *tEngine, TTexture *tTexture, TLinearImage *tImage, TPixelDataFormat tBufferFormat, TPixelDataType tPixelDataType) + { + auto engine = reinterpret_cast(tEngine); + auto image = reinterpret_cast<::image::LinearImage*>(tImage); + auto texture = reinterpret_cast(tTexture); + auto bufferFormat = static_cast(static_cast(tBufferFormat)); + auto pixelDataType = static_cast(static_cast(tPixelDataType)); + + uint32_t w = image->getWidth(); + uint32_t h = image->getHeight(); + uint32_t channels = image->getChannels(); + + size_t size; + switch(bufferFormat) { + case PixelBufferDescriptor::PixelDataFormat::RGB: + case PixelBufferDescriptor::PixelDataFormat::RGBA: + size = w * h * channels * sizeof(float); + break; + case PixelBufferDescriptor::PixelDataFormat::RGB_INTEGER: + case PixelBufferDescriptor::PixelDataFormat::RGBA_INTEGER: + size = w * h * channels * sizeof(uint8_t); + break; + default: + Log("Unsupported buffer format type : %d", bufferFormat); + return false; + } + + Log("Dimensions %d x %d, channels %d, size %d, buffer format %d and pixel data type %d", w, h,channels, size, bufferFormat, pixelDataType); + + + filament::Texture::PixelBufferDescriptor buffer( + image->getPixelRef(), + size, + bufferFormat, + pixelDataType); + + texture->setImage(*engine, 0, std::move(buffer)); + return true; + + } + +#ifdef __cplusplus + } +} +#endif diff --git a/thermion_dart/native/src/c_api/ThermionDartApi.cpp b/thermion_dart/native/src/c_api/ThermionDartApi.cpp index a0cbab85..cbd4a5e5 100644 --- a/thermion_dart/native/src/c_api/ThermionDartApi.cpp +++ b/thermion_dart/native/src/c_api/ThermionDartApi.cpp @@ -418,11 +418,6 @@ extern "C" // ((FilamentViewer *)viewer)->unprojectTexture(entity, input, inputWidth, inputHeight, out, outWidth, outHeight); } - EMSCRIPTEN_KEEPALIVE void *const create_texture(TSceneManager *sceneManager, uint8_t *data, size_t length) - { - return (void *const)((SceneManager *)sceneManager)->createTexture(data, length, "SOMETEXTURE"); - } - EMSCRIPTEN_KEEPALIVE void apply_texture_to_material(TSceneManager *sceneManager, EntityId entity, void *const texture, const char *parameterName, int materialIndex) { ((SceneManager *)sceneManager)->applyTexture(entity, reinterpret_cast(texture), parameterName, materialIndex); diff --git a/thermion_dart/native/src/c_api/ThermionDartRenderThreadApi.cpp b/thermion_dart/native/src/c_api/ThermionDartRenderThreadApi.cpp index 84146dc9..7398a164 100644 --- a/thermion_dart/native/src/c_api/ThermionDartRenderThreadApi.cpp +++ b/thermion_dart/native/src/c_api/ThermionDartRenderThreadApi.cpp @@ -10,6 +10,7 @@ #include "c_api/TView.h" #include "c_api/TSceneAsset.h" #include "c_api/TSceneManager.h" +#include "c_api/TTexture.h" #include "c_api/TAnimationManager.h" #include "c_api/ThermionDartRenderThreadApi.h" @@ -301,6 +302,23 @@ extern "C" auto fut = _rl->add_task(lambda); } + EMSCRIPTEN_KEEPALIVE void Engine_buildTextureRenderThread(TEngine *engine, + uint32_t width, + uint32_t height, + uint8_t levels, + TTextureSamplerType sampler, + TTextureFormat format, + void (*onComplete)(TTexture*) +) { + std::packaged_task lambda( + [=]() mutable + { + auto texture = Engine_buildTexture(engine, width, height, levels, sampler, format); + onComplete(texture); + }); +auto fut = _rl->add_task(lambda); +} + EMSCRIPTEN_KEEPALIVE void Engine_buildMaterialRenderThread(TEngine *tEngine, const uint8_t *materialData, size_t length, void (*onComplete)(TMaterial *)) { std::packaged_task lambda( diff --git a/thermion_dart/test/texture_tests.dart b/thermion_dart/test/texture_tests.dart new file mode 100644 index 00000000..3e111a57 --- /dev/null +++ b/thermion_dart/test/texture_tests.dart @@ -0,0 +1,26 @@ +import 'dart:io'; +import 'package:test/test.dart'; +import 'package:thermion_dart/thermion_dart.dart'; +import 'helpers.dart'; + +void main() async { + final testHelper = TestHelper("material"); + + group("image", () { + test('decode image', () async { + await testHelper.withViewer((viewer) async { + var imageData = + File("${testHelper.testDir}/assets/cube_texture_512x512.png") + .readAsBytesSync(); + final image = await viewer.decodeImage(imageData); + expect(await image.getChannels(), 4); + expect(await image.getWidth(), 512); + expect(await image.getHeight(), 512); + + final texture = await viewer.createTexture( + await image.getWidth(), await image.getHeight(), textureFormat: TextureFormat.RGBA32F); + await texture.setLinearImage(image, PixelDataFormat.RGBA, PixelDataType.FLOAT); + }, bg: kRed); + }); + }); +}