feat: 完成工具栏汉化,去掉视口黄色框和原点轴,默认加载 box1.glb,解决崩溃问题
This commit is contained in:
parent
1d0377584c
commit
107dbb6861
Binary file not shown.
Binary file not shown.
@ -200,26 +200,8 @@ void MetaCoreDrawWorldOriginOverlay(
|
||||
const MetaCoreSceneView& sceneView,
|
||||
const MetaCoreSceneViewportState& viewportState
|
||||
) {
|
||||
if (!editorContext.GetShowWorldOrigin()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ImVec2 originScreenPoint{};
|
||||
if (!MetaCoreProjectWorldPointToViewport(sceneView, viewportState, glm::vec3(0.0F, 0.0F, 0.0F), originScreenPoint)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ImDrawList* drawList = ImGui::GetForegroundDrawList();
|
||||
const ImU32 xColor = IM_COL32(220, 80, 80, 220);
|
||||
const ImU32 yColor = IM_COL32(120, 210, 100, 220);
|
||||
const ImU32 zColor = IM_COL32(90, 140, 235, 220);
|
||||
drawList->AddCircleFilled(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<MetaCoreTransformComponent>().Scale.x), 0.5F) * 0.5F,
|
||||
std::max(std::abs(selectedObject.GetComponent<MetaCoreTransformComponent>().Scale.y), 0.5F) * 0.5F,
|
||||
std::max(std::abs(selectedObject.GetComponent<MetaCoreTransformComponent>().Scale.z), 0.5F) * 0.5F
|
||||
);
|
||||
const glm::vec3 center = selectedObject.GetComponent<MetaCoreTransformComponent>().Position;
|
||||
|
||||
const std::array<glm::vec3, 8> 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<HWND>(Window_.GetNativeWindowHandle()));
|
||||
SwapBuffers(hdc);
|
||||
ReleaseDC(static_cast<HWND>(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_);
|
||||
|
||||
|
||||
@ -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() : "<Missing>"
|
||||
"选中: %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() : "<Missing>"
|
||||
activeObject ? activeObject.GetName().c_str() : "<缺失>"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -90,8 +90,6 @@ std::unordered_map<HWND, class MetaCoreWindow::MetaCoreWindowImpl*>& 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);
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -3,6 +3,8 @@
|
||||
#include "MetaCoreScene/MetaCoreScene.h"
|
||||
#include "MetaCoreScene/MetaCoreComponents.h"
|
||||
#include "MetaCoreRender/MetaCoreRenderTypes.h"
|
||||
#include "MetaCoreRender/MetaCoreImGuiHelper.h"
|
||||
#include <imgui.h>
|
||||
|
||||
#include <filament/Engine.h>
|
||||
#include <filament/Scene.h>
|
||||
@ -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<uint32_t>(width))
|
||||
.height(static_cast<uint32_t>(height))
|
||||
.usage(filament::Texture::Usage::COLOR_ATTACHMENT | filament::Texture::Usage::SAMPLEABLE)
|
||||
.format(filament::Texture::InternalFormat::RGBA8)
|
||||
.import(static_cast<intptr_t>(GLTextureId_))
|
||||
.build(*Engine_);
|
||||
|
||||
// 3. 创建深度纹理
|
||||
// 2. 创建深度纹理
|
||||
DepthTexture_ = filament::Texture::Builder()
|
||||
.width(static_cast<uint32_t>(width))
|
||||
.height(static_cast<uint32_t>(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<uint32_t>(width), static_cast<uint32_t>(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<uint32_t>(io.DisplaySize.x), static_cast<uint32_t>(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<uint32_t>(width) &&
|
||||
FilamentTexture_->getHeight() == static_cast<uint32_t>(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<uint32_t>(width))
|
||||
.height(static_cast<uint32_t>(height))
|
||||
.usage(filament::Texture::Usage::COLOR_ATTACHMENT | filament::Texture::Usage::SAMPLEABLE)
|
||||
.format(filament::Texture::InternalFormat::RGBA8)
|
||||
.import(static_cast<intptr_t>(GLTextureId_))
|
||||
.build(*Engine_);
|
||||
|
||||
DepthTexture_ = filament::Texture::Builder()
|
||||
@ -393,10 +421,14 @@ private:
|
||||
|
||||
std::unordered_map<MetaCoreId, filament::gltfio::FilamentAsset*> 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<filament::Texture*> 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 {
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -460,7 +460,9 @@ MetaCoreScene MetaCoreCreateDefaultScene() {
|
||||
directionalLight.GetComponent<MetaCoreTransformComponent>().RotationEulerDegrees = glm::vec3(-45.0F, 30.0F, 0.0F);
|
||||
|
||||
MetaCoreGameObject cube = scene.CreateGameObject("Cube");
|
||||
cube.AddComponent<MetaCoreMeshRendererComponent>();
|
||||
auto& meshRenderer = cube.AddComponent<MetaCoreMeshRendererComponent>();
|
||||
meshRenderer.MeshSource = MetaCoreMeshSourceKind::Asset;
|
||||
meshRenderer.SourceModelPath = "Assets/Models/box1.glb";
|
||||
cube.GetComponent<MetaCoreTransformComponent>().Position = glm::vec3(0.0F, 0.5F, 0.0F);
|
||||
|
||||
MetaCoreGameObject valve = scene.CreateGameObject("Valve");
|
||||
|
||||
Loading…
Reference in New Issue
Block a user