move set/remove stencilHighlight to View and implement via OverlayManager

This commit is contained in:
Nick Fisher
2025-07-01 10:13:47 +08:00
parent 96ef070be7
commit 0f9d2492e6
11 changed files with 382 additions and 140 deletions

View File

@@ -3,7 +3,7 @@
#include <chrono>
#include <mutex>
#include <vector>
#include <utility> // for std::pair
#include <utility>
#include <filament/Renderer.h>
#include <filament/SwapChain.h>
@@ -21,13 +21,18 @@
#include <filament/VertexBuffer.h>
#include "scene/AnimationManager.hpp"
#include "components/OverlayComponentManager.hpp"
namespace thermion
{
class RenderTicker
{
using ViewAttachment = std::pair<filament::SwapChain*, std::vector<filament::View*>>;
public:
RenderTicker(
filament::Engine *engine,
@@ -54,14 +59,21 @@ namespace thermion
/// @param animationManager
void removeAnimationManager(AnimationManager* animationManager);
/// @brief
/// @param overlayComponentManager
void addOverlayManager(OverlayComponentManager *overlayComponentManager) {
mOverlayComponentManager = overlayComponentManager;
}
private:
std::mutex mMutex;
filament::Engine *mEngine = nullptr;
filament::Renderer *mRenderer = nullptr;
filament::Engine *mEngine = std::nullptr_t();
filament::Renderer *mRenderer = std::nullptr_t();
std::vector<AnimationManager*> mAnimationManagers;
std::vector<std::pair<filament::SwapChain*, std::vector<filament::View*>>> mRenderable;
OverlayComponentManager *mOverlayComponentManager = std::nullptr_t();
std::vector<ViewAttachment> mRenderable;
std::chrono::high_resolution_clock::time_point mLastRender;
};
}

View File

@@ -0,0 +1,34 @@
#pragma once
#include "APIExport.h"
#include "APIBoundaryTypes.h"
#ifdef __cplusplus
extern "C"
{
#endif
EMSCRIPTEN_KEEPALIVE TOverlayManager *OverlayManager_create(
TEngine *tEngine,
TRenderer *tRenderer,
TView *tView,
TScene *tScene,
TRenderTarget *tRenderTarget
);
EMSCRIPTEN_KEEPALIVE void OverlayManager_addComponent(
TOverlayManager *tOverlayManager,
EntityId entityId,
TMaterialInstance *tMaterialInstance
);
EMSCRIPTEN_KEEPALIVE void OverlayManager_removeComponent(
TOverlayManager *tOverlayManager,
EntityId entityId
);
#ifdef __cplusplus
}
#endif

View File

@@ -92,6 +92,7 @@ EMSCRIPTEN_KEEPALIVE void View_setFogOptions(TView *tView, TFogOptions tFogOptio
typedef void (*PickCallback)(uint32_t requestId, EntityId entityId, float depth, float fragX, float fragY, float fragZ);
EMSCRIPTEN_KEEPALIVE void View_pick(TView* tView, uint32_t requestId, uint32_t x, uint32_t y, PickCallback callback);
EMSCRIPTEN_KEEPALIVE void View_setName(TView* tView, const char *name);
#ifdef __cplusplus
}

View File

@@ -0,0 +1,145 @@
#pragma once
#include <map>
#include <vector>
#include <math/mat4.h>
#include <filament/Engine.h>
#include <filament/Material.h>
#include <filament/MaterialInstance.h>
#include <filament/Renderer.h>
#include <filament/RenderTarget.h>
#include <filament/RenderableManager.h>
#include <filament/Scene.h>
#include <filament/Texture.h>
#include <filament/TextureSampler.h>
#include <filament/TransformManager.h>
#include <filament/View.h>
#include <utils/SingleInstanceComponentManager.h>
#include "c_api/APIBoundaryTypes.h"
#include "material/linear_depth.h"
namespace thermion
{
/// @brief
class OverlayComponentManager : public utils::SingleInstanceComponentManager<filament::MaterialInstance *>
{
public:
OverlayComponentManager(
filament::Engine *engine,
filament::View *view,
filament::Scene *scene,
filament::RenderTarget *renderTarget,
filament::Renderer *renderer) : mEngine(engine), mView(view), mScene(scene), mRenderTarget(renderTarget), mRenderer(renderer)
{
mDepthMaterial = filament::Material::Builder()
.package(LINEAR_DEPTH_LINEAR_DEPTH_DATA, LINEAR_DEPTH_LINEAR_DEPTH_SIZE)
.build(*engine);
mDepthMaterialInstance = mDepthMaterial->createInstance();
}
void addOverlayComponent(utils::Entity target, filament::MaterialInstance *materialInstance)
{
auto *color = mRenderTarget->getTexture(filament::RenderTarget::AttachmentPoint::COLOR);
materialInstance->setParameter("depth", color, mDepthSampler);
if (!hasComponent(target))
{
utils::EntityInstanceBase::Type componentInstance = addComponent(target);
this->elementAt<0>(componentInstance) = materialInstance;
}
mScene->addEntity(target);
}
void removeOverlayComponent(utils::Entity target)
{
if (hasComponent(target))
{
removeComponent(target);
}
mScene->remove(target);
}
void update()
{
if (!mView || !mScene || getComponentCount() == 0)
{
return;
}
auto &rm = mEngine->getRenderableManager();
std::map<utils::Entity, std::vector<filament::MaterialInstance *>> materials;
auto *scene = mView->getScene();
auto *renderTarget = mView->getRenderTarget();
mView->setRenderTarget(mRenderTarget);
mView->setScene(mScene);
for (auto it = begin(); it < end(); it++)
{
const auto &entity = getEntity(it);
auto ri = rm.getInstance(entity);
if (ri.isValid())
{
for (int i = 0; i < rm.getPrimitiveCount(ri); i++)
{
auto *existing = rm.getMaterialInstanceAt(ri, i);
materials[entity].push_back(existing);
rm.setMaterialInstanceAt(ri, i, mDepthMaterialInstance);
}
}
else
{
Log("WARNING: INVALID RENDERABLE");
}
}
mRenderer->render(mView);
mView->setRenderTarget(renderTarget);
for (auto it = begin(); it < end(); it++)
{
const auto &entity = getEntity(it);
auto componentInstance = getInstance(entity);
auto &materialInstance = elementAt<0>(componentInstance);
auto ri = rm.getInstance(entity);
if (ri.isValid())
{
for (int i = 0; i < rm.getPrimitiveCount(ri); i++)
{
rm.setMaterialInstanceAt(ri, i, materialInstance);
}
}
else
{
Log("WARNING: INVALID RENDERABLE");
}
}
mRenderer->render(mView);
for (auto it = begin(); it < end(); it++)
{
const auto &entity = getEntity(it);
auto ri = rm.getInstance(entity);
for (int i = 0; i < rm.getPrimitiveCount(ri); i++)
{
rm.setMaterialInstanceAt(ri, i, materials[entity][i]);
}
}
mView->setScene(scene);
}
private:
filament::Engine *mEngine = std::nullptr_t();
filament::View *mView = std::nullptr_t();
filament::Scene *mScene = std::nullptr_t();
filament::RenderTarget *mRenderTarget = std::nullptr_t();
filament::Renderer *mRenderer = std::nullptr_t();
filament::Material *mDepthMaterial = std::nullptr_t();
filament::MaterialInstance *mDepthMaterialInstance = std::nullptr_t();
filament::TextureSampler mDepthSampler;
};
}

View File

@@ -0,0 +1,44 @@
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#endif
#include "Log.hpp"
#include <filament/Engine.h>
#include <filament/RenderTarget.h>
#include <filament/Renderer.h>
#include <filament/View.h>
#include <utils/Entity.h>
#include "c_api/TOverlayManager.h"
#include "components/OverlayComponentManager.hpp"
using namespace thermion;
extern "C"
{
EMSCRIPTEN_KEEPALIVE TOverlayManager *OverlayManager_create(TEngine *tEngine, TRenderer *tRenderer, TView *tView, TScene *tScene, TRenderTarget *tRenderTarget) {
auto *engine = reinterpret_cast<filament::Engine *>(tEngine);
auto *view = reinterpret_cast<filament::View *>(tView);
auto *scene = reinterpret_cast<filament::Scene *>(tScene);
auto *renderer = reinterpret_cast<filament::Renderer *>(tRenderer);
auto *renderTarget = reinterpret_cast<filament::RenderTarget *>(tRenderTarget);
auto *overlayManager = new OverlayComponentManager(engine, view, scene, renderTarget, renderer);
return reinterpret_cast<TOverlayManager *>(overlayManager);
}
EMSCRIPTEN_KEEPALIVE void OverlayManager_addComponent(TOverlayManager *tOverlayManager, EntityId entityId, TMaterialInstance *tMaterialInstance) {
auto *overlayManager = reinterpret_cast<OverlayComponentManager *>(tOverlayManager);
auto *materialInstance = reinterpret_cast<filament::MaterialInstance *>(tMaterialInstance);
overlayManager->addOverlayComponent(utils::Entity::import(entityId), materialInstance);
}
EMSCRIPTEN_KEEPALIVE void OverlayManager_removeComponent(TOverlayManager *tOverlayManager, EntityId entityId) {
auto *overlayManager = reinterpret_cast<OverlayComponentManager *>(tOverlayManager);
overlayManager->removeOverlayComponent(utils::Entity::import(entityId));
}
}

View File

@@ -55,4 +55,11 @@ EMSCRIPTEN_KEEPALIVE void RenderTicker_setRenderable(TRenderTicker *tRenderTicke
renderTicker->setRenderable(swapChain, views, numViews);
}
EMSCRIPTEN_KEEPALIVE void RenderTicker_setOverlayManager(TRenderTicker *tRenderTicker, TOverlayManager *tOverlayManager) {
auto *renderTicker = reinterpret_cast<RenderTicker *>(tRenderTicker);
auto *overlayManager = reinterpret_cast<OverlayComponentManager *>(tOverlayManager);
renderTicker->addOverlayManager(overlayManager);
}
}

View File

@@ -279,6 +279,11 @@ namespace thermion
view->setFogOptions(fogOptions);
}
EMSCRIPTEN_KEEPALIVE void View_setName(TView* tView, const char *name) {
auto view = reinterpret_cast<View *>(tView);
view->setName(name);
}
#ifdef __cplusplus
}
}