From 3bf03f4b1ff76f36a43ddecc978fac04289dcedc Mon Sep 17 00:00:00 2001 From: ayuan9957 <107920784+ayuan9957@users.noreply.github.com> Date: Thu, 14 May 2026 15:36:17 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=9E=E7=8E=B0=20Filament=20?= =?UTF-8?q?=E7=A6=BB=E5=B1=8F=E6=B8=B2=E6=9F=93=E4=B8=8E=20ImGui=20?= =?UTF-8?q?=E8=A7=86=E5=8F=A3=E5=B5=8C=E5=90=88=EF=BC=88=E6=89=93=E9=80=9A?= =?UTF-8?q?=20RTT=20=E7=AE=A1=E7=BA=BF=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Apps/MetaCorePlayer/main.cpp | 2 +- CMakeLists.txt | 10 +- .../Private/MetaCoreEditorApp.cpp | 6 +- .../MetaCoreEditorViewportRenderer.cpp | 23 +- .../Private/MetaCoreFilamentSceneBridge.cpp | 408 ++++++++++++++++++ .../MetaCoreEditorViewportRenderer.h | 8 +- .../MetaCoreFilamentSceneBridge.h | 42 ++ cmake/MetaCoreFilament.cmake | 51 +++ 8 files changed, 543 insertions(+), 7 deletions(-) create mode 100644 Source/MetaCoreRender/Private/MetaCoreFilamentSceneBridge.cpp create mode 100644 Source/MetaCoreRender/Public/MetaCoreRender/MetaCoreFilamentSceneBridge.h create mode 100644 cmake/MetaCoreFilament.cmake diff --git a/Apps/MetaCorePlayer/main.cpp b/Apps/MetaCorePlayer/main.cpp index 4dcbf2c..049ece2 100644 --- a/Apps/MetaCorePlayer/main.cpp +++ b/Apps/MetaCorePlayer/main.cpp @@ -150,7 +150,7 @@ int main(int argc, char* argv[]) { } MetaCore::MetaCoreEditorViewportRenderer viewportRenderer; - if (!viewportRenderer.Initialize(renderDevice)) { + if (!viewportRenderer.Initialize(renderDevice, window)) { std::cerr << "MetaCorePlayer: viewport renderer initialize failed\n"; return 1; } diff --git a/CMakeLists.txt b/CMakeLists.txt index 52c1a87..ea2370c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,6 +27,9 @@ endif() include(MetaCorePanda3D) metacore_prepare_panda3d() +include(MetaCoreFilament) + + find_package(glm CONFIG REQUIRED) find_package(imgui CONFIG REQUIRED) @@ -207,6 +210,7 @@ target_compile_options(MetaCoreScene PRIVATE ${METACORE_COMMON_WARNINGS}) set(METACORE_RENDER_HEADERS Source/MetaCoreRender/Public/MetaCoreRender/MetaCoreEditorViewportRenderer.h Source/MetaCoreRender/Public/MetaCoreRender/MetaCorePandaSceneBridge.h + Source/MetaCoreRender/Public/MetaCoreRender/MetaCoreFilamentSceneBridge.h Source/MetaCoreRender/Public/MetaCoreRender/MetaCoreRenderDevice.h Source/MetaCoreRender/Public/MetaCoreRender/MetaCoreRenderTypes.h ) @@ -214,9 +218,11 @@ set(METACORE_RENDER_HEADERS set(METACORE_RENDER_SOURCES Source/MetaCoreRender/Private/MetaCoreEditorViewportRenderer.cpp Source/MetaCoreRender/Private/MetaCorePandaSceneBridge.cpp + Source/MetaCoreRender/Private/MetaCoreFilamentSceneBridge.cpp Source/MetaCoreRender/Private/MetaCoreRenderDevice.cpp ) + add_library(MetaCoreRender STATIC ${METACORE_RENDER_HEADERS} ${METACORE_RENDER_SOURCES} @@ -236,6 +242,9 @@ target_link_libraries(MetaCoreRender glm::glm ) +metacore_use_filament(MetaCoreRender) + + target_compile_options(MetaCoreRender PRIVATE ${METACORE_COMMON_WARNINGS}) set(METACORE_RUNTIME_DATA_HEADERS @@ -320,7 +329,6 @@ set(METACORE_EDITOR_SOURCES Source/MetaCoreEditor/Private/MetaCoreEditorModule.cpp Source/MetaCoreEditor/Private/MetaCoreSceneInteractionService.cpp third_party/ImGuizmo/ImGuizmo.cpp - third_party/cgltf/cgltf.cpp third_party/stb/stb_image_impl.cpp ) diff --git a/Source/MetaCoreEditor/Private/MetaCoreEditorApp.cpp b/Source/MetaCoreEditor/Private/MetaCoreEditorApp.cpp index 4668915..72e6cc0 100644 --- a/Source/MetaCoreEditor/Private/MetaCoreEditorApp.cpp +++ b/Source/MetaCoreEditor/Private/MetaCoreEditorApp.cpp @@ -658,7 +658,7 @@ bool MetaCoreEditorApp::Initialize() { } MetaCoreTraceStartup("metacore.app: initialize viewport"); - if (!ViewportRenderer_.Initialize(RenderDevice_)) { + if (!ViewportRenderer_.Initialize(RenderDevice_, Window_)) { MetaCoreTraceStartup("metacore.app: initialize viewport failed"); return false; } @@ -990,6 +990,10 @@ void MetaCoreEditorApp::DrawEditorFrame() { bool gizmoCanvasOpen = true; if (ImGui::Begin("MetaCoreSceneGizmoCanvas", &gizmoCanvasOpen, gizmoCanvasFlags)) { + // 绘制 Filament 离屏渲染的 3D 画面 + uint32_t texId = ViewportRenderer_.GetFilamentGLTextureId(); + ImGui::Image((void*)(intptr_t)texId, ImVec2(viewportState.Width, viewportState.Height)); + SceneInteractionService_.HandleGizmoManipulation(*EditorContext_); gizmoUsing = ImGuizmo::IsUsing(); diff --git a/Source/MetaCoreRender/Private/MetaCoreEditorViewportRenderer.cpp b/Source/MetaCoreRender/Private/MetaCoreEditorViewportRenderer.cpp index a9cb339..79f9768 100644 --- a/Source/MetaCoreRender/Private/MetaCoreEditorViewportRenderer.cpp +++ b/Source/MetaCoreRender/Private/MetaCoreEditorViewportRenderer.cpp @@ -39,7 +39,7 @@ void MetaCoreTrace(const char* message) { } } // namespace -bool MetaCoreEditorViewportRenderer::Initialize(MetaCoreRenderDevice& renderDevice) { +bool MetaCoreEditorViewportRenderer::Initialize(MetaCoreRenderDevice& renderDevice, MetaCoreWindow& window) { MetaCoreTrace("metacore.render: viewport init enter"); Shutdown(); @@ -48,6 +48,11 @@ bool MetaCoreEditorViewportRenderer::Initialize(MetaCoreRenderDevice& renderDevi MetaCoreTrace("metacore.render: viewport scene runtime bind failed"); return false; } + + if (!FilamentSceneBridge_.Initialize(window)) { + MetaCoreTrace("metacore.render: viewport filament scene runtime bind failed"); + return false; + } MetaCoreTrace("metacore.render: viewport scene runtime ready"); RenderDevice_ = &renderDevice; @@ -56,12 +61,15 @@ bool MetaCoreEditorViewportRenderer::Initialize(MetaCoreRenderDevice& renderDevi return true; } + void MetaCoreEditorViewportRenderer::Shutdown() { SceneBridge_.Shutdown(); + FilamentSceneBridge_.Shutdown(); RenderDevice_ = nullptr; ViewportRect_ = MetaCoreViewportRect{}; } + void MetaCoreEditorViewportRenderer::SetViewportRect(const MetaCoreViewportRect& viewportRect) { ViewportRect_ = viewportRect; if (RenderDevice_ != nullptr) { @@ -75,12 +83,21 @@ void MetaCoreEditorViewportRenderer::RenderSceneToViewport(const MetaCoreScene& } RenderDevice_->SetSceneViewportRect(ViewportRect_); - SceneBridge_.ApplySceneView(sceneView); - SceneBridge_.SyncScene(scene, false); + + // 更新并渲染 Filament 桥接器 + FilamentSceneBridge_.ApplySceneView(sceneView); + FilamentSceneBridge_.SyncScene(scene, false); + FilamentSceneBridge_.Render(); // 恢复 Render 调用,因为现在是离屏渲染 } + void MetaCoreEditorViewportRenderer::SetProjectRootPath(const std::filesystem::path& projectRootPath) { SceneBridge_.SetProjectRootPath(projectRootPath); + FilamentSceneBridge_.SetProjectRootPath(projectRootPath); +} + +uint32_t MetaCoreEditorViewportRenderer::GetFilamentGLTextureId() const { + return FilamentSceneBridge_.GetGLTextureId(); } bool MetaCoreEditorViewportRenderer::TryGetObjectWorldMatrix(MetaCoreId objectId, glm::mat4& worldMatrix) const { diff --git a/Source/MetaCoreRender/Private/MetaCoreFilamentSceneBridge.cpp b/Source/MetaCoreRender/Private/MetaCoreFilamentSceneBridge.cpp new file mode 100644 index 0000000..f37bd4c --- /dev/null +++ b/Source/MetaCoreRender/Private/MetaCoreFilamentSceneBridge.cpp @@ -0,0 +1,408 @@ +#include "MetaCoreRender/MetaCoreFilamentSceneBridge.h" +#include "MetaCorePlatform/MetaCoreWindow.h" +#include "MetaCoreScene/MetaCoreScene.h" +#include "MetaCoreScene/MetaCoreComponents.h" +#include "MetaCoreRender/MetaCoreRenderTypes.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#define GLM_ENABLE_EXPERIMENTAL +#include +#include + +#include +#include +#include +#include + +// 引入 Windows 和 OpenGL 头文件以创建纹理 +#define WIN32_LEAN_AND_MEAN +#include +#include + +namespace MetaCore { + +class MetaCoreFilamentSceneBridge::MetaCoreFilamentSceneBridgeImpl { +public: + MetaCoreFilamentSceneBridgeImpl() = default; + + ~MetaCoreFilamentSceneBridgeImpl() { + Shutdown(); + } + + bool Initialize(MetaCoreWindow& window) { + std::cout << "FilamentSceneBridge: Initializing..." << std::endl; + + // 创建 Filament Engine (不共享上下文,避免闪退) + Engine_ = filament::Engine::create(); + + if (!Engine_) { + std::cerr << "Failed to create Filament Engine with shared context!" << std::endl; + return false; + } + + // 创建无窗口的 1x1 交换链 (因为我们是离屏渲染,不需要绑定真实窗口,避免 OpenGL 上下文冲突) + SwapChain_ = Engine_->createSwapChain(1, 1, 0); + if (!SwapChain_) { + std::cerr << "Failed to create Filament headless SwapChain!" << std::endl; + return false; + } + + // 创建渲染器 + Renderer_ = Engine_->createRenderer(); + + // 创建场景 + Scene_ = Engine_->createScene(); + + // 创建默认灯光 + Light_ = utils::EntityManager::get().create(); + filament::LightManager::Builder(filament::LightManager::Type::DIRECTIONAL) + .color(filament::Color::toLinear({ 1.0f, 1.0f, 1.0f })) + .intensity(100000.0f) + .direction({ 0.5f, -1.0f, -0.5f }) + .castShadows(true) + .build(*Engine_, Light_); + Scene_->addEntity(Light_); + + // 创建相机 + utils::Entity cameraEntity = utils::EntityManager::get().create(); + Camera_ = Engine_->createCamera(cameraEntity); + + // 创建视图 + View_ = Engine_->createView(); + View_->setScene(Scene_); + View_->setCamera(Camera_); + + // 初始化离屏渲染纹理 + auto [width, height] = window.GetFramebufferSize(); + + // 1. 创建 OpenGL 纹理 + glGenTextures(1, &GLTextureId_); + glBindTexture(GL_TEXTURE_2D, GLTextureId_); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glBindTexture(GL_TEXTURE_2D, 0); + + // 2. 导入到 Filament 作为颜色附件 + FilamentTexture_ = filament::Texture::Builder() + .width(static_cast(width)) + .height(static_cast(height)) + .usage(filament::Texture::Usage::COLOR_ATTACHMENT | filament::Texture::Usage::SAMPLEABLE) + .format(filament::Texture::InternalFormat::RGBA8) + .import(static_cast(GLTextureId_)) + .build(*Engine_); + + // 3. 创建深度纹理 + DepthTexture_ = filament::Texture::Builder() + .width(static_cast(width)) + .height(static_cast(height)) + .usage(filament::Texture::Usage::DEPTH_ATTACHMENT) + .format(filament::Texture::InternalFormat::DEPTH24) + .build(*Engine_); + + // 4. 创建 RenderTarget 并绑定 + RenderTarget_ = filament::RenderTarget::Builder() + .texture(filament::RenderTarget::AttachmentPoint::COLOR, FilamentTexture_) + .texture(filament::RenderTarget::AttachmentPoint::DEPTH, DepthTexture_) + .build(*Engine_); + + // 5. 设置到 View + View_->setRenderTarget(RenderTarget_); + View_->setViewport({0, 0, static_cast(width), static_cast(height)}); + + // 初始化 gltfio (使用 JIT Shader Provider,需要链接 filamat) + MaterialProvider_ = filament::gltfio::createJitShaderProvider(Engine_); + AssetLoader_ = filament::gltfio::AssetLoader::create({ Engine_, MaterialProvider_, nullptr }); + + std::cout << "FilamentSceneBridge: Initialized with Offscreen Texture ID: " << GLTextureId_ << std::endl; + return true; + } + + void Shutdown() { + if (Engine_) { + std::cout << "FilamentSceneBridge: Shutting down..." << std::endl; + + // 销毁所有加载的资产 + for (auto& [id, asset] : LoadedAssets_) { + AssetLoader_->destroyAsset(asset); + } + LoadedAssets_.clear(); + + // 销毁 gltfio 资源 + if (AssetLoader_) { + filament::gltfio::AssetLoader::destroy(&AssetLoader_); + AssetLoader_ = nullptr; + } + if (MaterialProvider_) { + MaterialProvider_->destroyMaterials(); + delete MaterialProvider_; + MaterialProvider_ = nullptr; + } + + // 销毁离屏渲染资源 + if (RenderTarget_) { + Engine_->destroy(RenderTarget_); + RenderTarget_ = nullptr; + } + if (FilamentTexture_) { + Engine_->destroy(FilamentTexture_); + FilamentTexture_ = nullptr; + } + if (DepthTexture_) { + Engine_->destroy(DepthTexture_); + DepthTexture_ = nullptr; + } + if (GLTextureId_) { + glDeleteTextures(1, &GLTextureId_); + GLTextureId_ = 0; + } + + // 销毁 View + Engine_->destroy(View_); + + // 销毁相机组件和实体 + if (Camera_) { + utils::Entity cameraEntity = Camera_->getEntity(); + Engine_->destroyCameraComponent(cameraEntity); + utils::EntityManager::get().destroy(cameraEntity); + } + + // 销毁其他资源 + Engine_->destroy(Scene_); + Engine_->destroy(Renderer_); + Engine_->destroy(SwapChain_); + + // 最后销毁 Engine + filament::Engine::destroy(&Engine_); + Engine_ = nullptr; + } + } + + void SetProjectRootPath(const std::filesystem::path& projectRootPath) { + ProjectRootPath_ = projectRootPath; + } + + void SyncScene(const MetaCoreScene& scene, bool compatibilityMeshOnly) { + if (!AssetLoader_) return; + + for (const auto& gameObject : scene.GetGameObjects()) { + if (!gameObject.HasComponent()) { + continue; + } + + const auto& meshRenderer = gameObject.GetComponent(); + if (meshRenderer.MeshSource != MetaCoreMeshSourceKind::Asset) { + continue; + } + + std::string modelPath = meshRenderer.SourceModelPath; + if (modelPath.empty()) { + continue; + } + + std::filesystem::path absolutePath = ProjectRootPath_ / modelPath; + + // 如果已经加载过,更新位置即可 + if (LoadedAssets_.contains(gameObject.GetId())) { + UpdateTransform(gameObject); + continue; + } + + // 加载新模型 + std::cout << "FilamentSceneBridge: Loading GLTF: " << absolutePath << std::endl; + + std::ifstream file(absolutePath, std::ios::binary); + if (!file.is_open()) { + std::cerr << "Failed to open file: " << absolutePath << std::endl; + continue; + } + + std::vector buffer((std::istreambuf_iterator(file)), std::istreambuf_iterator()); + + filament::gltfio::FilamentAsset* asset = AssetLoader_->createAsset( + reinterpret_cast(buffer.data()), + static_cast(buffer.size()) + ); + + if (!asset) { + std::cerr << "Failed to create asset!" << std::endl; + continue; + } + + // 加载贴图等资源 + filament::gltfio::ResourceLoader resourceLoader({ Engine_ }); + resourceLoader.loadResources(asset); + + // 添加到场景 + Scene_->addEntities(asset->getEntities(), asset->getEntityCount()); + + LoadedAssets_[gameObject.GetId()] = asset; + + // 更新初始位置 + UpdateTransform(gameObject); + } + } + + void ApplySceneView(const MetaCoreSceneView& sceneView) { + if (!Camera_ || !View_) return; + + // 设置相机位置和朝向 + Camera_->lookAt( + { sceneView.CameraPosition.x, sceneView.CameraPosition.y, sceneView.CameraPosition.z }, + { sceneView.CameraTarget.x, sceneView.CameraTarget.y, sceneView.CameraTarget.z }, + { sceneView.CameraUp.x, sceneView.CameraUp.y, sceneView.CameraUp.z } + ); + + // 获取当前视口大小计算宽高比 + const auto& viewport = View_->getViewport(); + double aspect = 1.0; + if (viewport.height > 0) { + aspect = static_cast(viewport.width) / static_cast(viewport.height); + } + + // 设置透视投影 + double fov = sceneView.VerticalFieldOfViewDegrees; + double nearClip = 0.1; + double farClip = 1000.0; + + Camera_->setProjection(fov, aspect, nearClip, farClip, filament::Camera::Fov::VERTICAL); + } + + void Render() { + if (Renderer_ && SwapChain_ && View_) { + filament::Renderer::ClearOptions options; + options.clearColor = { 1.0f, 0.0f, 1.0f, 1.0f }; // 粉色,方便辨认 + options.clear = true; + Renderer_->setClearOptions(options); + + if (Renderer_->beginFrame(SwapChain_)) { + Renderer_->render(View_); + Renderer_->endFrame(); + } + } + } + + uint32_t GetGLTextureId() const { + return GLTextureId_; + } + + bool TryGetObjectWorldMatrix(MetaCoreId objectId, glm::mat4& worldMatrix) const { + return false; + } + + bool HasRuntimeSyncFailure() const { return false; } + const std::string& GetLastRuntimeSyncFailure() const { return EmptyString_; } + +private: + void UpdateTransform(const MetaCoreGameObject& gameObject) { + auto it = LoadedAssets_.find(gameObject.GetId()); + if (it == LoadedAssets_.end()) return; + + filament::gltfio::FilamentAsset* asset = it->second; + utils::Entity rootEntity = asset->getRoot(); + + auto& tm = Engine_->getTransformManager(); + auto instance = tm.getInstance(rootEntity); + if (instance) { + if (!gameObject.HasComponent()) return; + + const auto& transform = gameObject.GetComponent(); + + glm::mat4 matrix = glm::mat4(1.0f); + matrix = glm::translate(matrix, transform.Position); + matrix = glm::rotate(matrix, glm::radians(transform.RotationEulerDegrees.x), {1, 0, 0}); + matrix = glm::rotate(matrix, glm::radians(transform.RotationEulerDegrees.y), {0, 1, 0}); + matrix = glm::rotate(matrix, glm::radians(transform.RotationEulerDegrees.z), {0, 0, 1}); + matrix = glm::scale(matrix, transform.Scale); + + tm.setTransform(instance, *reinterpret_cast(glm::value_ptr(matrix))); + } + } + + filament::Engine* Engine_ = nullptr; + filament::SwapChain* SwapChain_ = nullptr; + filament::Renderer* Renderer_ = nullptr; + filament::Scene* Scene_ = nullptr; + filament::Camera* Camera_ = nullptr; + filament::View* View_ = nullptr; + + filament::gltfio::AssetLoader* AssetLoader_ = nullptr; + filament::gltfio::MaterialProvider* MaterialProvider_ = nullptr; + + std::unordered_map LoadedAssets_; + + GLuint GLTextureId_ = 0; + filament::Texture* FilamentTexture_ = nullptr; + filament::Texture* DepthTexture_ = nullptr; + filament::RenderTarget* RenderTarget_ = nullptr; + utils::Entity Light_; + + std::filesystem::path ProjectRootPath_{}; + std::string EmptyString_{}; +}; + +MetaCoreFilamentSceneBridge::MetaCoreFilamentSceneBridge() + : Impl_(std::make_unique()) {} + +MetaCoreFilamentSceneBridge::~MetaCoreFilamentSceneBridge() = default; + +bool MetaCoreFilamentSceneBridge::Initialize(MetaCoreWindow& window) { + return Impl_->Initialize(window); +} + +void MetaCoreFilamentSceneBridge::Shutdown() { + Impl_->Shutdown(); +} + +void MetaCoreFilamentSceneBridge::SetProjectRootPath(const std::filesystem::path& projectRootPath) { + Impl_->SetProjectRootPath(projectRootPath); +} + +void MetaCoreFilamentSceneBridge::SyncScene(const MetaCoreScene& scene, bool compatibilityMeshOnly) { + Impl_->SyncScene(scene, compatibilityMeshOnly); +} + +void MetaCoreFilamentSceneBridge::ApplySceneView(const MetaCoreSceneView& sceneView) { + Impl_->ApplySceneView(sceneView); +} + +void MetaCoreFilamentSceneBridge::Render() { + Impl_->Render(); +} + +uint32_t MetaCoreFilamentSceneBridge::GetGLTextureId() const { + return Impl_->GetGLTextureId(); +} + +bool MetaCoreFilamentSceneBridge::TryGetObjectWorldMatrix(MetaCoreId objectId, glm::mat4& worldMatrix) const { + return Impl_->TryGetObjectWorldMatrix(objectId, worldMatrix); +} + +bool MetaCoreFilamentSceneBridge::HasRuntimeSyncFailure() const { + return Impl_->HasRuntimeSyncFailure(); +} + +const std::string& MetaCoreFilamentSceneBridge::GetLastRuntimeSyncFailure() const { + return Impl_->GetLastRuntimeSyncFailure(); +} + +} // namespace MetaCore diff --git a/Source/MetaCoreRender/Public/MetaCoreRender/MetaCoreEditorViewportRenderer.h b/Source/MetaCoreRender/Public/MetaCoreRender/MetaCoreEditorViewportRenderer.h index 7311599..6463c7b 100644 --- a/Source/MetaCoreRender/Public/MetaCoreRender/MetaCoreEditorViewportRenderer.h +++ b/Source/MetaCoreRender/Public/MetaCoreRender/MetaCoreEditorViewportRenderer.h @@ -1,30 +1,36 @@ #pragma once #include "MetaCoreRender/MetaCorePandaSceneBridge.h" +#include "MetaCoreRender/MetaCoreFilamentSceneBridge.h" #include "MetaCoreRender/MetaCoreRenderTypes.h" + #include #include namespace MetaCore { class MetaCoreRenderDevice; +class MetaCoreWindow; class MetaCoreScene; class MetaCoreEditorViewportRenderer { public: - bool Initialize(MetaCoreRenderDevice& renderDevice); + bool Initialize(MetaCoreRenderDevice& renderDevice, MetaCoreWindow& window); void Shutdown(); void SetViewportRect(const MetaCoreViewportRect& viewportRect); void RenderSceneToViewport(const MetaCoreScene& scene, const MetaCoreSceneView& sceneView); void SetProjectRootPath(const std::filesystem::path& projectRootPath); + [[nodiscard]] uint32_t GetFilamentGLTextureId() const; [[nodiscard]] bool TryGetObjectWorldMatrix(MetaCoreId objectId, glm::mat4& worldMatrix) const; private: MetaCoreRenderDevice* RenderDevice_ = nullptr; MetaCorePandaSceneBridge SceneBridge_{}; + MetaCoreFilamentSceneBridge FilamentSceneBridge_{}; MetaCoreViewportRect ViewportRect_{}; + }; } // namespace MetaCore diff --git a/Source/MetaCoreRender/Public/MetaCoreRender/MetaCoreFilamentSceneBridge.h b/Source/MetaCoreRender/Public/MetaCoreRender/MetaCoreFilamentSceneBridge.h new file mode 100644 index 0000000..b6f904a --- /dev/null +++ b/Source/MetaCoreRender/Public/MetaCoreRender/MetaCoreFilamentSceneBridge.h @@ -0,0 +1,42 @@ +#pragma once + +#include "MetaCoreFoundation/MetaCoreId.h" + +#include + +#include +#include +#include + +namespace MetaCore { + +class MetaCoreWindow; +class MetaCoreScene; +struct MetaCoreSceneView; + +/** + * @brief Filament 场景桥接器,负责将 MetaCore 的场景数据同步到 Filament 渲染引擎中 + */ +class MetaCoreFilamentSceneBridge { +public: + MetaCoreFilamentSceneBridge(); + ~MetaCoreFilamentSceneBridge(); + + bool Initialize(MetaCoreWindow& window); + void Shutdown(); + void SetProjectRootPath(const std::filesystem::path& projectRootPath); + void SyncScene(const MetaCoreScene& scene, bool compatibilityMeshOnly = false); + void ApplySceneView(const MetaCoreSceneView& sceneView); + void Render(); + [[nodiscard]] uint32_t GetGLTextureId() const; + + [[nodiscard]] bool TryGetObjectWorldMatrix(MetaCoreId objectId, glm::mat4& worldMatrix) const; + [[nodiscard]] bool HasRuntimeSyncFailure() const; + [[nodiscard]] const std::string& GetLastRuntimeSyncFailure() const; + +private: + class MetaCoreFilamentSceneBridgeImpl; + std::unique_ptr Impl_{}; +}; + +} // namespace MetaCore diff --git a/cmake/MetaCoreFilament.cmake b/cmake/MetaCoreFilament.cmake new file mode 100644 index 0000000..822bdc4 --- /dev/null +++ b/cmake/MetaCoreFilament.cmake @@ -0,0 +1,51 @@ +# Filament SDK configuration for MetaCore + +set(METACORE_FILAMENT_ROOT "${CMAKE_SOURCE_DIR}/third_party/filament_installed" CACHE PATH "Path to installed Filament SDK") +set(METACORE_FILAMENT_INCLUDE_DIR "${METACORE_FILAMENT_ROOT}/include") +set(METACORE_FILAMENT_LIB_DIR "${METACORE_FILAMENT_ROOT}/lib/x86_64") + +function(metacore_use_filament target_name) + if(NOT TARGET ${target_name}) + message(FATAL_ERROR "Target ${target_name} does not exist.") + endif() + + message(STATUS "Linking Filament to ${target_name}") + + # 定义核心库 + set(_filament_libs + "${METACORE_FILAMENT_LIB_DIR}/filament.lib" + "${METACORE_FILAMENT_LIB_DIR}/backend.lib" + "${METACORE_FILAMENT_LIB_DIR}/utils.lib" + "${METACORE_FILAMENT_LIB_DIR}/filabridge.lib" + "${METACORE_FILAMENT_LIB_DIR}/filaflat.lib" + "${METACORE_FILAMENT_LIB_DIR}/filamat.lib" + "${METACORE_FILAMENT_LIB_DIR}/shaders.lib" + "${METACORE_FILAMENT_LIB_DIR}/bluegl.lib" + "${METACORE_FILAMENT_LIB_DIR}/gltfio.lib" + "${METACORE_FILAMENT_LIB_DIR}/gltfio_core.lib" + "${METACORE_FILAMENT_LIB_DIR}/abseil.lib" + "${METACORE_FILAMENT_LIB_DIR}/perfetto.lib" + "${METACORE_FILAMENT_LIB_DIR}/dracodec.lib" + "${METACORE_FILAMENT_LIB_DIR}/geometry.lib" + "${METACORE_FILAMENT_LIB_DIR}/smol-v.lib" + "${METACORE_FILAMENT_LIB_DIR}/zstd.lib" + opengl32.lib + gdi32.lib + user32.lib + shlwapi.lib + ) + + target_include_directories(${target_name} PRIVATE "${METACORE_FILAMENT_INCLUDE_DIR}") + target_link_libraries(${target_name} PRIVATE ${_filament_libs}) + + # Filament 需要 C++17 或更高版本 + target_compile_features(${target_name} PRIVATE cxx_std_17) + + # 针对 MSVC 的一些必要宏定义 + if(MSVC) + target_compile_definitions(${target_name} PRIVATE + WIN32_LEAN_AND_MEAN + _CRT_SECURE_NO_WARNINGS + ) + endif() +endfunction()