feat: expose setCastShadows/setReceiveShadows
This commit is contained in:
@@ -2502,7 +2502,6 @@ external bool RenderableManager_isRenderable(
|
|||||||
int entityId,
|
int entityId,
|
||||||
);
|
);
|
||||||
|
|
||||||
/// Checks if the given entity has a renderable component
|
|
||||||
@ffi.Native<ffi.Bool Function(ffi.Pointer<TRenderableManager>, EntityId)>(
|
@ffi.Native<ffi.Bool Function(ffi.Pointer<TRenderableManager>, EntityId)>(
|
||||||
isLeaf: true)
|
isLeaf: true)
|
||||||
external bool RenderableManager_hasComponent(
|
external bool RenderableManager_hasComponent(
|
||||||
@@ -2510,13 +2509,11 @@ external bool RenderableManager_hasComponent(
|
|||||||
int entityId,
|
int entityId,
|
||||||
);
|
);
|
||||||
|
|
||||||
/// Returns true if this manager has no components
|
|
||||||
@ffi.Native<ffi.Bool Function(ffi.Pointer<TRenderableManager>)>(isLeaf: true)
|
@ffi.Native<ffi.Bool Function(ffi.Pointer<TRenderableManager>)>(isLeaf: true)
|
||||||
external bool RenderableManager_empty(
|
external bool RenderableManager_empty(
|
||||||
ffi.Pointer<TRenderableManager> tRenderableManager,
|
ffi.Pointer<TRenderableManager> tRenderableManager,
|
||||||
);
|
);
|
||||||
|
|
||||||
/// Returns whether a light channel is enabled on a specified renderable
|
|
||||||
@ffi.Native<
|
@ffi.Native<
|
||||||
ffi.Bool Function(ffi.Pointer<TRenderableManager>, EntityId,
|
ffi.Bool Function(ffi.Pointer<TRenderableManager>, EntityId,
|
||||||
ffi.UnsignedInt)>(isLeaf: true)
|
ffi.UnsignedInt)>(isLeaf: true)
|
||||||
@@ -2526,7 +2523,6 @@ external bool RenderableManager_getLightChannel(
|
|||||||
int channel,
|
int channel,
|
||||||
);
|
);
|
||||||
|
|
||||||
/// Checks if the renderable can cast shadows
|
|
||||||
@ffi.Native<ffi.Bool Function(ffi.Pointer<TRenderableManager>, EntityId)>(
|
@ffi.Native<ffi.Bool Function(ffi.Pointer<TRenderableManager>, EntityId)>(
|
||||||
isLeaf: true)
|
isLeaf: true)
|
||||||
external bool RenderableManager_isShadowCaster(
|
external bool RenderableManager_isShadowCaster(
|
||||||
@@ -2534,7 +2530,24 @@ external bool RenderableManager_isShadowCaster(
|
|||||||
int entityId,
|
int entityId,
|
||||||
);
|
);
|
||||||
|
|
||||||
/// Checks if the renderable can receive shadows
|
@ffi.Native<
|
||||||
|
ffi.Void Function(
|
||||||
|
ffi.Pointer<TRenderableManager>, EntityId, ffi.Bool)>(isLeaf: true)
|
||||||
|
external void RenderableManager_setCastShadows(
|
||||||
|
ffi.Pointer<TRenderableManager> tRenderableManager,
|
||||||
|
int entityId,
|
||||||
|
bool castShadows,
|
||||||
|
);
|
||||||
|
|
||||||
|
@ffi.Native<
|
||||||
|
ffi.Void Function(
|
||||||
|
ffi.Pointer<TRenderableManager>, EntityId, ffi.Bool)>(isLeaf: true)
|
||||||
|
external void RenderableManager_setReceiveShadows(
|
||||||
|
ffi.Pointer<TRenderableManager> tRenderableManager,
|
||||||
|
int entityId,
|
||||||
|
bool receiveShadows,
|
||||||
|
);
|
||||||
|
|
||||||
@ffi.Native<ffi.Bool Function(ffi.Pointer<TRenderableManager>, EntityId)>(
|
@ffi.Native<ffi.Bool Function(ffi.Pointer<TRenderableManager>, EntityId)>(
|
||||||
isLeaf: true)
|
isLeaf: true)
|
||||||
external bool RenderableManager_isShadowReceiver(
|
external bool RenderableManager_isShadowReceiver(
|
||||||
@@ -2542,7 +2555,6 @@ external bool RenderableManager_isShadowReceiver(
|
|||||||
int entityId,
|
int entityId,
|
||||||
);
|
);
|
||||||
|
|
||||||
/// Returns whether large-scale fog is enabled for this renderable
|
|
||||||
@ffi.Native<ffi.Bool Function(ffi.Pointer<TRenderableManager>, EntityId)>(
|
@ffi.Native<ffi.Bool Function(ffi.Pointer<TRenderableManager>, EntityId)>(
|
||||||
isLeaf: true)
|
isLeaf: true)
|
||||||
external bool RenderableManager_getFogEnabled(
|
external bool RenderableManager_getFogEnabled(
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ class ThermionViewerFFI extends ThermionViewer {
|
|||||||
if (view == nullptr) {
|
if (view == nullptr) {
|
||||||
throw Exception("Failed to create view");
|
throw Exception("Failed to create view");
|
||||||
}
|
}
|
||||||
return FFIView(view, _viewer!,_engine!);
|
return FFIView(view, _viewer!, _engine!);
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -1678,9 +1678,6 @@ class ThermionViewerFFI extends ThermionViewer {
|
|||||||
throw Exception("Failed to create geometry");
|
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))} ");
|
|
||||||
|
|
||||||
var asset = FFIAsset(
|
var asset = FFIAsset(
|
||||||
assetPtr, _sceneManager!, _engine!, _unlitMaterialProvider!, this);
|
assetPtr, _sceneManager!, _engine!, _unlitMaterialProvider!, this);
|
||||||
|
|
||||||
@@ -2185,10 +2182,36 @@ class ThermionViewerFFI extends ThermionViewer {
|
|||||||
gizmoEntities.toSet()
|
gizmoEntities.toSet()
|
||||||
..add(SceneAsset_getEntity(gizmo.cast<TSceneAsset>())));
|
..add(SceneAsset_getEntity(gizmo.cast<TSceneAsset>())));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
///
|
||||||
|
///
|
||||||
|
Future setCastShadows(ThermionEntity entity, bool castShadows) async {
|
||||||
|
RenderableManager_setCastShadows(_renderableManager!, entity, castShadows);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
///
|
||||||
|
///
|
||||||
|
Future<bool> isCastShadowsEnabled(ThermionEntity entity) async {
|
||||||
|
return RenderableManager_isShadowCaster(_renderableManager!, entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
///
|
||||||
|
///
|
||||||
|
Future setReceiveShadows(ThermionEntity entity, bool receiveShadows) async {
|
||||||
|
RenderableManager_setReceiveShadows(_renderableManager!, entity, receiveShadows);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
///
|
||||||
|
///
|
||||||
|
Future<bool> isReceiveShadowsEnabled(ThermionEntity entity) async {
|
||||||
|
return RenderableManager_isShadowReceiver(_renderableManager!, entity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class FFISwapChain extends SwapChain {
|
class FFISwapChain extends SwapChain {
|
||||||
final Pointer<TSwapChain> swapChain;
|
final Pointer<TSwapChain> swapChain;
|
||||||
final Pointer<TViewer> viewer;
|
final Pointer<TViewer> viewer;
|
||||||
|
|||||||
@@ -918,4 +918,24 @@ abstract class ThermionViewer {
|
|||||||
/// Throws an exception if the index is out-of-bounds.
|
/// Throws an exception if the index is out-of-bounds.
|
||||||
///
|
///
|
||||||
Camera getCameraAt(int index);
|
Camera getCameraAt(int index);
|
||||||
|
|
||||||
|
///
|
||||||
|
///
|
||||||
|
///
|
||||||
|
Future setCastShadows(ThermionEntity entity, bool castShadows);
|
||||||
|
|
||||||
|
///
|
||||||
|
///
|
||||||
|
///
|
||||||
|
Future<bool> isCastShadowsEnabled(ThermionEntity entity);
|
||||||
|
|
||||||
|
///
|
||||||
|
///
|
||||||
|
///
|
||||||
|
Future setReceiveShadows(ThermionEntity entity, bool receiveShadows);
|
||||||
|
|
||||||
|
///
|
||||||
|
///
|
||||||
|
///
|
||||||
|
Future<bool> isReceiveShadowsEnabled(ThermionEntity entity);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,37 +12,13 @@ extern "C"
|
|||||||
EMSCRIPTEN_KEEPALIVE void RenderableManager_setPriority(TRenderableManager *tRenderableManager, EntityId entityId, int priority);
|
EMSCRIPTEN_KEEPALIVE void RenderableManager_setPriority(TRenderableManager *tRenderableManager, EntityId entityId, int priority);
|
||||||
EMSCRIPTEN_KEEPALIVE TMaterialInstance *RenderableManager_getMaterialInstanceAt(TRenderableManager *tRenderableManager, EntityId entityId, int primitiveIndex);
|
EMSCRIPTEN_KEEPALIVE TMaterialInstance *RenderableManager_getMaterialInstanceAt(TRenderableManager *tRenderableManager, EntityId entityId, int primitiveIndex);
|
||||||
EMSCRIPTEN_KEEPALIVE bool RenderableManager_isRenderable(TRenderableManager *tRenderableManager, EntityId entityId);
|
EMSCRIPTEN_KEEPALIVE bool RenderableManager_isRenderable(TRenderableManager *tRenderableManager, EntityId entityId);
|
||||||
|
|
||||||
// New boolean methods
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if the given entity has a renderable component
|
|
||||||
*/
|
|
||||||
EMSCRIPTEN_KEEPALIVE bool RenderableManager_hasComponent(TRenderableManager *tRenderableManager, EntityId entityId);
|
EMSCRIPTEN_KEEPALIVE bool RenderableManager_hasComponent(TRenderableManager *tRenderableManager, EntityId entityId);
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if this manager has no components
|
|
||||||
*/
|
|
||||||
EMSCRIPTEN_KEEPALIVE bool RenderableManager_empty(TRenderableManager *tRenderableManager);
|
EMSCRIPTEN_KEEPALIVE bool RenderableManager_empty(TRenderableManager *tRenderableManager);
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether a light channel is enabled on a specified renderable
|
|
||||||
*/
|
|
||||||
EMSCRIPTEN_KEEPALIVE bool RenderableManager_getLightChannel(TRenderableManager *tRenderableManager, EntityId entityId, unsigned int channel);
|
EMSCRIPTEN_KEEPALIVE bool RenderableManager_getLightChannel(TRenderableManager *tRenderableManager, EntityId entityId, unsigned int channel);
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if the renderable can cast shadows
|
|
||||||
*/
|
|
||||||
EMSCRIPTEN_KEEPALIVE bool RenderableManager_isShadowCaster(TRenderableManager *tRenderableManager, EntityId entityId);
|
EMSCRIPTEN_KEEPALIVE bool RenderableManager_isShadowCaster(TRenderableManager *tRenderableManager, EntityId entityId);
|
||||||
|
EMSCRIPTEN_KEEPALIVE void RenderableManager_setCastShadows(TRenderableManager *tRenderableManager, EntityId entityId, bool castShadows);
|
||||||
/**
|
EMSCRIPTEN_KEEPALIVE void RenderableManager_setReceiveShadows(TRenderableManager *tRenderableManager, EntityId entityId, bool receiveShadows);
|
||||||
* Checks if the renderable can receive shadows
|
|
||||||
*/
|
|
||||||
EMSCRIPTEN_KEEPALIVE bool RenderableManager_isShadowReceiver(TRenderableManager *tRenderableManager, EntityId entityId);
|
EMSCRIPTEN_KEEPALIVE bool RenderableManager_isShadowReceiver(TRenderableManager *tRenderableManager, EntityId entityId);
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether large-scale fog is enabled for this renderable
|
|
||||||
*/
|
|
||||||
EMSCRIPTEN_KEEPALIVE bool RenderableManager_getFogEnabled(TRenderableManager *tRenderableManager, EntityId entityId);
|
EMSCRIPTEN_KEEPALIVE bool RenderableManager_getFogEnabled(TRenderableManager *tRenderableManager, EntityId entityId);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
@@ -72,21 +72,45 @@ namespace thermion
|
|||||||
const auto &entity = utils::Entity::import(entityId);
|
const auto &entity = utils::Entity::import(entityId);
|
||||||
auto renderableInstance = renderableManager->getInstance(entity);
|
auto renderableInstance = renderableManager->getInstance(entity);
|
||||||
if (!renderableInstance.isValid()) {
|
if (!renderableInstance.isValid()) {
|
||||||
|
Log("Error: invalid renderable");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return renderableManager->isShadowCaster(renderableInstance);
|
return renderableManager->isShadowCaster(renderableInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EMSCRIPTEN_KEEPALIVE void RenderableManager_setCastShadows(TRenderableManager *tRenderableManager, EntityId entityId, bool enabled) {
|
||||||
|
auto *renderableManager = reinterpret_cast<filament::RenderableManager *>(tRenderableManager);
|
||||||
|
const auto &entity = utils::Entity::import(entityId);
|
||||||
|
auto renderableInstance = renderableManager->getInstance(entity);
|
||||||
|
if (!renderableInstance.isValid()) {
|
||||||
|
Log("Error: invalid renderable");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return renderableManager->setCastShadows(renderableInstance, enabled);
|
||||||
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE bool RenderableManager_isShadowReceiver(TRenderableManager *tRenderableManager, EntityId entityId) {
|
EMSCRIPTEN_KEEPALIVE bool RenderableManager_isShadowReceiver(TRenderableManager *tRenderableManager, EntityId entityId) {
|
||||||
auto *renderableManager = reinterpret_cast<filament::RenderableManager *>(tRenderableManager);
|
auto *renderableManager = reinterpret_cast<filament::RenderableManager *>(tRenderableManager);
|
||||||
const auto &entity = utils::Entity::import(entityId);
|
const auto &entity = utils::Entity::import(entityId);
|
||||||
auto renderableInstance = renderableManager->getInstance(entity);
|
auto renderableInstance = renderableManager->getInstance(entity);
|
||||||
if (!renderableInstance.isValid()) {
|
if (!renderableInstance.isValid()) {
|
||||||
|
Log("Error: invalid renderable");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return renderableManager->isShadowReceiver(renderableInstance);
|
return renderableManager->isShadowReceiver(renderableInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EMSCRIPTEN_KEEPALIVE void RenderableManager_setReceiveShadows(TRenderableManager *tRenderableManager, EntityId entityId, bool enabled) {
|
||||||
|
auto *renderableManager = reinterpret_cast<filament::RenderableManager *>(tRenderableManager);
|
||||||
|
const auto &entity = utils::Entity::import(entityId);
|
||||||
|
auto renderableInstance = renderableManager->getInstance(entity);
|
||||||
|
if (!renderableInstance.isValid()) {
|
||||||
|
Log("Error: invalid renderable");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return renderableManager->setReceiveShadows(renderableInstance, enabled);
|
||||||
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE bool RenderableManager_getFogEnabled(TRenderableManager *tRenderableManager, EntityId entityId) {
|
EMSCRIPTEN_KEEPALIVE bool RenderableManager_getFogEnabled(TRenderableManager *tRenderableManager, EntityId entityId) {
|
||||||
auto *renderableManager = reinterpret_cast<filament::RenderableManager *>(tRenderableManager);
|
auto *renderableManager = reinterpret_cast<filament::RenderableManager *>(tRenderableManager);
|
||||||
const auto &entity = utils::Entity::import(entityId);
|
const auto &entity = utils::Entity::import(entityId);
|
||||||
|
|||||||
@@ -387,7 +387,7 @@ void main() async {
|
|||||||
await viewer.loadIbl(
|
await viewer.loadIbl(
|
||||||
"file://${testHelper.testDir}/assets/default_env_ibl.ktx",
|
"file://${testHelper.testDir}/assets/default_env_ibl.ktx",
|
||||||
intensity: 1000);
|
intensity: 1000);
|
||||||
// await viewer.setShadowsEnabled(true);
|
|
||||||
await viewer.addDirectLight(DirectLight.sun(
|
await viewer.addDirectLight(DirectLight.sun(
|
||||||
intensity: 500000,
|
intensity: 500000,
|
||||||
castShadows: true,
|
castShadows: true,
|
||||||
|
|||||||
112
thermion_dart/test/shadow_tests.dart
Normal file
112
thermion_dart/test/shadow_tests.dart
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
import 'package:thermion_dart/thermion_dart.dart';
|
||||||
|
import 'package:test/test.dart';
|
||||||
|
import 'package:vector_math/vector_math_64.dart';
|
||||||
|
import 'helpers.dart';
|
||||||
|
|
||||||
|
void main() async {
|
||||||
|
final testHelper = TestHelper("material");
|
||||||
|
|
||||||
|
group("shadow tests", () {
|
||||||
|
test('enable/disable shadows', () async {
|
||||||
|
await testHelper.withViewer((viewer) async {
|
||||||
|
await viewer.setPostProcessing(true);
|
||||||
|
await viewer.setShadowsEnabled(true);
|
||||||
|
await viewer.setShadowType(ShadowType.PCF);
|
||||||
|
var materialInsance = await viewer.createUbershaderMaterialInstance();
|
||||||
|
await materialInsance.setParameterFloat4(
|
||||||
|
"baseColorFactor", 0.0, 1.0, 0.0, 1.0);
|
||||||
|
await viewer.addDirectLight(DirectLight.sun(
|
||||||
|
intensity: 50000,
|
||||||
|
castShadows: true,
|
||||||
|
direction: Vector3(1, -0.5, 0).normalized()));
|
||||||
|
|
||||||
|
final plane = await viewer.createGeometry(
|
||||||
|
GeometryHelper.plane(
|
||||||
|
normals: true, uvs: true, width: 10, height: 10),
|
||||||
|
materialInstances: [materialInsance]);
|
||||||
|
expect(await viewer.isCastShadowsEnabled(plane.entity), true);
|
||||||
|
expect(await viewer.isReceiveShadowsEnabled(plane.entity), true);
|
||||||
|
await viewer.createGeometry(
|
||||||
|
GeometryHelper.cube(
|
||||||
|
normals: true,
|
||||||
|
uvs: true,
|
||||||
|
),
|
||||||
|
materialInstances: [materialInsance]);
|
||||||
|
|
||||||
|
await testHelper.capture(viewer, "shadows_enabled");
|
||||||
|
|
||||||
|
await viewer.setShadowsEnabled(false);
|
||||||
|
|
||||||
|
await testHelper.capture(viewer, "shadows_disabled");
|
||||||
|
}, bg: kRed);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('enable/disable cast shadows', () async {
|
||||||
|
await testHelper.withViewer((viewer) async {
|
||||||
|
await viewer.setPostProcessing(true);
|
||||||
|
await viewer.setShadowsEnabled(true);
|
||||||
|
await viewer.setShadowType(ShadowType.PCF);
|
||||||
|
var materialInsance = await viewer.createUbershaderMaterialInstance();
|
||||||
|
await materialInsance.setParameterFloat4(
|
||||||
|
"baseColorFactor", 0.0, 1.0, 0.0, 1.0);
|
||||||
|
await viewer.addDirectLight(DirectLight.sun(
|
||||||
|
intensity: 50000,
|
||||||
|
castShadows: true,
|
||||||
|
direction: Vector3(1, -0.5, 0).normalized()));
|
||||||
|
|
||||||
|
final plane = await viewer.createGeometry(
|
||||||
|
GeometryHelper.plane(
|
||||||
|
normals: true, uvs: true, width: 10, height: 10),
|
||||||
|
materialInstances: [materialInsance]);
|
||||||
|
|
||||||
|
final cube = await viewer.createGeometry(
|
||||||
|
GeometryHelper.cube(
|
||||||
|
normals: true,
|
||||||
|
uvs: true,
|
||||||
|
),
|
||||||
|
materialInstances: [materialInsance]);
|
||||||
|
|
||||||
|
expect(await viewer.isCastShadowsEnabled(cube.entity), true);
|
||||||
|
await testHelper.capture(viewer, "cast_shadows_enabled");
|
||||||
|
|
||||||
|
await viewer.setCastShadows(cube.entity, false);
|
||||||
|
expect(await viewer.isCastShadowsEnabled(cube.entity), false);
|
||||||
|
await testHelper.capture(viewer, "cast_shadows_disabled");
|
||||||
|
}, bg: kRed);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('enable/disable receive shadows', () async {
|
||||||
|
await testHelper.withViewer((viewer) async {
|
||||||
|
await viewer.setPostProcessing(true);
|
||||||
|
await viewer.setShadowsEnabled(true);
|
||||||
|
await viewer.setShadowType(ShadowType.PCF);
|
||||||
|
var materialInsance = await viewer.createUbershaderMaterialInstance();
|
||||||
|
await materialInsance.setParameterFloat4(
|
||||||
|
"baseColorFactor", 0.0, 1.0, 0.0, 1.0);
|
||||||
|
await viewer.addDirectLight(DirectLight.sun(
|
||||||
|
intensity: 50000,
|
||||||
|
castShadows: true,
|
||||||
|
direction: Vector3(1, -0.5, 0).normalized()));
|
||||||
|
|
||||||
|
final plane = await viewer.createGeometry(
|
||||||
|
GeometryHelper.plane(
|
||||||
|
normals: true, uvs: true, width: 10, height: 10),
|
||||||
|
materialInstances: [materialInsance]);
|
||||||
|
|
||||||
|
final cube = await viewer.createGeometry(
|
||||||
|
GeometryHelper.cube(
|
||||||
|
normals: true,
|
||||||
|
uvs: true,
|
||||||
|
),
|
||||||
|
materialInstances: [materialInsance]);
|
||||||
|
|
||||||
|
expect(await viewer.isReceiveShadowsEnabled(plane.entity), true);
|
||||||
|
await testHelper.capture(viewer, "receive_shadows_enabled");
|
||||||
|
|
||||||
|
await viewer.setReceiveShadows(plane.entity, false);
|
||||||
|
expect(await viewer.isReceiveShadowsEnabled(plane.entity), false);
|
||||||
|
await testHelper.capture(viewer, "receive_shadows_disabled");
|
||||||
|
}, bg: kRed);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user