move MaterialInstance methods to own class

This commit is contained in:
Nick Fisher
2024-09-20 18:18:08 +08:00
parent f6c91294aa
commit 7cb3080596
11 changed files with 128 additions and 86 deletions

View File

@@ -1211,15 +1211,6 @@ external void remove_stencil_highlight(
int entity,
);
@ffi.Native<
ffi.Pointer<TMaterialInstance> Function(
ffi.Pointer<ffi.Void>, EntityId, ffi.Int)>(isLeaf: true)
external ffi.Pointer<TMaterialInstance> get_material_instance_at(
ffi.Pointer<ffi.Void> sceneManager,
int entity,
int materialIndex,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<ffi.Void>, EntityId, ffi.Int,
ffi.Pointer<ffi.Char>, ffi.Float)>(isLeaf: true)
@@ -1311,6 +1302,29 @@ external void apply_texture_to_material(
int materialIndex,
);
@ffi.Native<
ffi.Pointer<TMaterialInstance> Function(
ffi.Pointer<ffi.Void>, EntityId, ffi.Int)>(isLeaf: true)
external ffi.Pointer<TMaterialInstance> get_material_instance_at(
ffi.Pointer<ffi.Void> sceneManager,
int entity,
int materialIndex,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TMaterialInstance>, ffi.Bool)>(
isLeaf: true)
external void MaterialInstance_setDepthWrite(
ffi.Pointer<TMaterialInstance> materialInstance,
bool enabled,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TMaterialInstance>, ffi.Bool)>(
isLeaf: true)
external void MaterialInstance_setDepthCulling(
ffi.Pointer<TMaterialInstance> materialInstance,
bool enabled,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<ffi.Void>,

View File

@@ -1982,15 +1982,6 @@ class ThermionViewerFFI extends ThermionViewer {
allocator.free(ptr);
}
///
///
///
Future setMaterialDepthWrite(
ThermionEntity entity, int materialIndex, bool enabled) {
set_material_depth_write(_sceneManager!, entity, materialIndex, enabled);
return Future.value();
}
Future<Uint8List> unproject(ThermionEntity entity, Uint8List input,
int inputWidth, int inputHeight, int outWidth, int outHeight) async {
final outPtr = Uint8List(outWidth * outHeight * 4);
@@ -2132,6 +2123,18 @@ class ThermionViewerFFI extends ThermionViewer {
allocator.free(ptr);
return Future.value();
}
///
///
///
Future<MaterialInstance?> getMaterialInstanceAt(
ThermionEntity entity, int index) async {
final instance = get_material_instance_at(_sceneManager!, entity, index);
if (instance == nullptr) {
return null;
}
return ThermionFFIMaterialInstance(instance);
}
}
class ThermionFFITexture extends ThermionTexture {
@@ -2144,4 +2147,14 @@ class ThermionFFIMaterialInstance extends MaterialInstance {
final Pointer<TMaterialInstance> _pointer;
ThermionFFIMaterialInstance(this._pointer);
@override
Future setDepthCullingEnabled(bool enabled) async {
MaterialInstance_setDepthCulling(this._pointer, enabled);
}
@override
Future setDepthWriteEnabled(bool enabled) async {
MaterialInstance_setDepthWrite(this._pointer, enabled);
}
}

View File

@@ -1,9 +1,6 @@
abstract class MaterialInstance {
Future setDepthWriteEnabled(bool enabled);
Future setDepthCullingEnabled(bool enabled);
}
enum AlphaMode {
OPAQUE,
MASK,
BLEND
}
enum AlphaMode { OPAQUE, MASK, BLEND }

View File

@@ -599,13 +599,6 @@ abstract class ThermionViewer {
Future setMaterialPropertyInt(
ThermionEntity entity, String propertyName, int materialIndex, int value);
///
/// Sets the depthWrite material instance at [materialIndex] for [entity] to [enabled].
/// [entity] must have a Renderable attached.
///
Future setMaterialDepthWrite(
ThermionEntity entity, int materialIndex, bool enabled);
///
/// Scale [entity] to fit within the unit cube.
///
@@ -858,7 +851,7 @@ abstract class ThermionViewer {
///
/// Assigns [entity] to visibility layer [layer].
///
///
Future setVisibilityLayer(ThermionEntity entity, int layer);
///
@@ -944,4 +937,10 @@ abstract class ThermionViewer {
///
///
Future<MaterialInstance> createUnlitMaterialInstance();
///
///
///
Future<MaterialInstance?> getMaterialInstanceAt(
ThermionEntity entity, int index);
}

View File

@@ -928,6 +928,30 @@ class ThermionViewerStub extends ThermionViewer {
// TODO: implement setMaterialPropertyInt
throw UnimplementedError();
}
@override
Future<MaterialInstance?> getMaterialInstanceAt(ThermionEntity entity, int index) {
// TODO: implement getMaterialInstanceAt
throw UnimplementedError();
}
@override
Future setLayerVisibility(int layer, bool visible) {
// TODO: implement setLayerVisibility
throw UnimplementedError();
}
@override
Future setMaterialDepthWrite(ThermionEntity entity, int materialIndex, bool enabled) {
// TODO: implement setMaterialDepthWrite
throw UnimplementedError();
}
@override
Future setVisibilityLayer(ThermionEntity entity, int layer) {
// TODO: implement setVisibilityLayer
throw UnimplementedError();
}
}

View File

@@ -2186,7 +2186,7 @@ class ThermionViewerWasm implements ThermionViewer {
@override
Future setLayerEnabled(int layer, bool enabled) async {
_module!.ccall(
"set_layer_enabled",
"set_layer_visibility",
"void",
[
"void*".toJS,

View File

@@ -287,7 +287,6 @@ namespace thermion_filament
void setMaterialProperty(EntityId entity, int materialIndex, const char* property, float value);
void setMaterialProperty(EntityId entity, int materialIndex, const char* property, int32_t value);
void setMaterialProperty(EntityId entityId, int materialIndex, const char* property, filament::math::float4& value);
void setMaterialDepthWrite(EntityId entityId, int materialIndex, bool enabled);
MaterialInstance* createUbershaderMaterialInstance(MaterialKey key);
void destroy(MaterialInstance* materialInstance);

View File

@@ -275,7 +275,6 @@ extern "C"
EMSCRIPTEN_KEEPALIVE void set_gizmo_visibility(void *const sceneManager, bool visible);
EMSCRIPTEN_KEEPALIVE void set_stencil_highlight(void *const sceneManager, EntityId entity, float r, float g, float b);
EMSCRIPTEN_KEEPALIVE void remove_stencil_highlight(void *const sceneManager, EntityId entity);
EMSCRIPTEN_KEEPALIVE TMaterialInstance* get_material_instance_at(void *const sceneManager, EntityId entity, int materialIndex);
EMSCRIPTEN_KEEPALIVE void set_material_property_float(void *const sceneManager, EntityId entity, int materialIndex, const char *property, float value);
EMSCRIPTEN_KEEPALIVE void set_material_property_int(void *const sceneManager, EntityId entity, int materialIndex, const char *property, int value);
EMSCRIPTEN_KEEPALIVE void set_material_property_float4(void *const sceneManager, EntityId entity, int materialIndex, const char *property, double4 value);
@@ -285,6 +284,12 @@ extern "C"
EMSCRIPTEN_KEEPALIVE void destroy_texture(void *const sceneManager, void *const texture);
EMSCRIPTEN_KEEPALIVE void apply_texture_to_material(void *const sceneManager, EntityId entity, void *const texture, const char *parameterName, int materialIndex);
EMSCRIPTEN_KEEPALIVE TMaterialInstance* get_material_instance_at(void *const sceneManager, EntityId entity, int materialIndex);
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setDepthWrite(TMaterialInstance* materialInstance, bool enabled);
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setDepthCulling(TMaterialInstance* materialInstance, bool enabled);
#ifdef __cplusplus
}
#endif

View File

@@ -2633,20 +2633,6 @@ EntityId SceneManager::createGeometry(
auto instance = _unlitMaterialProvider->createMaterialInstance(nullptr, &uvmap);
return instance;
}
void SceneManager::setMaterialDepthWrite(EntityId entityId, int materialIndex, bool enabled) {
auto entity = Entity::import(entityId);
const auto &rm = _engine->getRenderableManager();
auto renderableInstance = rm.getInstance(entity);
if (!renderableInstance.isValid())
{
Log("Error setting material property for entity %d: no renderable");
return;
}
auto materialInstance = rm.getMaterialInstanceAt(renderableInstance, materialIndex);
materialInstance->setDepthWrite(enabled);
}
} // namespace thermion_filament

View File

@@ -987,10 +987,6 @@ extern "C"
((SceneManager *)sceneManager)->setMaterialProperty(entity, materialIndex, property, filamentValue);
}
EMSCRIPTEN_KEEPALIVE void set_material_depth_write(void *const sceneManager, EntityId entity, int materialIndex, bool enabled) {
((SceneManager *)sceneManager)->setMaterialDepthWrite(entity, materialIndex, enabled);
}
EMSCRIPTEN_KEEPALIVE void unproject_texture(void *const viewer, EntityId entity, uint8_t* input, uint32_t inputWidth, uint32_t inputHeight, uint8_t *out, uint32_t outWidth, uint32_t outHeight)
{
((FilamentViewer *)viewer)->unprojectTexture(entity, input, inputWidth, inputHeight, out, outWidth, outHeight);
@@ -1054,4 +1050,11 @@ EMSCRIPTEN_KEEPALIVE TMaterialInstance *create_unlit_material_instance(void *con
EMSCRIPTEN_KEEPALIVE void destroy_material_instance(void *const sceneManager, TMaterialInstance *instance) {
((SceneManager *)sceneManager)->destroy(reinterpret_cast<MaterialInstance*>(instance));
}
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setDepthWrite(TMaterialInstance* materialInstance, bool enabled) {
reinterpret_cast<MaterialInstance*>(materialInstance)->setDepthWrite(enabled);
}
EMSCRIPTEN_KEEPALIVE void MaterialInstance_setDepthCulling(TMaterialInstance* materialInstance, bool enabled) {
reinterpret_cast<MaterialInstance*>(materialInstance)->setDepthCulling(enabled);
}
}

View File

@@ -440,6 +440,40 @@ void main() async {
});
});
group("MaterialInstance", () {
test('disable depth write', () async {
var viewer = await createViewer();
await viewer.setBackgroundColor(1.0, 0.0, 0.0, 1.0);
await viewer.setCameraPosition(0, 0, 6);
await viewer.addDirectLight(
DirectLight.sun(direction: Vector3(0, 0, -1)..normalize()));
final cube1 = await viewer.createGeometry(GeometryHelper.cube());
var materialInstance = await viewer.getMaterialInstanceAt(cube1, 0);
final cube2 = await viewer.createGeometry(GeometryHelper.cube());
await viewer.setMaterialPropertyFloat4(
cube2, "baseColorFactor", 0, 0, 1, 0, 1);
await viewer.setPosition(cube2, 1.0, 0.0, -1.0);
expect(materialInstance, isNotNull);
// with depth write enabled on both materials, cube2 renders behind the white cube
await _capture(viewer, "material_instance_depth_write_enabled");
// if we disable depth write on cube1, then cube2 will always appear in front
// (relying on insertion order)
materialInstance!.setDepthWriteEnabled(false);
await _capture(viewer, "material_instance_depth_write_disabled");
// set priority for the cube1 cube to 7 (render) last, cube1 renders in front
await viewer.setPriority(cube1, 7);
await _capture(viewer, "material_instance_depth_write_disabled_with_priority");
});
});
// test('create instance from glb when keepData is true', () async {
// var model = await viewer.loadGlb("$testDir/cube.glb", keepData: true);
// await viewer.transformToUnitCube(model);
@@ -547,38 +581,6 @@ void main() async {
await viewer.setMaterialPropertyFloat(cube, "roughnessFactor", 0, 0.0);
await _capture(viewer, "set_material_roughness_post");
});
test('enable/disable depth write for custom geometry', () async {
var viewer = await createViewer();
await viewer.setCameraPosition(0, 0, 6);
await viewer.setBackgroundColor(0.0, 0.0, 1.0, 1.0);
var light =
await viewer.addLight(LightType.SUN, 6500, 100000, 0, 0, 0, 0, 0, -1);
final cube1 = await viewer.createGeometry(GeometryHelper.cube());
await viewer.setMaterialPropertyFloat4(
cube1, "baseColorFactor", 0, 1.0, 1.0, 1.0, 1);
final cube2 = await viewer.createGeometry(GeometryHelper.cube());
await viewer.setPosition(cube2, 1.0, 0.0, -1.0);
await viewer.setMaterialPropertyFloat4(
cube2, "baseColorFactor", 0, 1.0, 0, 0, 1);
// with depth write enabled on both materials, the red cube will render behind the white cube
await viewer.setMaterialDepthWrite(cube1, 0, true);
await viewer.setMaterialDepthWrite(cube2, 0, true);
await _capture(viewer, "geometry_enable_depth_write");
// with depth write disabled on the first material, the red cube will render in front of the white cube
// (relying on insertion order)
await viewer.setMaterialDepthWrite(cube1, 0, false);
await _capture(viewer, "geometry_disable_depth_write_insertion_order");
// if we set priority for the black cube to 7 (render) last, red cube will render behind the white cube
await viewer.setPriority(cube1, 7);
await _capture(viewer, "geometry_disable_depth_write_priority");
});
});
group("transforms & parenting", () {