#include "MetaCoreRender/MetaCoreFilamentSceneBridge.h" #include "MetaCorePlatform/MetaCoreWindow.h" #include "MetaCoreScene/MetaCoreScene.h" #include "MetaCoreScene/MetaCoreComponents.h" #include "MetaCoreRender/MetaCoreRenderTypes.h" #include "MetaCoreRender/MetaCoreImGuiHelper.h" #include #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; } // 创建绑定真实窗口的交换链 SwapChain_ = Engine_->createSwapChain((void*)window.GetNativeWindowHandle()); if (!SwapChain_) { std::cerr << "Failed to create Filament SwapChain with window handle!" << 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_); // 创建 UI 视图 UIView_ = Engine_->createView(); // 创建 ImGuiHelper ImGuiHelper_ = new MetaCoreImGuiHelper(Engine_, UIView_, "", ImGui::GetCurrentContext()); // 初始化离屏渲染纹理 auto [width, height] = window.GetFramebufferSize(); // 1. 创建 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) .build(*Engine_); // 2. 创建深度纹理 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_); // 3. 创建 RenderTarget 并绑定 RenderTarget_ = filament::RenderTarget::Builder() .texture(filament::RenderTarget::AttachmentPoint::COLOR, FilamentTexture_) .texture(filament::RenderTarget::AttachmentPoint::DEPTH, DepthTexture_) .build(*Engine_); // 4. 设置到 View View_->setRenderTarget(RenderTarget_); View_->setViewport({0, 0, static_cast(width), static_cast(height)}); // 确保开启后处理(为了HDR) View_->setPostProcessingEnabled(true); // 初始化 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 RenderAll() { if (!Renderer_ || !SwapChain_ || !View_ || !UIView_ || !ImGuiHelper_) { return; } if (Renderer_->beginFrame(SwapChain_)) { // 1. 渲染 3D 离屏视口 (输出到 RenderTarget) filament::Renderer::ClearOptions options; options.clearColor = { 0.11f, 0.12f, 0.14f, 1.0f }; // 深灰色 options.clear = true; Renderer_->setClearOptions(options); Renderer_->render(View_); // 2. 准备并渲染 UI 视口 (输出到 SwapChain) ImGuiIO& io = ImGui::GetIO(); ImGuiHelper_->setDisplaySize(io.DisplaySize.x, io.DisplaySize.y); UIView_->setViewport({0, 0, static_cast(io.DisplaySize.x), static_cast(io.DisplaySize.y)}); options.clearColor = { 0.11f, 0.12f, 0.14f, 1.0f }; // 灰色 options.clear = true; Renderer_->setClearOptions(options); ImGuiHelper_->processImGuiCommands(ImGui::GetDrawData(), io); Renderer_->render(UIView_); Renderer_->endFrame(); // 在帧结束、指令提交后,安全地销毁上一帧遗留的旧纹理 for (auto* tex : OldTextures_) { Engine_->destroy(tex); } OldTextures_.clear(); } } uint32_t GetGLTextureId() const { return GLTextureId_; } void Resize(int width, int height) { if (width <= 0 || height <= 0) return; // 【关键修复】:如果大小没有改变,不要重新创建纹理! // 否则会导致上一帧传给 ImGui 的纹理指针在这一帧被提前销毁,引发 Use-after-free 崩溃。 if (FilamentTexture_ && FilamentTexture_->getWidth() == static_cast(width) && FilamentTexture_->getHeight() == static_cast(height)) { return; } if (RenderTarget_) Engine_->destroy(RenderTarget_); if (DepthTexture_) Engine_->destroy(DepthTexture_); // 【关键修复】:推迟销毁旧纹理,避免当前帧 ImGui 的 DrawList 还在引用它导致崩溃。 if (FilamentTexture_) { OldTextures_.push_back(FilamentTexture_); } 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) .build(*Engine_); 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_); RenderTarget_ = filament::RenderTarget::Builder() .texture(filament::RenderTarget::AttachmentPoint::COLOR, FilamentTexture_) .texture(filament::RenderTarget::AttachmentPoint::DEPTH, DepthTexture_) .build(*Engine_); View_->setRenderTarget(RenderTarget_); View_->setViewport({0, 0, static_cast(width), static_cast(height)}); } void* GetFilamentTexturePointer() const { return FilamentTexture_; } 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_; filament::View* UIView_ = nullptr; MetaCoreImGuiHelper* ImGuiHelper_ = nullptr; GLuint GLTextureId_ = 0; filament::Texture* FilamentTexture_ = nullptr; filament::Texture* DepthTexture_ = nullptr; filament::RenderTarget* RenderTarget_ = nullptr; std::vector OldTextures_; 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::RenderAll() { Impl_->RenderAll(); } uint32_t MetaCoreFilamentSceneBridge::GetGLTextureId() const { return Impl_->GetGLTextureId(); } void MetaCoreFilamentSceneBridge::Resize(int width, int height) { Impl_->Resize(width, height); } void* MetaCoreFilamentSceneBridge::GetFilamentTexturePointer() const { return Impl_->GetFilamentTexturePointer(); } 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