fix: store reference to material instances in ThermionViewer so they can be cleaned up on dispose
This commit is contained in:
@@ -122,7 +122,7 @@ class FFIAsset extends ThermionAsset {
|
||||
}
|
||||
var sourceMaterialInstance = ThermionFFIMaterialInstance(
|
||||
RenderableManager_getMaterialInstanceAt(
|
||||
renderableManager, targetEntity, 0));
|
||||
renderableManager, targetEntity, 0), sceneManager);
|
||||
|
||||
await sourceMaterialInstance.setStencilWriteEnabled(true);
|
||||
await sourceMaterialInstance.setDepthWriteEnabled(true);
|
||||
@@ -138,7 +138,7 @@ class FFIAsset extends ThermionAsset {
|
||||
_unlitMaterialProvider, key.address, cb);
|
||||
});
|
||||
final highlightMaterialInstance =
|
||||
ThermionFFIMaterialInstance(materialInstancePtr);
|
||||
ThermionFFIMaterialInstance(materialInstancePtr, sceneManager);
|
||||
await highlightMaterialInstance
|
||||
.setStencilCompareFunction(SamplerCompareFunction.NE);
|
||||
await highlightMaterialInstance.setStencilReferenceValue(1);
|
||||
|
||||
@@ -6,8 +6,9 @@ import 'package:thermion_dart/thermion_dart.dart';
|
||||
|
||||
class ThermionFFIMaterialInstance extends MaterialInstance {
|
||||
final Pointer<TMaterialInstance> pointer;
|
||||
final Pointer<TSceneManager> sceneManager;
|
||||
|
||||
ThermionFFIMaterialInstance(this.pointer) {
|
||||
ThermionFFIMaterialInstance(this.pointer, this.sceneManager) {
|
||||
if (pointer == nullptr) {
|
||||
throw Exception("MaterialInstance not found");
|
||||
}
|
||||
@@ -50,14 +51,17 @@ class ThermionFFIMaterialInstance extends MaterialInstance {
|
||||
|
||||
@override
|
||||
Future setDepthFunc(SamplerCompareFunction depthFunc) async {
|
||||
MaterialInstance_setDepthFunc(pointer, TSamplerCompareFunc.values[depthFunc.index]);
|
||||
MaterialInstance_setDepthFunc(
|
||||
pointer, TSamplerCompareFunc.values[depthFunc.index]);
|
||||
}
|
||||
|
||||
@override
|
||||
Future setStencilCompareFunction(SamplerCompareFunction func,
|
||||
[StencilFace face = StencilFace.FRONT_AND_BACK]) async {
|
||||
MaterialInstance_setStencilCompareFunction(
|
||||
pointer, TSamplerCompareFunc.values[func.index], TStencilFace.values[face.index]);
|
||||
pointer,
|
||||
TSamplerCompareFunc.values[func.index],
|
||||
TStencilFace.values[face.index]);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -113,4 +117,8 @@ class ThermionFFIMaterialInstance extends MaterialInstance {
|
||||
Future setStencilWriteMask(int mask) async {
|
||||
MaterialInstance_setStencilWriteMask(pointer, mask);
|
||||
}
|
||||
|
||||
Future dispose() async {
|
||||
SceneManager_destroyMaterialInstance(sceneManager, pointer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,6 +282,8 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
final _onDispose = <Future Function()>[];
|
||||
bool _disposing = false;
|
||||
|
||||
final _materialInstances = <ThermionFFIMaterialInstance>[];
|
||||
|
||||
///
|
||||
///
|
||||
///
|
||||
@@ -291,12 +293,13 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
throw Exception("Viewer has already been disposed.");
|
||||
}
|
||||
_disposing = true;
|
||||
|
||||
await setRendering(false);
|
||||
await clearEntities();
|
||||
for (final mInstance in _materialInstances) {
|
||||
await mInstance.dispose();
|
||||
}
|
||||
await clearLights();
|
||||
|
||||
// await _sceneUpdateEventController.close();
|
||||
Viewer_destroyOnRenderThread(_viewer!);
|
||||
_sceneManager = null;
|
||||
_viewer = null;
|
||||
@@ -984,9 +987,6 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
_sceneManager!, asset.pointer, callback));
|
||||
}
|
||||
|
||||
///
|
||||
///
|
||||
///
|
||||
///
|
||||
///
|
||||
///
|
||||
@@ -1880,7 +1880,10 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
throw Exception("Failed to create material instance");
|
||||
}
|
||||
|
||||
return ThermionFFIMaterialInstance(materialInstance);
|
||||
var instance =
|
||||
ThermionFFIMaterialInstance(materialInstance, _sceneManager!);
|
||||
_materialInstances.add(instance);
|
||||
return instance;
|
||||
}
|
||||
|
||||
///
|
||||
@@ -1888,21 +1891,20 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
///
|
||||
Future destroyMaterialInstance(
|
||||
ThermionFFIMaterialInstance materialInstance) async {
|
||||
SceneManager_destroyMaterialInstance(
|
||||
_sceneManager!, materialInstance.pointer);
|
||||
await materialInstance.dispose();
|
||||
_materialInstances.remove(materialInstance);
|
||||
}
|
||||
|
||||
///
|
||||
///
|
||||
///
|
||||
Future<ThermionFFIMaterialInstance> createUnlitMaterialInstance() async {
|
||||
var instance = await withPointerCallback<TMaterialInstance>((cb) {
|
||||
var instancePtr = await withPointerCallback<TMaterialInstance>((cb) {
|
||||
SceneManager_createUnlitMaterialInstanceRenderThread(_sceneManager!, cb);
|
||||
});
|
||||
if (instance == nullptr) {
|
||||
throw Exception("Failed to create material instance");
|
||||
}
|
||||
return ThermionFFIMaterialInstance(instance);
|
||||
final instance = ThermionFFIMaterialInstance(instancePtr, _sceneManager!);
|
||||
_materialInstances.add(instance);
|
||||
return instance;
|
||||
}
|
||||
|
||||
///
|
||||
@@ -1910,14 +1912,13 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
///
|
||||
Future<ThermionFFIMaterialInstance>
|
||||
createUnlitFixedSizeMaterialInstance() async {
|
||||
var instance = await withPointerCallback<TMaterialInstance>((cb) {
|
||||
var instancePtr = await withPointerCallback<TMaterialInstance>((cb) {
|
||||
SceneManager_createUnlitFixedSizeMaterialInstanceRenderThread(
|
||||
_sceneManager!, cb);
|
||||
});
|
||||
if (instance == nullptr) {
|
||||
throw Exception("Failed to create material instance");
|
||||
}
|
||||
return ThermionFFIMaterialInstance(instance);
|
||||
final instance = ThermionFFIMaterialInstance(instancePtr, _sceneManager!);
|
||||
_materialInstances.add(instance);
|
||||
return instance;
|
||||
}
|
||||
|
||||
///
|
||||
@@ -1925,12 +1926,11 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
///
|
||||
Future<MaterialInstance> getMaterialInstanceAt(
|
||||
ThermionEntity entity, int index) async {
|
||||
final instance = RenderableManager_getMaterialInstanceAt(
|
||||
final instancePtr = RenderableManager_getMaterialInstanceAt(
|
||||
_renderableManager!, entity, index);
|
||||
if (instance == nullptr) {
|
||||
throw Exception("Failed to get material instance");
|
||||
}
|
||||
return ThermionFFIMaterialInstance(instance);
|
||||
|
||||
final instance = ThermionFFIMaterialInstance(instancePtr, _sceneManager!);
|
||||
return instance;
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -2036,8 +2036,8 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
SceneManager_getOverlayEntityCount(_sceneManager!);
|
||||
final overlayEntities = List<ThermionEntity>.generate(overlayEntityCount,
|
||||
(i) => SceneManager_getOverlayEntityAt(_sceneManager!, i)).toSet();
|
||||
return FFIGizmo(
|
||||
view, gizmo.cast<TSceneAsset>(), _sceneManager!, _engine!, nullptr, overlayEntities);
|
||||
return FFIGizmo(view, gizmo.cast<TSceneAsset>(), _sceneManager!, _engine!,
|
||||
nullptr, overlayEntities);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ enum StencilFace {
|
||||
BACK,
|
||||
|
||||
/// Both front and back faces
|
||||
FRONT_AND_BACK
|
||||
FRONT_AND_BACK
|
||||
}
|
||||
|
||||
enum AlphaMode { OPAQUE, MASK, BLEND }
|
||||
@@ -109,4 +109,5 @@ abstract class MaterialInstance {
|
||||
|
||||
Future setStencilReadMask(int mask);
|
||||
Future setStencilWriteMask(int mask);
|
||||
|
||||
}
|
||||
|
||||
@@ -792,28 +792,28 @@ abstract class ThermionViewer {
|
||||
AlphaMode alphaMode = AlphaMode.OPAQUE,
|
||||
bool enableDiagnostics = false,
|
||||
bool hasMetallicRoughnessTexture = false,
|
||||
int metallicRoughnessUV = 0,
|
||||
int baseColorUV = 0,
|
||||
int metallicRoughnessUV = -1,
|
||||
int baseColorUV = -1,
|
||||
bool hasClearCoatTexture = false,
|
||||
int clearCoatUV = 0,
|
||||
int clearCoatUV = -1,
|
||||
bool hasClearCoatRoughnessTexture = false,
|
||||
int clearCoatRoughnessUV = 0,
|
||||
int clearCoatRoughnessUV = -1,
|
||||
bool hasClearCoatNormalTexture = false,
|
||||
int clearCoatNormalUV = 0,
|
||||
int clearCoatNormalUV = -1,
|
||||
bool hasClearCoat = false,
|
||||
bool hasTransmission = false,
|
||||
bool hasTextureTransforms = false,
|
||||
int emissiveUV = 0,
|
||||
int aoUV = 0,
|
||||
int normalUV = 0,
|
||||
int emissiveUV = -1,
|
||||
int aoUV = -1,
|
||||
int normalUV = -1,
|
||||
bool hasTransmissionTexture = false,
|
||||
int transmissionUV = 0,
|
||||
int transmissionUV = -1,
|
||||
bool hasSheenColorTexture = false,
|
||||
int sheenColorUV = 0,
|
||||
int sheenColorUV = -1,
|
||||
bool hasSheenRoughnessTexture = false,
|
||||
int sheenRoughnessUV = 0,
|
||||
int sheenRoughnessUV = -1,
|
||||
bool hasVolumeThicknessTexture = false,
|
||||
int volumeThicknessUV = 0,
|
||||
int volumeThicknessUV = -1,
|
||||
bool hasSheen = false,
|
||||
bool hasIOR = false,
|
||||
bool hasVolume = false,
|
||||
|
||||
@@ -41,9 +41,6 @@
|
||||
#include "scene/GeometrySceneAssetBuilder.hpp"
|
||||
#include "UnprojectTexture.hpp"
|
||||
|
||||
|
||||
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include "material/image.h"
|
||||
@@ -130,11 +127,12 @@ namespace thermion
|
||||
_engine->getEntityManager().destroy(entity);
|
||||
}
|
||||
|
||||
destroyAll();
|
||||
|
||||
_engine->destroy(_unlitFixedSizeMaterial);
|
||||
_cameras.clear();
|
||||
|
||||
_gridOverlay->destroy();
|
||||
destroyAll();
|
||||
|
||||
_gltfResourceLoader->asyncCancelLoad();
|
||||
_ubershaderProvider->destroyMaterials();
|
||||
@@ -153,7 +151,7 @@ namespace thermion
|
||||
Gizmo *SceneManager::createGizmo(View *view, Scene *scene)
|
||||
{
|
||||
auto gizmo = std::make_unique<Gizmo>(_engine, view, scene, _unlitFixedSizeMaterial);
|
||||
auto *raw =gizmo.get();
|
||||
auto *raw = gizmo.get();
|
||||
_sceneAssets.push_back(std::move(gizmo));
|
||||
return raw;
|
||||
}
|
||||
@@ -682,7 +680,6 @@ namespace thermion
|
||||
math::float4 entityPlaneInClipSpace = Camera::inverseProjection(camera.getProjectionMatrix()) * ndcEntityPlanePos;
|
||||
auto entityPlaneInCameraSpace = entityPlaneInClipSpace / entityPlaneInClipSpace.w;
|
||||
auto entityPlaneInWorldSpace = camera.getModelMatrix() * entityPlaneInCameraSpace;
|
||||
|
||||
}
|
||||
|
||||
void SceneManager::queueTransformUpdates(EntityId *entities, math::mat4 *transforms, int numEntities)
|
||||
|
||||
@@ -13,16 +13,30 @@ import 'helpers.dart';
|
||||
void main() async {
|
||||
final testHelper = TestHelper("geometry");
|
||||
group("custom geometry", () {
|
||||
test('create cube', () async {
|
||||
test('create cube (no normals/uvs)', () async {
|
||||
await testHelper.withViewer((viewer) async {
|
||||
final cube = await viewer
|
||||
.createGeometry(GeometryHelper.cube(normals: false, uvs: false));
|
||||
await testHelper.capture(viewer, "geometry_add_cube");
|
||||
await testHelper.capture(viewer, "geometry_cube_no_normals_uvs");
|
||||
await viewer.removeEntity(cube);
|
||||
await testHelper.capture(viewer, "geometry_remove_cube");
|
||||
});
|
||||
});
|
||||
|
||||
test('create cube with unlit ubershader material (no normals/uvs)',
|
||||
() async {
|
||||
await testHelper.withViewer((viewer) async {
|
||||
final materialInstance =
|
||||
await viewer.createUbershaderMaterialInstance(unlit: true);
|
||||
await materialInstance.setParameterFloat4(
|
||||
"baseColorFactor", 1.0, 0.0, 0.0, 1.0);
|
||||
final cube = await viewer.createGeometry(
|
||||
GeometryHelper.cube(normals: false, uvs: false),
|
||||
materialInstances: [materialInstance]);
|
||||
await testHelper.capture(viewer, "geometry_cube_ubershader");
|
||||
});
|
||||
});
|
||||
|
||||
test('create cube (with normals)', () async {
|
||||
var viewer = await testHelper.createViewer();
|
||||
await viewer
|
||||
@@ -30,6 +44,36 @@ void main() async {
|
||||
await testHelper.capture(viewer, "geometry_cube_with_normals");
|
||||
});
|
||||
|
||||
test('create cube with lit ubershader material (normals/ no uvs)',
|
||||
() async {
|
||||
await testHelper.withViewer((viewer) async {
|
||||
final materialInstance =
|
||||
await viewer.createUbershaderMaterialInstance(
|
||||
unlit: false,
|
||||
alphaMode: AlphaMode.BLEND,
|
||||
hasVertexColors:false);
|
||||
await materialInstance.setParameterFloat4(
|
||||
"baseColorFactor", 1.0, 0.0, 0.0, 1.0);
|
||||
final cube = await viewer.createGeometry(
|
||||
GeometryHelper.cube(normals: true, uvs: false),
|
||||
materialInstances: [materialInstance]
|
||||
);
|
||||
|
||||
await viewer.addDirectLight(DirectLight.sun(
|
||||
intensity: 100000,
|
||||
castShadows: false,
|
||||
direction: Vector3(0,-0.5,-1)));
|
||||
// await viewer.addDirectLight(DirectLight.spot(
|
||||
// intensity: 1000000,
|
||||
// position: Vector3(0,3,3),
|
||||
// direction: Vector3(0,-1.5,-1),
|
||||
// falloffRadius: 10));
|
||||
await materialInstance.setParameterFloat4(
|
||||
"baseColorFactor", 1.0, 0.0, 0.0, 1.0);
|
||||
await testHelper.capture(viewer, "geometry_cube_lit_ubershader");
|
||||
});
|
||||
});
|
||||
|
||||
test('create instance', () async {
|
||||
await testHelper.withViewer((viewer) async {
|
||||
final cube = await viewer
|
||||
|
||||
Reference in New Issue
Block a user