From 107dbb6861cd4ca7cd1d79c699199dd234207234 Mon Sep 17 00:00:00 2001 From: ayuan9957 <107920784+ayuan9957@users.noreply.github.com> Date: Fri, 15 May 2026 17:12:24 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=8C=E6=88=90=E5=B7=A5=E5=85=B7?= =?UTF-8?q?=E6=A0=8F=E6=B1=89=E5=8C=96=EF=BC=8C=E5=8E=BB=E6=8E=89=E8=A7=86?= =?UTF-8?q?=E5=8F=A3=E9=BB=84=E8=89=B2=E6=A1=86=E5=92=8C=E5=8E=9F=E7=82=B9?= =?UTF-8?q?=E8=BD=B4=EF=BC=8C=E9=BB=98=E8=AE=A4=E5=8A=A0=E8=BD=BD=20box1.g?= =?UTF-8?q?lb=EF=BC=8C=E8=A7=A3=E5=86=B3=E5=B4=A9=E6=BA=83=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Library/Cooked/Windows/CookManifest.bin | Bin 3397 -> 3721 bytes SandboxProject/Scenes/Main.mcscene | Bin 3398 -> 7695 bytes .../Private/MetaCoreEditorApp.cpp | 127 ++---------------- .../MetaCoreSceneInteractionService.cpp | 55 ++++---- .../Private/MetaCoreWindow.cpp | 39 ------ .../MetaCoreEditorViewportRenderer.cpp | 7 +- .../Private/MetaCoreFilamentSceneBridge.cpp | 102 +++++++++----- .../MetaCoreEditorViewportRenderer.h | 1 + .../MetaCoreFilamentSceneBridge.h | 2 +- .../MetaCoreScene/Private/MetaCoreScene.cpp | 4 +- 10 files changed, 116 insertions(+), 221 deletions(-) diff --git a/SandboxProject/Library/Cooked/Windows/CookManifest.bin b/SandboxProject/Library/Cooked/Windows/CookManifest.bin index acbf5be95cb20f1731d1283571273032e28d80c3..24e37e79d21726989f5d88b59e835f1054a899c3 100644 GIT binary patch delta 128 zcmX>q)hRncoHL7$0Sve|DyZ^K&S$j~*mmgf55GbWi>WUsWhLuBxiNV!tK{TKEHNfY zX30j$#%UJ1CaLCzx+WIJ7P^+Esg}ByMrMg-#ztwWCMg#2Nh!ujmWFAGrj{wjX=bUD f^Vw85eooxec;~y+-pPKfk{r*!U5@-U(RwccP7o~2 delta 20 YcmeB_Jt{RpoKuaL0Sve{DyZ@T04m)o(LlyV15ohky7LdRR<-IVmey|H%z51_%hwFD*(=^++tv;DCypGCFi&ho=U| z#+T7dOqr6C-I(Q=_~j<2G4~3f8#0-hrJE^IaWpT{E$s? zvoz}x7Cs?Xh!7)4sr2NtoU)9JlV5XAn>>e|gB#)w-~5!+oXL`0c9R>q#LeZPMv6gc z$KvADl45c}?^9HUBj7~7)z_tKQOZCi4Nv&XkTJj$VcwiQmCi$ioXJE)r zPT=vKJcmPyk!7+BtFZ_#R5{f53}J~mWt0DMSh1Wv!*gJ=HD?RoAE@c@fZ2j0NYn*k zuA_!$moWOxni*-ImiEl<>=_?Bn9)@5I4j8GlTWb-u!JP$Wl#RcVF~iA1JJX++{VV6 z?V)(`8+M%m^gPfNc4=v9zyL_Ir=sWCz@8Un5#VvmNi51$a7s-~&d&n|f<2Rh!(@BT jhRLhg#3t);XmQM%DG3buGq#fxIHV^ZXH%TKmS-jaR#FII delta 186 zcmeCTIVLq>yAj{)`3lzSJ$LlFpZ&(O-{ue(0|W%;mlh?bdL$NSa6m;K*4SQHb#-6N z#+T7dOba+ByD`f#x$#a;W9}6|H)Jw1OE=R5j>(Q(VqA<+?Lh7Z7Dvu4><~WlAddCircleFilled(originScreenPoint, 3.5F, IM_COL32(255, 255, 255, 220)); - drawList->AddLine(originScreenPoint, ImVec2(originScreenPoint.x + 16.0F, originScreenPoint.y), xColor, 2.0F); - drawList->AddLine(originScreenPoint, ImVec2(originScreenPoint.x, originScreenPoint.y - 16.0F), yColor, 2.0F); - drawList->AddLine(originScreenPoint, ImVec2(originScreenPoint.x - 12.0F, originScreenPoint.y + 12.0F), zColor, 2.0F); - drawList->AddText(ImVec2(originScreenPoint.x + 18.0F, originScreenPoint.y - 8.0F), xColor, "X"); - drawList->AddText(ImVec2(originScreenPoint.x - 4.0F, originScreenPoint.y - 30.0F), yColor, "Y"); - drawList->AddText(ImVec2(originScreenPoint.x - 24.0F, originScreenPoint.y + 10.0F), zColor, "Z"); + // 用户要求去掉小 XYZ 轴和原点指示 + return; } void MetaCoreDrawViewportGridOverlay( @@ -281,83 +263,8 @@ void MetaCoreDrawSelectionBoundsOverlay( const MetaCoreSceneView& sceneView, const MetaCoreSceneViewportState& viewportState ) { - const auto& selectedObjectIds = editorContext.GetSelectedObjectIds(); - if (selectedObjectIds.empty()) { - return; - } - - ImDrawList* drawList = ImGui::GetForegroundDrawList(); - const ImU32 boxColor = IM_COL32(255, 204, 64, 220); - const ImU32 activeBoxColor = IM_COL32(255, 235, 120, 255); - const ImU32 fillColor = IM_COL32(255, 204, 64, 24); - bool hasGroupBounds = false; - ImVec2 groupMin(FLT_MAX, FLT_MAX); - ImVec2 groupMax(-FLT_MAX, -FLT_MAX); - - for (const MetaCoreId selectedObjectId : selectedObjectIds) { - const MetaCoreGameObject selectedObject = scene.FindGameObject(selectedObjectId); - if (!selectedObject) { - continue; - } - - const glm::vec3 halfExtents( - std::max(std::abs(selectedObject.GetComponent().Scale.x), 0.5F) * 0.5F, - std::max(std::abs(selectedObject.GetComponent().Scale.y), 0.5F) * 0.5F, - std::max(std::abs(selectedObject.GetComponent().Scale.z), 0.5F) * 0.5F - ); - const glm::vec3 center = selectedObject.GetComponent().Position; - - const std::array corners = { - center + glm::vec3(-halfExtents.x, -halfExtents.y, -halfExtents.z), - center + glm::vec3( halfExtents.x, -halfExtents.y, -halfExtents.z), - center + glm::vec3(-halfExtents.x, halfExtents.y, -halfExtents.z), - center + glm::vec3( halfExtents.x, halfExtents.y, -halfExtents.z), - center + glm::vec3(-halfExtents.x, -halfExtents.y, halfExtents.z), - center + glm::vec3( halfExtents.x, -halfExtents.y, halfExtents.z), - center + glm::vec3(-halfExtents.x, halfExtents.y, halfExtents.z), - center + glm::vec3( halfExtents.x, halfExtents.y, halfExtents.z) - }; - - bool anyPointVisible = false; - ImVec2 minPoint(FLT_MAX, FLT_MAX); - ImVec2 maxPoint(-FLT_MAX, -FLT_MAX); - for (const glm::vec3& corner : corners) { - ImVec2 screenPoint{}; - if (!MetaCoreProjectWorldPointToViewport(sceneView, viewportState, corner, screenPoint)) { - continue; - } - anyPointVisible = true; - minPoint.x = std::min(minPoint.x, screenPoint.x); - minPoint.y = std::min(minPoint.y, screenPoint.y); - maxPoint.x = std::max(maxPoint.x, screenPoint.x); - maxPoint.y = std::max(maxPoint.y, screenPoint.y); - } - - if (!anyPointVisible) { - continue; - } - - hasGroupBounds = true; - groupMin.x = std::min(groupMin.x, minPoint.x); - groupMin.y = std::min(groupMin.y, minPoint.y); - groupMax.x = std::max(groupMax.x, maxPoint.x); - groupMax.y = std::max(groupMax.y, maxPoint.y); - - const bool isActive = selectedObjectId == editorContext.GetActiveObjectId(); - const ImU32 strokeColor = isActive ? activeBoxColor : boxColor; - drawList->AddRectFilled(minPoint, maxPoint, fillColor, 2.0F); - drawList->AddRect(minPoint, maxPoint, strokeColor, 2.0F, 0, isActive ? 2.0F : 1.5F); - drawList->AddText(ImVec2(minPoint.x, minPoint.y - 18.0F), strokeColor, selectedObject.GetName().c_str()); - } - - if (selectedObjectIds.size() > 1 && hasGroupBounds) { - const ImU32 groupStrokeColor = IM_COL32(255, 245, 180, 220); - const ImU32 groupFillColor = IM_COL32(255, 245, 180, 10); - drawList->AddRectFilled(groupMin, groupMax, groupFillColor, 4.0F); - drawList->AddRect(groupMin, groupMax, groupStrokeColor, 4.0F, 0, 2.0F); - const std::string groupLabel = "Selection x" + std::to_string(selectedObjectIds.size()); - drawList->AddText(ImVec2(groupMin.x, groupMin.y - 34.0F), groupStrokeColor, groupLabel.c_str()); - } + // 用户要求去掉左下角的黄色框和文字 + return; } void MetaCoreDrawCompatibilityScenePreviewOverlay( @@ -576,7 +483,7 @@ void MetaCoreConfigureChineseFont() { candidatePath.string().c_str(), 17.0F, nullptr, - io.Fonts->GetGlyphRangesChineseSimplifiedCommon() + io.Fonts->GetGlyphRangesChineseFull() ); if (chineseFont != nullptr) { io.FontDefault = chineseFont; @@ -744,7 +651,7 @@ int MetaCoreEditorApp::Run() { while (!Window_.ShouldClose()) { Window_.BeginFrame(); - ImGui_ImplOpenGL3_NewFrame(); + // Filament 接管,不再使用 OpenGL3 后端的 NewFrame ImGui_ImplWin32_NewFrame(); ImGui::NewFrame(); if (GMetaCoreEnableImGuizmo) { @@ -755,18 +662,13 @@ int MetaCoreEditorApp::Run() { ImGui::Render(); - // 1. Filament 渲染 3D 视口到离屏纹理 + // 1. 收集并更新场景数据(但不在这里渲染) MetaCoreSceneView sceneView = EditorContext_->GetCameraController().BuildSceneView(); sceneView.SelectedObjectId = EditorContext_->GetSelectedObjectId(); ViewportRenderer_.RenderSceneToViewport(Scene_, sceneView); - // 2. ImGui 渲染 UI 到屏幕 (包含 3D 纹理的显示) - ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); - - // 3. 交换缓冲区 (因为去掉了 Panda3D 的 flip_frame) - HDC hdc = GetDC(static_cast(Window_.GetNativeWindowHandle())); - SwapBuffers(hdc); - ReleaseDC(static_cast(Window_.GetNativeWindowHandle()), hdc); + // 2. 统一在一个 Frame 内渲染离屏 3D 和上屏 UI + ViewportRenderer_.RenderAll(); Window_.EndFrame(); } @@ -817,17 +719,10 @@ bool MetaCoreEditorApp::InitializeImGui() { } MetaCoreTraceStartup("metacore.ui: platform backend ready"); - if (!ImGui_ImplOpenGL3_Init("#version 130")) { - MetaCoreTraceStartup("metacore.ui: graphics backend init failed"); - return false; - } - MetaCoreTraceStartup("metacore.ui: graphics backend ready"); - return true; } void MetaCoreEditorApp::ShutdownImGui() { - ImGui_ImplOpenGL3_Shutdown(); ImGui_ImplWin32_Shutdown(); ImGui::DestroyContext(); } @@ -1002,8 +897,8 @@ 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)); + void* texPtr = ViewportRenderer_.GetFilamentTexturePointer(); + ImGui::Image(texPtr, ImVec2(viewportState.Width, viewportState.Height)); SceneInteractionService_.HandleGizmoManipulation(*EditorContext_); diff --git a/Source/MetaCoreEditor/Private/MetaCoreSceneInteractionService.cpp b/Source/MetaCoreEditor/Private/MetaCoreSceneInteractionService.cpp index f17400d..fc53be1 100644 --- a/Source/MetaCoreEditor/Private/MetaCoreSceneInteractionService.cpp +++ b/Source/MetaCoreEditor/Private/MetaCoreSceneInteractionService.cpp @@ -89,19 +89,19 @@ ImGuizmo::OPERATION MetaCoreToImGuizmoOperation(MetaCoreGizmoOperation operation const char* MetaCoreGizmoOperationLabel(MetaCoreGizmoOperation operation) { switch (operation) { - case MetaCoreGizmoOperation::None: return "View"; - case MetaCoreGizmoOperation::Translate: return "Move"; - case MetaCoreGizmoOperation::Rotate: return "Rotate"; - case MetaCoreGizmoOperation::Scale: return "Scale"; - default: return "Unknown"; + case MetaCoreGizmoOperation::None: return "视图"; + case MetaCoreGizmoOperation::Translate: return "移动"; + case MetaCoreGizmoOperation::Rotate: return "旋转"; + case MetaCoreGizmoOperation::Scale: return "缩放"; + default: return "未知"; } } const char* MetaCoreGizmoModeLabel(MetaCoreGizmoMode mode) { switch (mode) { - case MetaCoreGizmoMode::Local: return "Local"; - case MetaCoreGizmoMode::Global: return "Global"; - default: return "Unknown"; + case MetaCoreGizmoMode::Local: return "局部"; + case MetaCoreGizmoMode::Global: return "全局"; + default: return "未知"; } } @@ -467,7 +467,8 @@ void MetaCoreSceneInteractionService::DrawViewportToolbar(MetaCoreEditorContext& } else { ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.15F, 0.17F, 0.20F, 0.7F)); } - const bool clicked = ImGui::Button(label, ImVec2(32.0F, 24.0F)); + // 改为 0.0F 自动宽度,以适应中文 + const bool clicked = ImGui::Button(label, ImVec2(0.0F, 24.0F)); if (selected) { ImGui::PopStyleColor(3); } else { @@ -477,30 +478,30 @@ void MetaCoreSceneInteractionService::DrawViewportToolbar(MetaCoreEditorContext& }; // Tools (Unity-Style Icons/Labels) - if (drawToolbarToggle(" V ", editorContext.GetGizmoOperation() == MetaCoreGizmoOperation::None)) { + if (drawToolbarToggle(" 视图 ", editorContext.GetGizmoOperation() == MetaCoreGizmoOperation::None)) { editorContext.SetGizmoOperation(MetaCoreGizmoOperation::None); } ImGui::SameLine(); - if (drawToolbarToggle(" M ", editorContext.GetGizmoOperation() == MetaCoreGizmoOperation::Translate)) { + if (drawToolbarToggle(" 移动 ", editorContext.GetGizmoOperation() == MetaCoreGizmoOperation::Translate)) { editorContext.SetGizmoOperation(MetaCoreGizmoOperation::Translate); } ImGui::SameLine(); - if (drawToolbarToggle(" R ", editorContext.GetGizmoOperation() == MetaCoreGizmoOperation::Rotate)) { + if (drawToolbarToggle(" 旋转 ", editorContext.GetGizmoOperation() == MetaCoreGizmoOperation::Rotate)) { editorContext.SetGizmoOperation(MetaCoreGizmoOperation::Rotate); } ImGui::SameLine(); - if (drawToolbarToggle(" S ", editorContext.GetGizmoOperation() == MetaCoreGizmoOperation::Scale)) { + if (drawToolbarToggle(" 缩放 ", editorContext.GetGizmoOperation() == MetaCoreGizmoOperation::Scale)) { editorContext.SetGizmoOperation(MetaCoreGizmoOperation::Scale); } ImGui::SameLine(0, 12); // Mode Toggles (Unity uses "Global" instead of "World") - if (drawToolbarToggle("Local", editorContext.GetGizmoMode() == MetaCoreGizmoMode::Local)) { + if (drawToolbarToggle(" 局部 ", editorContext.GetGizmoMode() == MetaCoreGizmoMode::Local)) { editorContext.SetGizmoMode(MetaCoreGizmoMode::Local); } ImGui::SameLine(0, 2); - if (drawToolbarToggle("Global", editorContext.GetGizmoMode() == MetaCoreGizmoMode::Global)) { + if (drawToolbarToggle(" 全局 ", editorContext.GetGizmoMode() == MetaCoreGizmoMode::Global)) { editorContext.SetGizmoMode(MetaCoreGizmoMode::Global); } @@ -509,53 +510,53 @@ void MetaCoreSceneInteractionService::DrawViewportToolbar(MetaCoreEditorContext& if (!hasSelection) { ImGui::BeginDisabled(); } - if (drawToolbarToggle(" F ", false)) { + if (drawToolbarToggle(" 聚焦 ", false)) { FocusSelectedObject(editorContext); } if (!hasSelection) { ImGui::EndDisabled(); } ImGui::SameLine(0, 2); - if (drawToolbarToggle(" A ", false)) { + if (drawToolbarToggle(" 全览 ", false)) { FocusVisibleScene(editorContext); } ImGui::SameLine(0, 12); bool showGrid = editorContext.GetShowViewportGrid(); - if (drawToolbarToggle(" G ", showGrid)) { + if (drawToolbarToggle(" 网格 ", showGrid)) { editorContext.SetShowViewportGrid(!showGrid); } ImGui::SameLine(); bool showOrigin = editorContext.GetShowWorldOrigin(); - if (drawToolbarToggle(" O ", showOrigin)) { + if (drawToolbarToggle(" 原点 ", showOrigin)) { editorContext.SetShowWorldOrigin(!showOrigin); } ImGui::SameLine(0, 12); ImGui::TextDisabled( - "Tool: %s | Mode: %s | Grid: %s | Origin: %s | [Q/W/E/R] [Z] [F] [A] [G] [O]", + "工具: %s | 模式: %s | 网格: %s | 原点: %s | [Q/W/E/R] [Z] [F] [A] [G] [O]", MetaCoreGizmoOperationLabel(editorContext.GetGizmoOperation()), MetaCoreGizmoModeLabel(editorContext.GetGizmoMode()), - editorContext.GetShowViewportGrid() ? "On" : "Off", - editorContext.GetShowWorldOrigin() ? "On" : "Off" + editorContext.GetShowViewportGrid() ? "开启" : "关闭", + editorContext.GetShowWorldOrigin() ? "开启" : "关闭" ); ImGui::SameLine(0, 12); const auto& selectedObjectIds = editorContext.GetSelectedObjectIds(); if (selectedObjectIds.empty()) { - ImGui::TextDisabled("Selection: None"); + ImGui::TextDisabled("选中: 无"); } else if (selectedObjectIds.size() == 1) { const MetaCoreGameObject activeObject = editorContext.GetSelectedGameObject(); ImGui::TextDisabled( - "Selection: %s", - activeObject ? activeObject.GetName().c_str() : "" + "选中: %s", + activeObject ? activeObject.GetName().c_str() : "<缺失>" ); } else { const MetaCoreGameObject activeObject = editorContext.GetSelectedGameObject(); ImGui::TextDisabled( - "Selection: %zu objects | Active: %s", + "选中: %zu 个对象 | 激活: %s", selectedObjectIds.size(), - activeObject ? activeObject.GetName().c_str() : "" + activeObject ? activeObject.GetName().c_str() : "<缺失>" ); } } diff --git a/Source/MetaCorePlatform/Private/MetaCoreWindow.cpp b/Source/MetaCorePlatform/Private/MetaCoreWindow.cpp index cd948b1..4abc60d 100644 --- a/Source/MetaCorePlatform/Private/MetaCoreWindow.cpp +++ b/Source/MetaCorePlatform/Private/MetaCoreWindow.cpp @@ -90,8 +90,6 @@ std::unordered_map& MetaCoreGet class MetaCoreWindow::MetaCoreWindowImpl { public: HWND NativeHandle = nullptr; - HDC hDC = nullptr; - HGLRC hGLRC = nullptr; MetaCoreInput Input{}; MetaCoreNativeWindowMessageHandler MessageHandler{}; WNDPROC OriginalWindowProc = nullptr; @@ -187,33 +185,6 @@ bool MetaCoreWindow::Initialize(int width, int height, const std::string& title) 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; @@ -242,16 +213,6 @@ 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); DestroyWindow(Impl_->NativeHandle); diff --git a/Source/MetaCoreRender/Private/MetaCoreEditorViewportRenderer.cpp b/Source/MetaCoreRender/Private/MetaCoreEditorViewportRenderer.cpp index 9966f4c..5113e33 100644 --- a/Source/MetaCoreRender/Private/MetaCoreEditorViewportRenderer.cpp +++ b/Source/MetaCoreRender/Private/MetaCoreEditorViewportRenderer.cpp @@ -89,10 +89,13 @@ void MetaCoreEditorViewportRenderer::RenderSceneToViewport(const MetaCoreScene& // 动态调整离屏纹理大小以匹配 ImGui 视口 FilamentSceneBridge_.Resize(ViewportRect_.Width, ViewportRect_.Height); - // 更新并渲染 Filament 桥接器 + // 更新并同步 Filament 桥接器(但不在这里调用 Render,交由 RenderAll 统一渲染) FilamentSceneBridge_.ApplySceneView(sceneView); FilamentSceneBridge_.SyncScene(scene, false); - FilamentSceneBridge_.Render(); // 恢复 Render 调用,因为现在是离屏渲染 +} + +void MetaCoreEditorViewportRenderer::RenderAll() { + FilamentSceneBridge_.RenderAll(); } diff --git a/Source/MetaCoreRender/Private/MetaCoreFilamentSceneBridge.cpp b/Source/MetaCoreRender/Private/MetaCoreFilamentSceneBridge.cpp index 2636a15..4c27d12 100644 --- a/Source/MetaCoreRender/Private/MetaCoreFilamentSceneBridge.cpp +++ b/Source/MetaCoreRender/Private/MetaCoreFilamentSceneBridge.cpp @@ -3,6 +3,8 @@ #include "MetaCoreScene/MetaCoreScene.h" #include "MetaCoreScene/MetaCoreComponents.h" #include "MetaCoreRender/MetaCoreRenderTypes.h" +#include "MetaCoreRender/MetaCoreImGuiHelper.h" +#include #include #include @@ -59,10 +61,10 @@ public: return false; } - // 创建无窗口的 1x1 交换链 (因为我们是离屏渲染,不需要绑定真实窗口,避免 OpenGL 上下文冲突) - SwapChain_ = Engine_->createSwapChain(1, 1, 0); + // 创建绑定真实窗口的交换链 + SwapChain_ = Engine_->createSwapChain((void*)window.GetNativeWindowHandle()); if (!SwapChain_) { - std::cerr << "Failed to create Filament headless SwapChain!" << std::endl; + std::cerr << "Failed to create Filament SwapChain with window handle!" << std::endl; return false; } @@ -91,27 +93,24 @@ public: View_->setScene(Scene_); View_->setCamera(Camera_); + // 创建 UI 视图 + UIView_ = Engine_->createView(); + + // 创建 ImGuiHelper + ImGuiHelper_ = new MetaCoreImGuiHelper(Engine_, UIView_, "", ImGui::GetCurrentContext()); + // 初始化离屏渲染纹理 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 作为颜色附件 + // 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) - .import(static_cast(GLTextureId_)) .build(*Engine_); - // 3. 创建深度纹理 + // 2. 创建深度纹理 DepthTexture_ = filament::Texture::Builder() .width(static_cast(width)) .height(static_cast(height)) @@ -119,15 +118,18 @@ public: .format(filament::Texture::InternalFormat::DEPTH24) .build(*Engine_); - // 4. 创建 RenderTarget 并绑定 + // 3. 创建 RenderTarget 并绑定 RenderTarget_ = filament::RenderTarget::Builder() .texture(filament::RenderTarget::AttachmentPoint::COLOR, FilamentTexture_) .texture(filament::RenderTarget::AttachmentPoint::DEPTH, DepthTexture_) .build(*Engine_); - // 5. 设置到 View + // 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_); @@ -287,17 +289,40 @@ public: Camera_->setProjection(fov, aspect, nearClip, farClip, filament::Camera::Fov::VERTICAL); } - void Render() { - if (Renderer_ && SwapChain_ && View_) { + void RenderAll() { + if (!Renderer_ || !SwapChain_ || !View_ || !UIView_ || !ImGuiHelper_) { + return; + } + + if (Renderer_->beginFrame(SwapChain_)) { + // 1. 渲染 3D 离屏视口 (输出到 RenderTarget) filament::Renderer::ClearOptions options; - options.clearColor = { 1.0f, 0.0f, 1.0f, 1.0f }; // 粉色,方便辨认 + options.clearColor = { 0.11f, 0.12f, 0.14f, 1.0f }; // 深灰色 options.clear = true; Renderer_->setClearOptions(options); + + Renderer_->render(View_); - if (Renderer_->beginFrame(SwapChain_)) { - Renderer_->render(View_); - Renderer_->endFrame(); + // 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(); } } @@ -308,24 +333,27 @@ public: 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_); + // 【关键修复】:如果大小没有改变,不要重新创建纹理! + // 否则会导致上一帧传给 ImGui 的纹理指针在这一帧被提前销毁,引发 Use-after-free 崩溃。 + if (FilamentTexture_ && + FilamentTexture_->getWidth() == static_cast(width) && + FilamentTexture_->getHeight() == static_cast(height)) { + return; + } - 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); + 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) - .import(static_cast(GLTextureId_)) .build(*Engine_); DepthTexture_ = filament::Texture::Builder() @@ -393,10 +421,14 @@ private: 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_{}; @@ -428,8 +460,8 @@ void MetaCoreFilamentSceneBridge::ApplySceneView(const MetaCoreSceneView& sceneV Impl_->ApplySceneView(sceneView); } -void MetaCoreFilamentSceneBridge::Render() { - Impl_->Render(); +void MetaCoreFilamentSceneBridge::RenderAll() { + Impl_->RenderAll(); } uint32_t MetaCoreFilamentSceneBridge::GetGLTextureId() const { diff --git a/Source/MetaCoreRender/Public/MetaCoreRender/MetaCoreEditorViewportRenderer.h b/Source/MetaCoreRender/Public/MetaCoreRender/MetaCoreEditorViewportRenderer.h index 4fd84f5..046acc1 100644 --- a/Source/MetaCoreRender/Public/MetaCoreRender/MetaCoreEditorViewportRenderer.h +++ b/Source/MetaCoreRender/Public/MetaCoreRender/MetaCoreEditorViewportRenderer.h @@ -19,6 +19,7 @@ public: void Shutdown(); void SetViewportRect(const MetaCoreViewportRect& viewportRect); void RenderSceneToViewport(const MetaCoreScene& scene, const MetaCoreSceneView& sceneView); + void RenderAll(); void SetProjectRootPath(const std::filesystem::path& projectRootPath); [[nodiscard]] uint32_t GetFilamentGLTextureId() const; [[nodiscard]] void* GetFilamentTexturePointer() const; diff --git a/Source/MetaCoreRender/Public/MetaCoreRender/MetaCoreFilamentSceneBridge.h b/Source/MetaCoreRender/Public/MetaCoreRender/MetaCoreFilamentSceneBridge.h index b3d7a4b..e0eec52 100644 --- a/Source/MetaCoreRender/Public/MetaCoreRender/MetaCoreFilamentSceneBridge.h +++ b/Source/MetaCoreRender/Public/MetaCoreRender/MetaCoreFilamentSceneBridge.h @@ -28,7 +28,7 @@ public: void SetProjectRootPath(const std::filesystem::path& projectRootPath); void SyncScene(const MetaCoreScene& scene, bool compatibilityMeshOnly = false); void ApplySceneView(const MetaCoreSceneView& sceneView); - void Render(); + void RenderAll(); [[nodiscard]] uint32_t GetGLTextureId() const; [[nodiscard]] void* GetFilamentTexturePointer() const; diff --git a/Source/MetaCoreScene/Private/MetaCoreScene.cpp b/Source/MetaCoreScene/Private/MetaCoreScene.cpp index 7760a03..b0307ff 100644 --- a/Source/MetaCoreScene/Private/MetaCoreScene.cpp +++ b/Source/MetaCoreScene/Private/MetaCoreScene.cpp @@ -460,7 +460,9 @@ MetaCoreScene MetaCoreCreateDefaultScene() { directionalLight.GetComponent().RotationEulerDegrees = glm::vec3(-45.0F, 30.0F, 0.0F); MetaCoreGameObject cube = scene.CreateGameObject("Cube"); - cube.AddComponent(); + auto& meshRenderer = cube.AddComponent(); + meshRenderer.MeshSource = MetaCoreMeshSourceKind::Asset; + meshRenderer.SourceModelPath = "Assets/Models/box1.glb"; cube.GetComponent().Position = glm::vec3(0.0F, 0.5F, 0.0F); MetaCoreGameObject valve = scene.CreateGameObject("Valve");