diff --git a/thermion_dart/lib/thermion_dart/compatibility/native/thermion_dart.g.dart b/thermion_dart/lib/thermion_dart/compatibility/native/thermion_dart.g.dart index d2b40eaf..b2822241 100644 --- a/thermion_dart/lib/thermion_dart/compatibility/native/thermion_dart.g.dart +++ b/thermion_dart/lib/thermion_dart/compatibility/native/thermion_dart.g.dart @@ -796,6 +796,25 @@ external void set_post_processing( bool enabled, ); +@ffi.Native, ffi.Bool)>() +external void set_shadows_enabled( + ffi.Pointer viewer, + bool enabled, +); + +@ffi.Native, ffi.Int)>() +external void set_shadow_type( + ffi.Pointer viewer, + int shadowType, +); + +@ffi.Native, ffi.Float, ffi.Float)>() +external void set_soft_shadow_options( + ffi.Pointer viewer, + double penumbraScale, + double penumbraRatioScale, +); + @ffi.Native< ffi.Void Function(ffi.Pointer, ffi.Bool, ffi.Bool, ffi.Bool)>() external void set_antialiasing( diff --git a/thermion_dart/lib/thermion_dart/thermion_viewer.dart b/thermion_dart/lib/thermion_dart/thermion_viewer.dart index 332f5a83..6f622bd3 100644 --- a/thermion_dart/lib/thermion_dart/thermion_viewer.dart +++ b/thermion_dart/lib/thermion_dart/thermion_viewer.dart @@ -19,6 +19,13 @@ enum LightType { SPOT, } +enum ShadowType { + PCF, //!< percentage-closer filtered shadows (default) + VSM, //!< variance shadows + DPCF, //!< PCF with contact hardening simulation + PCSS, //!< PCF with soft shadows and contact hardening +} + // copied from filament/backened/DriverEnums.h enum PrimitiveType { // don't change the enums values (made to match GL) @@ -562,10 +569,25 @@ abstract class ThermionViewer { {bool relative = false}); /// - /// Enable/disable postprocessing. + /// Enable/disable postprocessing (disabled by default). /// Future setPostProcessing(bool enabled); + /// + /// Enable/disable shadows (disabled by default). + /// + Future setShadowsEnabled(bool enabled); + + /// + /// Set shadow type. + /// + Future setShadowType(ShadowType shadowType); + + /// + /// Set soft shadow options (ShadowType DPCF and PCSS) + /// + Future setSoftShadowOptions(double penumbraScale, double penumbraRatioScale); + /// /// Set antialiasing options. /// @@ -707,6 +729,7 @@ abstract class ThermionViewer { /// Register a callback to be invoked when this viewer is disposed. /// void onDispose(Future Function() callback); + } abstract class AbstractGizmo { diff --git a/thermion_dart/lib/thermion_dart/thermion_viewer_ffi.dart b/thermion_dart/lib/thermion_dart/thermion_viewer_ffi.dart index ff28fe0e..8aecbc0c 100644 --- a/thermion_dart/lib/thermion_dart/thermion_viewer_ffi.dart +++ b/thermion_dart/lib/thermion_dart/thermion_viewer_ffi.dart @@ -198,6 +198,7 @@ class ThermionViewerFFI extends ThermionViewer { await callback.call(); } _onDispose.clear(); + } /// @@ -1063,6 +1064,29 @@ class ThermionViewerFFI extends ThermionViewer { set_post_processing_ffi(_viewer!, enabled); } + /// + /// + /// + @override + Future setShadowsEnabled(bool enabled) async { + set_shadows_enabled(_viewer!, enabled); + } + + /// + /// + /// + Future setShadowType(ShadowType shadowType) async { + set_shadow_type(_viewer!, shadowType.index); + } + + /// + /// + /// + Future setSoftShadowOptions( + double penumbraScale, double penumbraRatioScale) async { + set_soft_shadow_options(_viewer!, penumbraScale, penumbraRatioScale); + } + /// /// /// @@ -1564,8 +1588,9 @@ class ThermionViewerFFI extends ThermionViewer { // ignore: sdk_version_since if (callback != null) { - var ptr = NativeCallable< - Void Function(Int entityId1, Int entityId2)>.listener(callback); + var ptr = + NativeCallable.listener( + callback); add_collision_component( _sceneManager!, entity, ptr.nativeFunction, affectsTransform); _collisions[entity] = ptr; diff --git a/thermion_dart/lib/thermion_dart/thermion_viewer_stub.dart b/thermion_dart/lib/thermion_dart/thermion_viewer_stub.dart index 2fff9d97..cde3d073 100644 --- a/thermion_dart/lib/thermion_dart/thermion_viewer_stub.dart +++ b/thermion_dart/lib/thermion_dart/thermion_viewer_stub.dart @@ -726,4 +726,22 @@ class ThermionViewerStub extends ThermionViewer { // TODO: implement zoomUpdate throw UnimplementedError(); } + + @override + Future setShadowType(ShadowType shadowType) { + // TODO: implement setShadowType + throw UnimplementedError(); + } + + @override + Future setShadowsEnabled(bool enabled) { + // TODO: implement setShadowsEnabled + throw UnimplementedError(); + } + + @override + Future setSoftShadowOptions(double penumbraScale, double penumbraRatioScale) { + // TODO: implement setSoftShadowOptions + throw UnimplementedError(); + } } diff --git a/thermion_dart/native/include/FilamentViewer.hpp b/thermion_dart/native/include/FilamentViewer.hpp index 32f59744..371d227e 100644 --- a/thermion_dart/native/include/FilamentViewer.hpp +++ b/thermion_dart/native/include/FilamentViewer.hpp @@ -153,6 +153,9 @@ namespace thermion_filament void setAntiAliasing(bool msaaEnabled, bool fxaaEnabled, bool taaEnabled); void setDepthOfField(); + void setShadowsEnabled(bool enabled); + void setShadowType(ShadowType shadowType); + void setSoftShadowOptions( float penumbraScale, float penumbraRatioScale); EntityId createGeometry(float *vertices, uint32_t numVertices, uint16_t *indices, uint32_t numIndices, filament::RenderableManager::PrimitiveType primitiveType = RenderableManager::PrimitiveType::TRIANGLES, const char *materialPath = nullptr); @@ -222,6 +225,7 @@ namespace thermion_filament void loadPngTexture(std::string path, ResourceBuffer data); void loadTextureFromPath(std::string path); void savePng(void *data, size_t size, int frameNumber); + void createBackgroundImage(); time_point_t _recordingStartTime = std::chrono::high_resolution_clock::now(); time_point_t _fpsCounterStartTime = std::chrono::high_resolution_clock::now(); @@ -229,6 +233,7 @@ namespace thermion_filament bool _recording = false; std::string _recordingOutputDirectory = std::string("/tmp"); std::mutex _recordingMutex; + std::mutex _imageMutex; double _cumulativeAnimationUpdateTime = 0; int _frameCount = 0; int _skippedFrames = 0; diff --git a/thermion_dart/native/include/ThermionDartApi.h b/thermion_dart/native/include/ThermionDartApi.h index 28af7795..041d342e 100644 --- a/thermion_dart/native/include/ThermionDartApi.h +++ b/thermion_dart/native/include/ThermionDartApi.h @@ -216,6 +216,9 @@ extern "C" EMSCRIPTEN_KEEPALIVE int hide_mesh(void *sceneManager, EntityId entity, const char *meshName); EMSCRIPTEN_KEEPALIVE int reveal_mesh(void *sceneManager, EntityId entity, const char *meshName); EMSCRIPTEN_KEEPALIVE void set_post_processing(void *const viewer, bool enabled); + EMSCRIPTEN_KEEPALIVE void set_shadows_enabled(void *const viewer, bool enabled); + EMSCRIPTEN_KEEPALIVE void set_shadow_type(void *const viewer, int shadowType); + EMSCRIPTEN_KEEPALIVE void set_soft_shadow_options(void *const viewer, float penumbraScale, float penumbraRatioScale); EMSCRIPTEN_KEEPALIVE void set_antialiasing(void *const viewer, bool msaa, bool fxaa, bool taa); EMSCRIPTEN_KEEPALIVE void filament_pick(void *const viewer, int x, int y, void (*callback)(EntityId entityId, int x, int y)); EMSCRIPTEN_KEEPALIVE const char *get_name_for_entity(void *const sceneManager, const EntityId entityId); diff --git a/thermion_dart/native/src/FilamentViewer.cpp b/thermion_dart/native/src/FilamentViewer.cpp index fbc091c0..0fd27b50 100644 --- a/thermion_dart/native/src/FilamentViewer.cpp +++ b/thermion_dart/native/src/FilamentViewer.cpp @@ -214,60 +214,6 @@ namespace thermion_filament Log("Created scene maager"); - _dummyImageTexture = Texture::Builder() - .width(1) - .height(1) - .levels(0x01) - .format(Texture::InternalFormat::RGB16F) - .sampler(Texture::Sampler::SAMPLER_2D) - .build(*_engine); - try - { - _imageMaterial = - Material::Builder() - .package(IMAGE_IMAGE_DATA, IMAGE_IMAGE_SIZE) - .build(*_engine); - _imageMaterial->setDefaultParameter("showImage", 0); - _imageMaterial->setDefaultParameter("backgroundColor", RgbaType::sRGB, float4(1.0f, 1.0f, 1.0f, 0.0f)); - _imageMaterial->setDefaultParameter("image", _dummyImageTexture, _imageSampler); - } - catch (...) - { - Log("Failed to load background image material provider"); - std::rethrow_exception(std::current_exception()); - } - _imageScale = mat4f{1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}; - - _imageMaterial->setDefaultParameter("transform", _imageScale); - - _imageVb = VertexBuffer::Builder() - .vertexCount(3) - .bufferCount(1) - .attribute(VertexAttribute::POSITION, 0, - VertexBuffer::AttributeType::FLOAT4, 0) - .build(*_engine); - - _imageVb->setBufferAt( - *_engine, 0, - {sFullScreenTriangleVertices, sizeof(sFullScreenTriangleVertices)}); - - _imageIb = IndexBuffer::Builder() - .indexCount(3) - .bufferType(IndexBuffer::IndexType::USHORT) - .build(*_engine); - - _imageIb->setBuffer(*_engine, {sFullScreenTriangleIndices, - sizeof(sFullScreenTriangleIndices)}); - - _imageEntity = em.create(); - RenderableManager::Builder(1) - .boundingBox({{}, {1.0f, 1.0f, 1.0f}}) - .material(0, _imageMaterial->getDefaultInstance()) - .geometry(0, RenderableManager::PrimitiveType::TRIANGLES, _imageVb, - _imageIb, 0, 3) - .culling(false) - .build(*_engine, _imageEntity); - _scene->addEntity(_imageEntity); } void FilamentViewer::setAntiAliasing(bool msaa, bool fxaa, bool taa) @@ -287,6 +233,24 @@ namespace thermion_filament _view->setPostProcessingEnabled(enabled); } + void FilamentViewer::setShadowsEnabled(bool enabled) + { + _view->setShadowingEnabled(enabled); + } + + void FilamentViewer::setShadowType(ShadowType shadowType) + { + _view->setShadowType(shadowType); + } + + void FilamentViewer::setSoftShadowOptions(float penumbraScale, float penumbraRatioScale) { + SoftShadowOptions opts; + opts.penumbraRatioScale = penumbraRatioScale; + opts.penumbraScale = penumbraScale; + _view->setSoftShadowOptions(opts); + } + + void FilamentViewer::setBloom(float strength) { #ifndef __EMSCRIPTEN__ @@ -541,14 +505,81 @@ namespace thermion_filament void FilamentViewer::setBackgroundColor(const float r, const float g, const float b, const float a) { - // Log("Setting background color to rgba(%f,%f,%f,%f)", r, g, b, a); + std::lock_guard lock(_imageMutex); + + if(_imageEntity.isNull()) { + createBackgroundImage(); + } _imageMaterial->setDefaultParameter("showImage", 0); _imageMaterial->setDefaultParameter("backgroundColor", RgbaType::sRGB, float4(r, g, b, a)); _imageMaterial->setDefaultParameter("transform", _imageScale); } + void FilamentViewer::createBackgroundImage() { + + _dummyImageTexture = Texture::Builder() + .width(1) + .height(1) + .levels(0x01) + .format(Texture::InternalFormat::RGB16F) + .sampler(Texture::Sampler::SAMPLER_2D) + .build(*_engine); + try + { + _imageMaterial = + Material::Builder() + .package(IMAGE_IMAGE_DATA, IMAGE_IMAGE_SIZE) + .build(*_engine); + _imageMaterial->setDefaultParameter("showImage", 0); + _imageMaterial->setDefaultParameter("backgroundColor", RgbaType::sRGB, float4(1.0f, 1.0f, 1.0f, 0.0f)); + _imageMaterial->setDefaultParameter("image", _dummyImageTexture, _imageSampler); + } + catch (...) + { + Log("Failed to load background image material provider"); + std::rethrow_exception(std::current_exception()); + } + _imageScale = mat4f{1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}; + + _imageMaterial->setDefaultParameter("transform", _imageScale); + + _imageVb = VertexBuffer::Builder() + .vertexCount(3) + .bufferCount(1) + .attribute(VertexAttribute::POSITION, 0, + VertexBuffer::AttributeType::FLOAT4, 0) + .build(*_engine); + + _imageVb->setBufferAt( + *_engine, 0, + {sFullScreenTriangleVertices, sizeof(sFullScreenTriangleVertices)}); + + _imageIb = IndexBuffer::Builder() + .indexCount(3) + .bufferType(IndexBuffer::IndexType::USHORT) + .build(*_engine); + + _imageIb->setBuffer(*_engine, {sFullScreenTriangleIndices, + sizeof(sFullScreenTriangleIndices)}); + auto & em = EntityManager::get(); + _imageEntity = em.create(); + RenderableManager::Builder(1) + .boundingBox({{}, {1.0f, 1.0f, 1.0f}}) + .material(0, _imageMaterial->getDefaultInstance()) + .geometry(0, RenderableManager::PrimitiveType::TRIANGLES, _imageVb, + _imageIb, 0, 3) + .culling(false) + .build(*_engine, _imageEntity); + _scene->addEntity(_imageEntity); + } + void FilamentViewer::clearBackgroundImage() { + std::lock_guard lock(_imageMutex); + + if(_imageEntity.isNull()) { + createBackgroundImage(); + } _imageMaterial->setDefaultParameter("image", _dummyImageTexture, _imageSampler); _imageMaterial->setDefaultParameter("showImage", 0); if (_imageTexture) @@ -562,6 +593,12 @@ namespace thermion_filament void FilamentViewer::setBackgroundImage(const char *resourcePath, bool fillHeight) { + std::lock_guard lock(_imageMutex); + + if(_imageEntity.isNull()) { + createBackgroundImage(); + } + string resourcePathString(resourcePath); Log("Setting background image to %s", resourcePath); @@ -602,6 +639,11 @@ namespace thermion_filament /// void FilamentViewer::setBackgroundImagePosition(float x, float y, bool clamp = false) { + std::lock_guard lock(_imageMutex); + + if(_imageEntity.isNull()) { + createBackgroundImage(); + } // to translate the background image, we apply a transform to the UV coordinates of the quad texture, not the quad itself (see image.mat). // this allows us to set a background colour for the quad when the texture has been translated outside the quad's bounds. @@ -682,11 +724,13 @@ namespace thermion_filament { clearLights(); destroySwapChain(); - _engine->destroy(_imageEntity); - _engine->destroy(_imageTexture); - _engine->destroy(_imageVb); - _engine->destroy(_imageIb); - _engine->destroy(_imageMaterial); + if(!_imageEntity.isNull()) { + _engine->destroy(_imageEntity); + _engine->destroy(_imageTexture); + _engine->destroy(_imageVb); + _engine->destroy(_imageIb); + _engine->destroy(_imageMaterial); + } delete _sceneManager; _engine->destroyCameraComponent(_mainCamera->getEntity()); _mainCamera = nullptr; diff --git a/thermion_dart/native/src/ThermionDartApi.cpp b/thermion_dart/native/src/ThermionDartApi.cpp index bee3ab48..349adfe2 100644 --- a/thermion_dart/native/src/ThermionDartApi.cpp +++ b/thermion_dart/native/src/ThermionDartApi.cpp @@ -443,6 +443,21 @@ extern "C" ((FilamentViewer *)viewer)->setPostProcessing(enabled); } + EMSCRIPTEN_KEEPALIVE void set_shadows_enabled(void *const viewer, bool enabled) + { + ((FilamentViewer *)viewer)->setShadowsEnabled(enabled); + } + + EMSCRIPTEN_KEEPALIVE void set_shadow_type(void *const viewer, int shadowType) + { + ((FilamentViewer *)viewer)->setShadowType((ShadowType)shadowType); + } + + EMSCRIPTEN_KEEPALIVE void set_soft_shadow_options(void *const viewer, float penumbraScale, float penumbraRatioScale) + { + ((FilamentViewer *)viewer)->setSoftShadowOptions(penumbraScale, penumbraRatioScale); + } + EMSCRIPTEN_KEEPALIVE void set_antialiasing(void *const viewer, bool msaa, bool fxaa, bool taa) { ((FilamentViewer *)viewer)->setAntiAliasing(msaa, fxaa, taa);