From 1d0377584cd45ab529f2126d8f3fefc57277d3dc Mon Sep 17 00:00:00 2001 From: ayuan9957 <107920784+ayuan9957@users.noreply.github.com> Date: Fri, 15 May 2026 15:06:15 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=81=A2=E5=A4=8D=20ImGui=20OpenGL3=20?= =?UTF-8?q?=E6=B8=B2=E6=9F=93=E9=93=BE=EF=BC=8C=E5=89=A5=E7=A6=BB=20Panda3?= =?UTF-8?q?D=EF=BC=8C=E5=AE=9E=E7=8E=B0=20Filament=20=E7=A6=BB=E5=B1=8F?= =?UTF-8?q?=E6=B8=B2=E6=9F=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 18 +- .../Private/MetaCoreEditorApp.cpp | 15 +- .../Private/MetaCoreWindow.cpp | 201 ++++++++---------- .../Public/MetaCorePlatform/MetaCoreWindow.h | 3 - .../MetaCoreEditorViewportRenderer.cpp | 14 +- .../Private/MetaCoreFilamentSceneBridge.cpp | 51 +++++ .../Private/MetaCoreRenderDevice.cpp | 113 +--------- .../MetaCoreEditorViewportRenderer.h | 3 +- .../MetaCoreFilamentSceneBridge.h | 2 + .../MetaCoreRender/MetaCoreRenderDevice.h | 5 - tests/FilamentImGuiDemo.cpp | 171 +++++++++++++++ 11 files changed, 351 insertions(+), 245 deletions(-) create mode 100644 tests/FilamentImGuiDemo.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index ea2370c..d17ca28 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -209,16 +209,16 @@ 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/MetaCoreImGuiHelper.h Source/MetaCoreRender/Public/MetaCoreRender/MetaCoreRenderDevice.h Source/MetaCoreRender/Public/MetaCoreRender/MetaCoreRenderTypes.h ) set(METACORE_RENDER_SOURCES Source/MetaCoreRender/Private/MetaCoreEditorViewportRenderer.cpp - Source/MetaCoreRender/Private/MetaCorePandaSceneBridge.cpp Source/MetaCoreRender/Private/MetaCoreFilamentSceneBridge.cpp + Source/MetaCoreRender/Private/MetaCoreImGuiHelper.cpp Source/MetaCoreRender/Private/MetaCoreRenderDevice.cpp ) @@ -240,6 +240,7 @@ target_link_libraries(MetaCoreRender MetaCoreScene MetaCorePanda3D::SDK glm::glm + imgui::imgui ) metacore_use_filament(MetaCoreRender) @@ -418,4 +419,17 @@ if(METACORE_BUILD_TESTS) metacore_stage_panda3d_runtime(MetaCoreSmokeTests) metacore_stage_simplepbr_runtime(MetaCoreSmokeTests) add_test(NAME MetaCoreSmokeTests COMMAND MetaCoreSmokeTests) + + # Filament + ImGui 离屏渲染 Demo + add_executable(FilamentImGuiDemo + tests/FilamentImGuiDemo.cpp + ) + target_link_libraries(FilamentImGuiDemo + PRIVATE + MetaCoreRender + imgui::imgui + ) + target_compile_options(FilamentImGuiDemo PRIVATE ${METACORE_COMMON_WARNINGS}) + target_compile_definitions(FilamentImGuiDemo PRIVATE WIN32_LEAN_AND_MEAN NOMINMAX) + metacore_use_filament(FilamentImGuiDemo) endif() diff --git a/Source/MetaCoreEditor/Private/MetaCoreEditorApp.cpp b/Source/MetaCoreEditor/Private/MetaCoreEditorApp.cpp index 72e6cc0..802ba14 100644 --- a/Source/MetaCoreEditor/Private/MetaCoreEditorApp.cpp +++ b/Source/MetaCoreEditor/Private/MetaCoreEditorApp.cpp @@ -754,9 +754,20 @@ int MetaCoreEditorApp::Run() { DrawEditorFrame(); ImGui::Render(); - RenderDevice_.RenderFrame(); + + // 1. Filament 渲染 3D 视口到离屏纹理 + MetaCoreSceneView sceneView = EditorContext_->GetCameraController().BuildSceneView(); + sceneView.SelectedObjectId = EditorContext_->GetSelectedObjectId(); + ViewportRenderer_.RenderSceneToViewport(Scene_, sceneView); + + // 2. ImGui 渲染 UI 到屏幕 (包含 3D 纹理的显示) ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); - RenderDevice_.PresentFrame(); + + // 3. 交换缓冲区 (因为去掉了 Panda3D 的 flip_frame) + HDC hdc = GetDC(static_cast(Window_.GetNativeWindowHandle())); + SwapBuffers(hdc); + ReleaseDC(static_cast(Window_.GetNativeWindowHandle()), hdc); + Window_.EndFrame(); } diff --git a/Source/MetaCorePlatform/Private/MetaCoreWindow.cpp b/Source/MetaCorePlatform/Private/MetaCoreWindow.cpp index e4779de..cd948b1 100644 --- a/Source/MetaCorePlatform/Private/MetaCoreWindow.cpp +++ b/Source/MetaCorePlatform/Private/MetaCoreWindow.cpp @@ -1,11 +1,5 @@ #include "MetaCorePlatform/MetaCoreWindow.h" -#include "graphicsWindow.h" -#include "load_prc_file.h" -#include "nativeWindowHandle.h" -#include "pandaFramework.h" -#include "windowFramework.h" - #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif @@ -50,41 +44,6 @@ void MetaCoreWindowTrace(const char* message) { std::printf("%s%s\n", timeBuffer, message); } -void MetaCoreConfigurePanda3D(const std::string& title) { - static bool configured = false; - if (configured) { - return; - } - - load_prc_file_data("", "load-display pandagl\n"); - load_prc_file_data("", "aux-display p3windisplay\n"); - load_prc_file_data("", "window-type onscreen\n"); - load_prc_file_data("", "model-path ./models\n"); - load_prc_file_data("", "sync-video false\n"); - load_prc_file_data("", "notify-level warning\n"); - load_prc_file_data("", "audio-library-name null\n"); - load_prc_file_data("", "textures-power-2 none\n"); - - // Use window-title PrC variable instead of WindowProperties::set_title to avoid ABI mismatch in Debug builds. - const std::string configData = "window-title " + title + "\n"; - load_prc_file_data("", configData); - - configured = true; -} - -HWND MetaCoreResolveNativeWindowHandle(GraphicsWindow* graphicsWindow) { - if (graphicsWindow == nullptr) { - return nullptr; - } - - WindowHandle* windowHandle = graphicsWindow->get_window_handle(); - if (windowHandle == nullptr) { - return nullptr; - } - - return reinterpret_cast(windowHandle->get_int_handle()); -} - std::wstring MetaCoreUtf8ToWide(std::string_view utf8Text) { if (utf8Text.empty()) { return {}; @@ -130,10 +89,9 @@ std::unordered_map& MetaCoreGet class MetaCoreWindow::MetaCoreWindowImpl { public: - PandaFramework Framework{}; - WindowFramework* WindowFrameworkHandle = nullptr; - GraphicsWindow* GraphicsWindowHandle = nullptr; HWND NativeHandle = nullptr; + HDC hDC = nullptr; + HGLRC hGLRC = nullptr; MetaCoreInput Input{}; MetaCoreNativeWindowMessageHandler MessageHandler{}; WNDPROC OriginalWindowProc = nullptr; @@ -189,54 +147,75 @@ bool MetaCoreWindow::Initialize(int width, int height, const std::string& title) return true; } - MetaCoreWindowTrace("metacore.window: configure runtime backend"); - MetaCoreConfigurePanda3D(title); - MetaCoreWindowTrace("metacore.window: open framework"); - Impl_->Framework.open_framework(); + // 1. 注册窗口类 + WNDCLASSEXW wcex{}; + wcex.cbSize = sizeof(WNDCLASSEXW); + wcex.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; + wcex.lpfnWndProc = MetaCoreWindowSubclassProc; // 直接使用我们的处理函数 + wcex.hInstance = GetModuleHandle(nullptr); + wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); + wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wcex.lpszClassName = L"MetaCoreWindowClass"; - MetaCoreWindowTrace("metacore.window: setup window properties begin"); - WindowProperties windowProperties; - - MetaCoreWindowTrace("metacore.window: set window size"); - windowProperties.set_size(width, height); - - MetaCoreWindowTrace("metacore.window: skip runtime title handoff due to ABI issues"); - // windowProperties.set_title(title); // This triggers bad_alloc in VS2022 Debug vs Panda3D VS2019 SDK - - MetaCoreWindowTrace("metacore.window: set foreground"); - windowProperties.set_foreground(true); + RegisterClassExW(&wcex); - MetaCoreWindowTrace("metacore.window: open window"); - Impl_->WindowFrameworkHandle = Impl_->Framework.open_window(windowProperties, 0); - if (Impl_->WindowFrameworkHandle == nullptr) { - MetaCoreWindowTrace("metacore.window: open window returned null"); - Shutdown(); - return false; - } + // 2. 转换标题 + std::wstring wideTitle = MetaCoreUtf8ToWide(title); - MetaCoreWindowTrace("metacore.window: get graphics window"); - Impl_->GraphicsWindowHandle = Impl_->WindowFrameworkHandle->get_graphics_window(); - MetaCoreWindowTrace("metacore.window: resolve native handle"); - Impl_->NativeHandle = MetaCoreResolveNativeWindowHandle(Impl_->GraphicsWindowHandle); - if (Impl_->GraphicsWindowHandle == nullptr || Impl_->NativeHandle == nullptr) { - MetaCoreWindowTrace("metacore.window: graphics/native handle invalid"); - Shutdown(); - return false; - } + // 3. 计算窗口大小 (包含边框) + RECT rect = { 0, 0, width, height }; + AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE); - if (!title.empty()) { - const std::wstring wideTitle = MetaCoreUtf8ToWide(title); - if (!wideTitle.empty()) { - SetWindowTextW(Impl_->NativeHandle, wideTitle.c_str()); - } - } - - MetaCoreWindowTrace("metacore.window: subclass window proc"); - MetaCoreGetWindowMap()[Impl_->NativeHandle] = Impl_.get(); - Impl_->OriginalWindowProc = reinterpret_cast( - SetWindowLongPtr(Impl_->NativeHandle, GWLP_WNDPROC, reinterpret_cast(&MetaCoreWindowSubclassProc)) + // 4. 创建窗口 + Impl_->NativeHandle = CreateWindowExW( + 0, + L"MetaCoreWindowClass", + wideTitle.c_str(), + WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, CW_USEDEFAULT, + rect.right - rect.left, rect.bottom - rect.top, + nullptr, nullptr, GetModuleHandle(nullptr), nullptr ); + if (!Impl_->NativeHandle) { + MetaCoreWindowTrace("metacore.window: CreateWindowExW failed"); + return false; + } + + ShowWindow(Impl_->NativeHandle, SW_SHOW); + UpdateWindow(Impl_->NativeHandle); + + MetaCoreWindowTrace("metacore.window: window created"); + + // 创建 OpenGL 上下文 + Impl_->hDC = GetDC(Impl_->NativeHandle); + PIXELFORMATDESCRIPTOR pfd = { + sizeof(PIXELFORMATDESCRIPTOR), + 1, + PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, + PFD_TYPE_RGBA, + 32, + 0, 0, 0, 0, 0, 0, + 0, + 0, + 0, + 0, 0, 0, 0, + 24, + 8, + 0, + PFD_MAIN_PLANE, + 0, + 0, 0, 0 + }; + int pixelFormat = ChoosePixelFormat(Impl_->hDC, &pfd); + SetPixelFormat(Impl_->hDC, pixelFormat, &pfd); + Impl_->hGLRC = wglCreateContext(Impl_->hDC); + wglMakeCurrent(Impl_->hDC, Impl_->hGLRC); + + MetaCoreWindowTrace("metacore.window: OpenGL context created and made current"); + + MetaCoreGetWindowMap()[Impl_->NativeHandle] = Impl_.get(); + Impl_->CloseRequested = false; Impl_->LastFrameTime = std::chrono::steady_clock::now(); Impl_->Initialized = true; @@ -263,22 +242,23 @@ void MetaCoreWindow::Shutdown() { return; } + if (Impl_->hGLRC) { + wglMakeCurrent(nullptr, nullptr); + wglDeleteContext(Impl_->hGLRC); + Impl_->hGLRC = nullptr; + } + if (Impl_->hDC && Impl_->NativeHandle) { + ReleaseDC(Impl_->NativeHandle, Impl_->hDC); + Impl_->hDC = nullptr; + } + if (Impl_->NativeHandle != nullptr) { MetaCoreGetWindowMap().erase(Impl_->NativeHandle); - if (Impl_->OriginalWindowProc != nullptr) { - SetWindowLongPtr(Impl_->NativeHandle, GWLP_WNDPROC, reinterpret_cast(Impl_->OriginalWindowProc)); - } + DestroyWindow(Impl_->NativeHandle); } - if (Impl_->WindowFrameworkHandle != nullptr) { - Impl_->Framework.close_window(Impl_->WindowFrameworkHandle); - Impl_->WindowFrameworkHandle = nullptr; - } - - Impl_->GraphicsWindowHandle = nullptr; Impl_->NativeHandle = nullptr; Impl_->OriginalWindowProc = nullptr; - Impl_->Framework.close_framework(); Impl_->Initialized = false; } @@ -296,8 +276,11 @@ void MetaCoreWindow::BeginFrame() { Impl_->Input.BeginFrame(); - if (Impl_->GraphicsWindowHandle != nullptr) { - Impl_->GraphicsWindowHandle->process_events(); + // Win32 消息循环 + MSG msg; + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { + TranslateMessage(&msg); + DispatchMessage(&msg); } Impl_->Input.SetKeyState(MetaCoreInputKey::LeftAlt, MetaCoreIsVirtualKeyDown(VK_LMENU)); @@ -323,27 +306,12 @@ bool MetaCoreWindow::ShouldClose() const { void MetaCoreWindow::RequestClose() { Impl_->CloseRequested = true; - if (Impl_->GraphicsWindowHandle != nullptr) { - Impl_->GraphicsWindowHandle->request_close(); - } } void* MetaCoreWindow::GetNativeWindowHandle() const { return Impl_->NativeHandle; } -void* MetaCoreWindow::GetNativeFrameworkHandle() const { - return &Impl_->Framework; -} - -void* MetaCoreWindow::GetNativeWindowFrameworkHandle() const { - return Impl_->WindowFrameworkHandle; -} - -void* MetaCoreWindow::GetNativeGraphicsWindowHandle() const { - return Impl_->GraphicsWindowHandle; -} - MetaCoreInput& MetaCoreWindow::GetInput() { return Impl_->Input; } @@ -357,12 +325,13 @@ float MetaCoreWindow::GetDeltaSeconds() const { } std::pair MetaCoreWindow::GetWindowSize() const { - if (Impl_->GraphicsWindowHandle == nullptr) { + if (Impl_->NativeHandle == nullptr) { return {0, 0}; } - const WindowProperties windowProperties = Impl_->GraphicsWindowHandle->get_properties(); - return {windowProperties.get_x_size(), windowProperties.get_y_size()}; + RECT rect{}; + GetClientRect(Impl_->NativeHandle, &rect); + return { rect.right - rect.left, rect.bottom - rect.top }; } std::pair MetaCoreWindow::GetFramebufferSize() const { diff --git a/Source/MetaCorePlatform/Public/MetaCorePlatform/MetaCoreWindow.h b/Source/MetaCorePlatform/Public/MetaCorePlatform/MetaCoreWindow.h index 5b29e7b..d809b7a 100644 --- a/Source/MetaCorePlatform/Public/MetaCorePlatform/MetaCoreWindow.h +++ b/Source/MetaCorePlatform/Public/MetaCorePlatform/MetaCoreWindow.h @@ -30,9 +30,6 @@ public: void RequestClose(); [[nodiscard]] void* GetNativeWindowHandle() const; - [[nodiscard]] void* GetNativeFrameworkHandle() const; - [[nodiscard]] void* GetNativeWindowFrameworkHandle() const; - [[nodiscard]] void* GetNativeGraphicsWindowHandle() const; [[nodiscard]] MetaCoreInput& GetInput(); [[nodiscard]] const MetaCoreInput& GetInput() const; diff --git a/Source/MetaCoreRender/Private/MetaCoreEditorViewportRenderer.cpp b/Source/MetaCoreRender/Private/MetaCoreEditorViewportRenderer.cpp index 79f9768..9966f4c 100644 --- a/Source/MetaCoreRender/Private/MetaCoreEditorViewportRenderer.cpp +++ b/Source/MetaCoreRender/Private/MetaCoreEditorViewportRenderer.cpp @@ -44,10 +44,13 @@ bool MetaCoreEditorViewportRenderer::Initialize(MetaCoreRenderDevice& renderDevi Shutdown(); MetaCoreTrace("metacore.render: viewport scene runtime bind begin"); + // 彻底剔除 Panda3D:不再初始化 Panda3D 场景桥接器 + /* if (!SceneBridge_.Initialize(renderDevice)) { MetaCoreTrace("metacore.render: viewport scene runtime bind failed"); return false; } + */ if (!FilamentSceneBridge_.Initialize(window)) { MetaCoreTrace("metacore.render: viewport filament scene runtime bind failed"); @@ -63,7 +66,6 @@ bool MetaCoreEditorViewportRenderer::Initialize(MetaCoreRenderDevice& renderDevi void MetaCoreEditorViewportRenderer::Shutdown() { - SceneBridge_.Shutdown(); FilamentSceneBridge_.Shutdown(); RenderDevice_ = nullptr; ViewportRect_ = MetaCoreViewportRect{}; @@ -84,6 +86,9 @@ void MetaCoreEditorViewportRenderer::RenderSceneToViewport(const MetaCoreScene& RenderDevice_->SetSceneViewportRect(ViewportRect_); + // 动态调整离屏纹理大小以匹配 ImGui 视口 + FilamentSceneBridge_.Resize(ViewportRect_.Width, ViewportRect_.Height); + // 更新并渲染 Filament 桥接器 FilamentSceneBridge_.ApplySceneView(sceneView); FilamentSceneBridge_.SyncScene(scene, false); @@ -92,7 +97,6 @@ void MetaCoreEditorViewportRenderer::RenderSceneToViewport(const MetaCoreScene& void MetaCoreEditorViewportRenderer::SetProjectRootPath(const std::filesystem::path& projectRootPath) { - SceneBridge_.SetProjectRootPath(projectRootPath); FilamentSceneBridge_.SetProjectRootPath(projectRootPath); } @@ -100,8 +104,12 @@ uint32_t MetaCoreEditorViewportRenderer::GetFilamentGLTextureId() const { return FilamentSceneBridge_.GetGLTextureId(); } +void* MetaCoreEditorViewportRenderer::GetFilamentTexturePointer() const { + return FilamentSceneBridge_.GetFilamentTexturePointer(); +} + bool MetaCoreEditorViewportRenderer::TryGetObjectWorldMatrix(MetaCoreId objectId, glm::mat4& worldMatrix) const { - return SceneBridge_.TryGetObjectWorldMatrix(objectId, worldMatrix); + return FilamentSceneBridge_.TryGetObjectWorldMatrix(objectId, worldMatrix); } } // namespace MetaCore diff --git a/Source/MetaCoreRender/Private/MetaCoreFilamentSceneBridge.cpp b/Source/MetaCoreRender/Private/MetaCoreFilamentSceneBridge.cpp index f37bd4c..2636a15 100644 --- a/Source/MetaCoreRender/Private/MetaCoreFilamentSceneBridge.cpp +++ b/Source/MetaCoreRender/Private/MetaCoreFilamentSceneBridge.cpp @@ -305,6 +305,49 @@ public: return GLTextureId_; } + void Resize(int width, int height) { + if (width <= 0 || height <= 0) return; + + if (RenderTarget_) Engine_->destroy(RenderTarget_); + if (FilamentTexture_) Engine_->destroy(FilamentTexture_); + if (DepthTexture_) Engine_->destroy(DepthTexture_); + if (GLTextureId_) glDeleteTextures(1, &GLTextureId_); + + 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); + + 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_); + + 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; } @@ -393,6 +436,14 @@ 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); } diff --git a/Source/MetaCoreRender/Private/MetaCoreRenderDevice.cpp b/Source/MetaCoreRender/Private/MetaCoreRenderDevice.cpp index fb65c91..0e9b77c 100644 --- a/Source/MetaCoreRender/Private/MetaCoreRenderDevice.cpp +++ b/Source/MetaCoreRender/Private/MetaCoreRenderDevice.cpp @@ -59,55 +59,7 @@ bool MetaCoreRenderDevice::Initialize(MetaCoreWindow& window) { if (Impl_->Initialized) { return true; } - - auto* frameworkHandle = static_cast(window.GetNativeFrameworkHandle()); - auto* windowFrameworkHandle = static_cast(window.GetNativeWindowFrameworkHandle()); - auto* graphicsWindowHandle = static_cast(window.GetNativeGraphicsWindowHandle()); - if (frameworkHandle == nullptr || windowFrameworkHandle == nullptr || graphicsWindowHandle == nullptr) { - return false; - } - Impl_->Window = &window; - Impl_->Framework = frameworkHandle; - Impl_->WindowFrameworkHandle = windowFrameworkHandle; - Impl_->GraphicsWindowHandle = graphicsWindowHandle; - Impl_->GraphicsEngineHandle = frameworkHandle->get_graphics_engine(); - if (Impl_->GraphicsEngineHandle == nullptr) { - return false; - } - - Impl_->GraphicsEngineHandle->set_auto_flip(false); - Impl_->GraphicsEngineHandle->open_windows(); - - if (Impl_->WindowFrameworkHandle->get_display_region_2d() != nullptr) { - Impl_->WindowFrameworkHandle->get_display_region_2d()->set_active(false); - } - - Impl_->SceneDisplayRegion = Impl_->WindowFrameworkHandle->get_display_region_3d(); - if (Impl_->SceneDisplayRegion == nullptr) { - return false; - } - - Impl_->GraphicsWindowHandle->set_clear_color_active(true); - Impl_->GraphicsWindowHandle->set_clear_color(LColor(0.38F, 0.48F, 0.62F, 1.0F)); - - PT(PandaNode) sceneRootNode = new PandaNode("MetaCoreSceneRoot"); - Impl_->SceneRoot = Impl_->WindowFrameworkHandle->get_render().attach_new_node(sceneRootNode); - Impl_->SceneRoot.set_shader_auto(); - - Impl_->EditorCamera = Impl_->WindowFrameworkHandle->make_camera(); - Impl_->SceneDisplayRegion->set_camera(Impl_->EditorCamera); - Impl_->SceneDisplayRegion->set_sort(0); - Impl_->SceneDisplayRegion->set_scissor_enabled(true); - Impl_->SceneDisplayRegion->set_clear_color_active(false); - - if (auto* cameraNode = DCAST(Camera, Impl_->EditorCamera.node()); cameraNode != nullptr) { - PT(PerspectiveLens) lens = new PerspectiveLens(); - lens->set_fov(60.0F); - lens->set_near_far(0.05F, 500.0F); - cameraNode->set_lens(lens); - } - Impl_->Initialized = true; return true; } @@ -149,70 +101,7 @@ void MetaCoreRenderDevice::PresentFrame() const { } void MetaCoreRenderDevice::SetSceneViewportRect(const MetaCoreViewportRect& viewportRect) { - if (Impl_->SceneDisplayRegion == nullptr || Impl_->Window == nullptr) { - return; - } - - const auto [framebufferWidth, framebufferHeight] = Impl_->Window->GetFramebufferSize(); - if (framebufferWidth <= 0 || framebufferHeight <= 0 || viewportRect.Width <= 1.0F || viewportRect.Height <= 1.0F) { - Impl_->SceneDisplayRegion->set_active(false); - return; - } - - const float clampedLeft = std::clamp(viewportRect.Left / static_cast(framebufferWidth), 0.0F, 1.0F); - const float clampedRight = std::clamp((viewportRect.Left + viewportRect.Width) / static_cast(framebufferWidth), 0.0F, 1.0F); - const float clampedTop = std::clamp(viewportRect.Top / static_cast(framebufferHeight), 0.0F, 1.0F); - const float clampedBottom = std::clamp((viewportRect.Top + viewportRect.Height) / static_cast(framebufferHeight), 0.0F, 1.0F); - - Impl_->SceneDisplayRegion->set_active(true); - Impl_->SceneDisplayRegion->set_dimensions( - clampedLeft, - clampedRight, - 1.0F - clampedBottom, - 1.0F - clampedTop - ); - - if (auto* cameraNode = DCAST(Camera, Impl_->EditorCamera.node()); cameraNode != nullptr) { - if (auto* perspectiveLens = DCAST(PerspectiveLens, cameraNode->get_lens()); perspectiveLens != nullptr) { - perspectiveLens->set_aspect_ratio(viewportRect.Width / viewportRect.Height); - } - } -} - -void* MetaCoreRenderDevice::GetNativeWindowFrameworkHandle() const { - return Impl_->WindowFrameworkHandle; -} - -void* MetaCoreRenderDevice::GetNativeSceneRootHandle() const { - return Impl_->SceneRoot.is_empty() ? nullptr : static_cast(&Impl_->SceneRoot); -} - -void* MetaCoreRenderDevice::GetNativeEditorCameraHandle() const { - return Impl_->EditorCamera.is_empty() ? nullptr : static_cast(&Impl_->EditorCamera); -} - -bool MetaCoreRenderDevice::TryGetEditorCameraMatrices(glm::mat4& viewMatrix, glm::mat4& projectionMatrix) const { - if (!Impl_->Initialized || Impl_->EditorCamera.is_empty()) { - return false; - } - - auto* cameraNode = DCAST(Camera, Impl_->EditorCamera.node()); - if (cameraNode == nullptr) { - return false; - } - - auto* lens = cameraNode->get_lens(); - if (lens == nullptr) { - return false; - } - - // view = inverse of camera world matrix (Panda world → Panda camera space). - const glm::mat4 cameraWorldMatrix = MetaCoreConvertPandaMatrixToGlm(Impl_->EditorCamera.get_mat(Impl_->SceneRoot)); - viewMatrix = glm::inverse(cameraWorldMatrix); - - // Panda's native projection matrix works correctly once mathematically transposed. - projectionMatrix = MetaCoreConvertPandaMatrixToGlm(lens->get_projection_mat()); - return true; + // 已废弃 Panda3D 实现,视口管理已移至 Filament 链 } } // namespace MetaCore diff --git a/Source/MetaCoreRender/Public/MetaCoreRender/MetaCoreEditorViewportRenderer.h b/Source/MetaCoreRender/Public/MetaCoreRender/MetaCoreEditorViewportRenderer.h index 6463c7b..4fd84f5 100644 --- a/Source/MetaCoreRender/Public/MetaCoreRender/MetaCoreEditorViewportRenderer.h +++ b/Source/MetaCoreRender/Public/MetaCoreRender/MetaCoreEditorViewportRenderer.h @@ -1,6 +1,5 @@ #pragma once -#include "MetaCoreRender/MetaCorePandaSceneBridge.h" #include "MetaCoreRender/MetaCoreFilamentSceneBridge.h" #include "MetaCoreRender/MetaCoreRenderTypes.h" @@ -22,12 +21,12 @@ public: void RenderSceneToViewport(const MetaCoreScene& scene, const MetaCoreSceneView& sceneView); void SetProjectRootPath(const std::filesystem::path& projectRootPath); [[nodiscard]] uint32_t GetFilamentGLTextureId() const; + [[nodiscard]] void* GetFilamentTexturePointer() const; [[nodiscard]] bool TryGetObjectWorldMatrix(MetaCoreId objectId, glm::mat4& worldMatrix) const; private: MetaCoreRenderDevice* RenderDevice_ = nullptr; - MetaCorePandaSceneBridge SceneBridge_{}; MetaCoreFilamentSceneBridge FilamentSceneBridge_{}; MetaCoreViewportRect ViewportRect_{}; diff --git a/Source/MetaCoreRender/Public/MetaCoreRender/MetaCoreFilamentSceneBridge.h b/Source/MetaCoreRender/Public/MetaCoreRender/MetaCoreFilamentSceneBridge.h index b6f904a..b3d7a4b 100644 --- a/Source/MetaCoreRender/Public/MetaCoreRender/MetaCoreFilamentSceneBridge.h +++ b/Source/MetaCoreRender/Public/MetaCoreRender/MetaCoreFilamentSceneBridge.h @@ -24,11 +24,13 @@ public: bool Initialize(MetaCoreWindow& window); void Shutdown(); + void Resize(int width, int height); 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]] void* GetFilamentTexturePointer() const; [[nodiscard]] bool TryGetObjectWorldMatrix(MetaCoreId objectId, glm::mat4& worldMatrix) const; [[nodiscard]] bool HasRuntimeSyncFailure() const; diff --git a/Source/MetaCoreRender/Public/MetaCoreRender/MetaCoreRenderDevice.h b/Source/MetaCoreRender/Public/MetaCoreRender/MetaCoreRenderDevice.h index 6229fba..a1c89ec 100644 --- a/Source/MetaCoreRender/Public/MetaCoreRender/MetaCoreRenderDevice.h +++ b/Source/MetaCoreRender/Public/MetaCoreRender/MetaCoreRenderDevice.h @@ -23,11 +23,6 @@ public: void PresentFrame() const; void SetSceneViewportRect(const MetaCoreViewportRect& viewportRect); - [[nodiscard]] void* GetNativeWindowFrameworkHandle() const; - [[nodiscard]] void* GetNativeSceneRootHandle() const; - [[nodiscard]] void* GetNativeEditorCameraHandle() const; - [[nodiscard]] bool TryGetEditorCameraMatrices(glm::mat4& viewMatrix, glm::mat4& projectionMatrix) const; - private: class MetaCoreRenderDeviceImpl; diff --git a/tests/FilamentImGuiDemo.cpp b/tests/FilamentImGuiDemo.cpp new file mode 100644 index 0000000..1f7efe0 --- /dev/null +++ b/tests/FilamentImGuiDemo.cpp @@ -0,0 +1,171 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "MetaCoreRender/MetaCoreImGuiHelper.h" +#include +#include +#include +#include + +using namespace filament; + +LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { + switch (message) { + case WM_DESTROY: + PostQuitMessage(0); + return 0; + } + return DefWindowProc(hWnd, message, wParam, lParam); +} + +int main() { + std::cout << "[Demo] Starting..." << std::endl; + + HINSTANCE hInstance = GetModuleHandle(nullptr); + int nCmdShow = SW_SHOW; + + // 1. 注册窗口类 + std::cout << "[Demo] Registering window class..." << std::endl; + WNDCLASSEXW wcex = {0}; + wcex.cbSize = sizeof(WNDCLASSEXW); + wcex.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; + wcex.lpfnWndProc = WndProc; + wcex.hInstance = hInstance; + wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); + wcex.lpszClassName = L"FilamentImGuiDemoClass"; + RegisterClassExW(&wcex); + + // 2. 创建窗口 + std::cout << "[Demo] Creating window..." << std::endl; + HWND hWnd = CreateWindowExW(0, L"FilamentImGuiDemoClass", L"Filament + ImGui 离屏渲染最小化 Demo", WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, CW_USEDEFAULT, 1280, 720, nullptr, nullptr, hInstance, nullptr); + + if (!hWnd) { + std::cout << "[Demo] Failed to create window!" << std::endl; + return -1; + } + + ShowWindow(hWnd, nCmdShow); + UpdateWindow(hWnd); + + // 3. 初始化 Filament + std::cout << "[Demo] Creating Filament Engine (OpenGL)..." << std::endl; + Engine* engine = Engine::create(Engine::Backend::OPENGL); + if (!engine) { + std::cout << "[Demo] Failed to create Engine!" << std::endl; + return -1; + } + + std::cout << "[Demo] Creating Renderer..." << std::endl; + Renderer* renderer = engine->createRenderer(); + + std::cout << "[Demo] Creating SwapChain..." << std::endl; + SwapChain* swapChain = engine->createSwapChain(hWnd); + + std::cout << "[Demo] Creating Scene..." << std::endl; + Scene* scene = engine->createScene(); + + std::cout << "[Demo] Creating View..." << std::endl; + View* view = engine->createView(); + view->setScene(scene); + + std::cout << "[Demo] Creating Camera..." << std::endl; + utils::Entity cameraEntity = utils::EntityManager::get().create(); + Camera* camera = engine->createCamera(cameraEntity); + view->setCamera(camera); + view->setViewport({0, 0, 1280, 720}); + + std::cout << "[Demo] Creating Skybox..." << std::endl; + Skybox* skybox = Skybox::Builder().color({1.0f, 0.0f, 1.0f, 1.0f}).build(*engine); + scene->setSkybox(skybox); + + // 4. 创建离屏 RenderTarget + std::cout << "[Demo] Creating offscreen texture..." << std::endl; + Texture* viewportTexture = Texture::Builder() + .width(800).height(600).levels(1) + .usage(Texture::Usage::COLOR_ATTACHMENT | Texture::Usage::SAMPLEABLE) + .format(Texture::InternalFormat::RGBA8) + .build(*engine); + + std::cout << "[Demo] Creating RenderTarget..." << std::endl; + RenderTarget* renderTarget = RenderTarget::Builder() + .texture(RenderTarget::AttachmentPoint::COLOR, viewportTexture) + .build(*engine); + + std::cout << "[Demo] Creating offscreen View..." << std::endl; + View* offscreenView = engine->createView(); + offscreenView->setScene(scene); + offscreenView->setCamera(camera); + offscreenView->setRenderTarget(renderTarget); + offscreenView->setViewport({0, 0, 800, 600}); + offscreenView->setPostProcessingEnabled(true); + + // 5. 初始化 ImGui + std::cout << "[Demo] Initializing ImGui..." << std::endl; + IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + ImGuiIO& io = ImGui::GetIO(); + io.DisplaySize = ImVec2(1280, 720); + + std::cout << "[Demo] Creating UI View..." << std::endl; + View* uiView = engine->createView(); + uiView->setViewport({0, 0, 1280, 720}); + uiView->setPostProcessingEnabled(false); + + std::cout << "[Demo] Creating MetaCoreImGuiHelper..." << std::endl; + MetaCore::MetaCoreImGuiHelper imguiHelper(engine, uiView, "C:\\Windows\\Fonts\\msyh.ttc"); + + std::cout << "[Demo] Setting Display Size..." << std::endl; + imguiHelper.setDisplaySize(1280, 720); + + std::cout << "[Demo] Entering message loop..." << std::endl; + MSG msg = {0}; + bool quit = false; + while (!quit) { + while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) { + if (msg.message == WM_QUIT) quit = true; + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + if (renderer->beginFrame(swapChain)) { + // 1. 渲染离屏 3D 场景 + renderer->render(offscreenView); + + // 2. 构建 ImGui 界面 + ImGui::NewFrame(); + + ImGui::SetNextWindowSize(ImVec2(820, 640), ImGuiCond_FirstUseEver); + ImGui::Begin("3D Viewport"); + + ImGui::Image((void*)viewportTexture, ImVec2(800, 600), ImVec2(0, 1), ImVec2(1, 0)); + + ImGui::End(); + + ImGui::Render(); + + // 3. 处理 ImGui 命令 + imguiHelper.processImGuiCommands(ImGui::GetDrawData(), io); + + // 4. 渲染 UI + renderer->render(uiView); + + renderer->endFrame(); + } + Sleep(16); + } + + std::cout << "[Demo] Cleaning up..." << std::endl; + // 省略详细清理,由操作系统回收 + + return 0; +}