create material for texture baking

textures can now be created manually and are no longer tracked by SceneManager (and therefore require manual tracking/disposal)
This commit is contained in:
Nick Fisher
2025-03-04 14:52:48 +08:00
parent 5dca42c3c1
commit fc7f5d7b93
27 changed files with 528 additions and 571 deletions

View File

@@ -0,0 +1,19 @@
import 'dart:ffi';
import 'package:thermion_dart/src/viewer/src/ffi/src/callbacks.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_texture.dart';
import 'package:thermion_dart/thermion_dart.dart';
class FFIRenderTarget extends RenderTarget {
final Pointer<TRenderTarget> renderTarget;
final Pointer<TViewer> viewer;
final Pointer<TEngine> engine;
FFIRenderTarget(this.renderTarget, this.viewer, this.engine);
@override
Future<Texture> getColorTexture() async {
final ptr = RenderTarget_getColorTexture(renderTarget);
return FFITexture(engine, ptr);
}
}

View File

@@ -23,9 +23,8 @@ class FFITexture extends Texture {
}
@override
Future dispose() {
// TODO: implement dispose
throw UnimplementedError();
Future dispose() async {
Engine_destroyTexture(_engine, pointer);
}
@override
@@ -130,4 +129,13 @@ class FFILinearImage extends LinearImage {
Future<int> getWidth() async {
return Image_getWidth(pointer);
}
@override
Future<Float32List> getData() async {
final height = await getHeight();
final width = await getWidth();
final channels = await getChannels();
final ptr = Image_getBytes(pointer);
return ptr.asTypedList(height * width * channels);
}
}

View File

@@ -1,4 +1,5 @@
import 'dart:ffi';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_render_target.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/thermion_dart.g.dart';
import 'package:thermion_dart/src/viewer/src/shared_types/shared_types.dart';
import 'callbacks.dart';
@@ -8,12 +9,17 @@ import 'thermion_viewer_ffi.dart';
class FFIView extends View {
final Pointer<TView> view;
final Pointer<TViewer> viewer;
final Pointer<TEngine> engine;
FFIRenderTarget? renderTarget;
FFIView(this.view, this.viewer) {
FFIView(this.view, this.viewer, this.engine) {
final renderTargetPtr = View_getRenderTarget(view);
if (renderTargetPtr != nullptr) {
renderTarget = FFIRenderTarget(renderTargetPtr, viewer);
renderTarget = FFIRenderTarget(
renderTargetPtr,
viewer,
engine
);
}
}

View File

@@ -663,36 +663,6 @@ external void get_bounding_box_to_out(
ffi.Pointer<ffi.Float> maxY,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TViewer>,
EntityId,
ffi.Pointer<ffi.Uint8>,
ffi.Uint32,
ffi.Uint32,
ffi.Pointer<ffi.Uint8>,
ffi.Uint32,
ffi.Uint32)>(isLeaf: true)
external void unproject_texture(
ffi.Pointer<TViewer> viewer,
int entity,
ffi.Pointer<ffi.Uint8> input,
int inputWidth,
int inputHeight,
ffi.Pointer<ffi.Uint8> out,
int outWidth,
int outHeight,
);
@ffi.Native<
ffi.Pointer<ffi.Void> Function(ffi.Pointer<TSceneManager>,
ffi.Pointer<ffi.Uint8>, ffi.Size)>(isLeaf: true)
external ffi.Pointer<ffi.Void> create_texture(
ffi.Pointer<TSceneManager> sceneManager,
ffi.Pointer<ffi.Uint8> data,
int length,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TSceneManager>, ffi.Pointer<ffi.Void>)>(isLeaf: true)
@@ -701,17 +671,6 @@ external void destroy_texture(
ffi.Pointer<ffi.Void> texture,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<TSceneManager>, EntityId,
ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Char>, ffi.Int)>(isLeaf: true)
external void apply_texture_to_material(
ffi.Pointer<TSceneManager> sceneManager,
int entity,
ffi.Pointer<ffi.Void> texture,
ffi.Pointer<ffi.Char> parameterName,
int materialIndex,
);
@ffi.Native<TViewport Function(ffi.Pointer<TView>)>(isLeaf: true)
external TViewport View_getViewport(
ffi.Pointer<TView> view,
@@ -920,6 +879,15 @@ bool Texture_loadImage(
pixelDataType.value,
);
@ffi.Native<
ffi.Pointer<TLinearImage> Function(
ffi.Uint32, ffi.Uint32, ffi.Uint32)>(isLeaf: true)
external ffi.Pointer<TLinearImage> Image_createEmpty(
int width,
int height,
int channel,
);
@ffi.Native<
ffi.Pointer<TLinearImage> Function(
ffi.Pointer<ffi.Uint8>, ffi.Size, ffi.Pointer<ffi.Char>)>(isLeaf: true)
@@ -929,6 +897,12 @@ external ffi.Pointer<TLinearImage> Image_decode(
ffi.Pointer<ffi.Char> name,
);
@ffi.Native<ffi.Pointer<ffi.Float> Function(ffi.Pointer<TLinearImage>)>(
isLeaf: true)
external ffi.Pointer<ffi.Float> Image_getBytes(
ffi.Pointer<TLinearImage> tLinearImage,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TLinearImage>)>(isLeaf: true)
external void Image_destroy(
ffi.Pointer<TLinearImage> tLinearImage,
@@ -949,6 +923,12 @@ external int Image_getChannels(
ffi.Pointer<TLinearImage> tLinearImage,
);
@ffi.Native<ffi.Pointer<TTexture> Function(ffi.Pointer<TRenderTarget>)>(
isLeaf: true)
external ffi.Pointer<TTexture> RenderTarget_getColorTexture(
ffi.Pointer<TRenderTarget> tRenderTarget,
);
@ffi.Native<ffi.Pointer<TTextureSampler> Function()>(isLeaf: true)
external ffi.Pointer<TTextureSampler> TextureSampler_create();
@@ -2139,29 +2119,6 @@ external void reset_to_rest_pose_render_thread(
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> callback,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TViewer>,
EntityId,
ffi.Pointer<ffi.Uint8>,
ffi.Uint32,
ffi.Uint32,
ffi.Pointer<ffi.Uint8>,
ffi.Uint32,
ffi.Uint32,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(isLeaf: true)
external void unproject_texture_render_thread(
ffi.Pointer<TViewer> viewer,
int entity,
ffi.Pointer<ffi.Uint8> input,
int inputWidth,
int inputHeight,
ffi.Pointer<ffi.Uint8> out,
int outWidth,
int outHeight,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> callback,
);
@ffi.Native<
ffi.Pointer<TGizmo> Function(
ffi.Pointer<TSceneManager>,
@@ -2633,6 +2590,13 @@ ffi.Pointer<TTexture> Engine_buildTexture(
format.value,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TEngine>, ffi.Pointer<TTexture>)>(
isLeaf: true)
external void Engine_destroyTexture(
ffi.Pointer<TEngine> tEngine,
ffi.Pointer<TTexture> tTexture,
);
@ffi.Native<
ffi.Pointer<TMaterial> Function(
ffi.Pointer<TEngine>, ffi.Pointer<ffi.Uint8>, ffi.Size)>(isLeaf: true)

View File

@@ -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_render_target.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;
@@ -83,7 +84,7 @@ class ThermionViewerFFI extends ThermionViewer {
_viewer!, textureHandle, width, height, cb);
});
return FFIRenderTarget(renderTarget, _viewer!);
return FFIRenderTarget(renderTarget, _viewer!, _engine!);
}
///
@@ -110,14 +111,14 @@ class ThermionViewerFFI extends ThermionViewer {
if (view == nullptr) {
throw Exception("Failed to create view");
}
return FFIView(view, _viewer!);
return FFIView(view, _viewer!,_engine!);
}
///
///
///
Future updateViewportAndCameraProjection(double width, double height) async {
var mainView = FFIView(Viewer_getViewAt(_viewer!, 0), _viewer!);
var mainView = FFIView(Viewer_getViewAt(_viewer!, 0), _viewer!, _engine!);
mainView.updateViewport(width.toInt(), height.toInt());
final cameraCount = await getCameraCount();
@@ -1817,28 +1818,6 @@ class ThermionViewerFFI extends ThermionViewer {
}
}
///
///
///
Future<Uint8List> project(ThermionEntity entity, Uint8List input,
int inputWidth, int inputHeight, int outWidth, int outHeight) async {
final outPtr = Uint8List(outWidth * outHeight * 4);
await withVoidCallback((callback) {
unproject_texture_render_thread(
_viewer!,
entity,
input.address,
inputWidth,
inputHeight,
outPtr.address,
outWidth,
outHeight,
callback);
});
return outPtr.buffer.asUint8List();
}
///
///
///
@@ -1897,6 +1876,9 @@ class ThermionViewerFFI extends ThermionViewer {
return FFITextureSampler(samplerPtr);
}
///
///
///
Future<LinearImage> decodeImage(Uint8List data) async {
final name = "image";
var ptr = Image_decode(
@@ -1910,12 +1892,12 @@ class ThermionViewerFFI extends ThermionViewer {
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.cast<Void>(), namePtr.cast<Char>(), materialIndex);
});
///
/// Creates an (empty) imge with the given dimensions.
///
Future<LinearImage> createImage(int width, int height, int channels) async {
final ptr = Image_createEmpty(width, height, channels);
return FFILinearImage(ptr);
}
///
@@ -2173,7 +2155,7 @@ class ThermionViewerFFI extends ThermionViewer {
if (view == nullptr) {
throw Exception("Failed to get view");
}
return FFIView(view, _viewer!);
return FFIView(view, _viewer!, _engine!);
}
@override
@@ -2205,12 +2187,7 @@ class ThermionViewerFFI extends ThermionViewer {
}
}
class FFIRenderTarget extends RenderTarget {
final Pointer<TRenderTarget> renderTarget;
final Pointer<TViewer> viewer;
FFIRenderTarget(this.renderTarget, this.viewer);
}
class FFISwapChain extends SwapChain {
final Pointer<TSwapChain> swapChain;

View File

@@ -1,3 +1,5 @@
import 'package:thermion_dart/thermion_dart.dart';
abstract class RenderTarget {
Future<Texture> getColorTexture();
}

View File

@@ -420,6 +420,7 @@ typedef ThermionTexture = Texture;
abstract class LinearImage {
Future destroy();
Future<Float32List> getData();
Future<int> getWidth();
Future<int> getHeight();
Future<int> getChannels();

View File

@@ -777,18 +777,21 @@ abstract class ThermionViewer {
///
Future<Texture> createTexture(int width, int height,
{TextureSamplerType textureSamplerType = TextureSamplerType.SAMPLER_2D,
TextureFormat textureFormat = TextureFormat.RGBA16F});
TextureFormat textureFormat = TextureFormat.RGBA32F});
Future<TextureSampler> createTextureSampler({
TextureMinFilter minFilter = TextureMinFilter.LINEAR,
TextureMagFilter magFilter = TextureMagFilter.LINEAR,
TextureWrapMode wrapS = TextureWrapMode.CLAMP_TO_EDGE,
TextureWrapMode wrapT = TextureWrapMode.CLAMP_TO_EDGE,
TextureWrapMode wrapR = TextureWrapMode.CLAMP_TO_EDGE,
double anisotropy = 0.0,
TextureCompareMode compareMode = TextureCompareMode.NONE,
TextureCompareFunc compareFunc = TextureCompareFunc.LESS_EQUAL
});
///
///
///
Future<TextureSampler> createTextureSampler({
TextureMinFilter minFilter = TextureMinFilter.LINEAR,
TextureMagFilter magFilter = TextureMagFilter.LINEAR,
TextureWrapMode wrapS = TextureWrapMode.CLAMP_TO_EDGE,
TextureWrapMode wrapT = TextureWrapMode.CLAMP_TO_EDGE,
TextureWrapMode wrapR = TextureWrapMode.CLAMP_TO_EDGE,
double anisotropy = 0.0,
TextureCompareMode compareMode = TextureCompareMode.NONE,
TextureCompareFunc compareFunc = TextureCompareFunc.LESS_EQUAL
});
///
/// Decodes the specified image data.
@@ -796,10 +799,9 @@ Future<TextureSampler> createTextureSampler({
Future<LinearImage> decodeImage(Uint8List data);
///
/// Creates an (empty) imge with the given dimensions.
///
///
Future applyTexture(covariant ThermionTexture texture, ThermionEntity entity,
{int materialIndex = 0, String parameterName = "baseColorMap"});
Future<LinearImage> createImage(int width, int height, int channels);
///
///

View File

@@ -659,19 +659,7 @@ class ThermionViewerStub extends ThermionViewer {
// TODO: implement addDirectLight
throw UnimplementedError();
}
@override
Future applyTexture(covariant ThermionTexture texture, ThermionEntity entity, {int materialIndex = 0, String parameterName = "baseColorMap"}) {
// TODO: implement applyTexture
throw UnimplementedError();
}
@override
Future<ThermionTexture> createTexture(Uint8List data) {
// TODO: implement createTexture
throw UnimplementedError();
}
@override
Future<MaterialInstance> createUbershaderMaterialInstance({bool doubleSided = false, bool unlit = false, bool hasVertexColors = false, bool hasBaseColorTexture = false, bool hasNormalTexture = false, bool hasOcclusionTexture = false, bool hasEmissiveTexture = false, bool useSpecularGlossiness = false, AlphaMode alphaMode = AlphaMode.OPAQUE, bool enableDiagnostics = false, bool hasMetallicRoughnessTexture = false, int metallicRoughnessUV = 0, int baseColorUV = 0, bool hasClearCoatTexture = false, int clearCoatUV = 0, bool hasClearCoatRoughnessTexture = false, int clearCoatRoughnessUV = 0, bool hasClearCoatNormalTexture = false, int clearCoatNormalUV = 0, bool hasClearCoat = false, bool hasTransmission = false, bool hasTextureTransforms = false, int emissiveUV = 0, int aoUV = 0, int normalUV = 0, bool hasTransmissionTexture = false, int transmissionUV = 0, bool hasSheenColorTexture = false, int sheenColorUV = 0, bool hasSheenRoughnessTexture = false, int sheenRoughnessUV = 0, bool hasVolumeThicknessTexture = false, int volumeThicknessUV = 0, bool hasSheen = false, bool hasIOR = false, bool hasVolume = false}) {
// TODO: implement createUbershaderMaterialInstance