feat: 实现 Filament 离屏渲染与 ImGui 视口嵌合(打通 RTT 管线)
This commit is contained in:
parent
2799ddc0e3
commit
3bf03f4b1f
@ -150,7 +150,7 @@ int main(int argc, char* argv[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MetaCore::MetaCoreEditorViewportRenderer viewportRenderer;
|
MetaCore::MetaCoreEditorViewportRenderer viewportRenderer;
|
||||||
if (!viewportRenderer.Initialize(renderDevice)) {
|
if (!viewportRenderer.Initialize(renderDevice, window)) {
|
||||||
std::cerr << "MetaCorePlayer: viewport renderer initialize failed\n";
|
std::cerr << "MetaCorePlayer: viewport renderer initialize failed\n";
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,6 +27,9 @@ endif()
|
|||||||
include(MetaCorePanda3D)
|
include(MetaCorePanda3D)
|
||||||
metacore_prepare_panda3d()
|
metacore_prepare_panda3d()
|
||||||
|
|
||||||
|
include(MetaCoreFilament)
|
||||||
|
|
||||||
|
|
||||||
find_package(glm CONFIG REQUIRED)
|
find_package(glm CONFIG REQUIRED)
|
||||||
find_package(imgui CONFIG REQUIRED)
|
find_package(imgui CONFIG REQUIRED)
|
||||||
|
|
||||||
@ -207,6 +210,7 @@ target_compile_options(MetaCoreScene PRIVATE ${METACORE_COMMON_WARNINGS})
|
|||||||
set(METACORE_RENDER_HEADERS
|
set(METACORE_RENDER_HEADERS
|
||||||
Source/MetaCoreRender/Public/MetaCoreRender/MetaCoreEditorViewportRenderer.h
|
Source/MetaCoreRender/Public/MetaCoreRender/MetaCoreEditorViewportRenderer.h
|
||||||
Source/MetaCoreRender/Public/MetaCoreRender/MetaCorePandaSceneBridge.h
|
Source/MetaCoreRender/Public/MetaCoreRender/MetaCorePandaSceneBridge.h
|
||||||
|
Source/MetaCoreRender/Public/MetaCoreRender/MetaCoreFilamentSceneBridge.h
|
||||||
Source/MetaCoreRender/Public/MetaCoreRender/MetaCoreRenderDevice.h
|
Source/MetaCoreRender/Public/MetaCoreRender/MetaCoreRenderDevice.h
|
||||||
Source/MetaCoreRender/Public/MetaCoreRender/MetaCoreRenderTypes.h
|
Source/MetaCoreRender/Public/MetaCoreRender/MetaCoreRenderTypes.h
|
||||||
)
|
)
|
||||||
@ -214,9 +218,11 @@ set(METACORE_RENDER_HEADERS
|
|||||||
set(METACORE_RENDER_SOURCES
|
set(METACORE_RENDER_SOURCES
|
||||||
Source/MetaCoreRender/Private/MetaCoreEditorViewportRenderer.cpp
|
Source/MetaCoreRender/Private/MetaCoreEditorViewportRenderer.cpp
|
||||||
Source/MetaCoreRender/Private/MetaCorePandaSceneBridge.cpp
|
Source/MetaCoreRender/Private/MetaCorePandaSceneBridge.cpp
|
||||||
|
Source/MetaCoreRender/Private/MetaCoreFilamentSceneBridge.cpp
|
||||||
Source/MetaCoreRender/Private/MetaCoreRenderDevice.cpp
|
Source/MetaCoreRender/Private/MetaCoreRenderDevice.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
add_library(MetaCoreRender STATIC
|
add_library(MetaCoreRender STATIC
|
||||||
${METACORE_RENDER_HEADERS}
|
${METACORE_RENDER_HEADERS}
|
||||||
${METACORE_RENDER_SOURCES}
|
${METACORE_RENDER_SOURCES}
|
||||||
@ -236,6 +242,9 @@ target_link_libraries(MetaCoreRender
|
|||||||
glm::glm
|
glm::glm
|
||||||
)
|
)
|
||||||
|
|
||||||
|
metacore_use_filament(MetaCoreRender)
|
||||||
|
|
||||||
|
|
||||||
target_compile_options(MetaCoreRender PRIVATE ${METACORE_COMMON_WARNINGS})
|
target_compile_options(MetaCoreRender PRIVATE ${METACORE_COMMON_WARNINGS})
|
||||||
|
|
||||||
set(METACORE_RUNTIME_DATA_HEADERS
|
set(METACORE_RUNTIME_DATA_HEADERS
|
||||||
@ -320,7 +329,6 @@ set(METACORE_EDITOR_SOURCES
|
|||||||
Source/MetaCoreEditor/Private/MetaCoreEditorModule.cpp
|
Source/MetaCoreEditor/Private/MetaCoreEditorModule.cpp
|
||||||
Source/MetaCoreEditor/Private/MetaCoreSceneInteractionService.cpp
|
Source/MetaCoreEditor/Private/MetaCoreSceneInteractionService.cpp
|
||||||
third_party/ImGuizmo/ImGuizmo.cpp
|
third_party/ImGuizmo/ImGuizmo.cpp
|
||||||
third_party/cgltf/cgltf.cpp
|
|
||||||
third_party/stb/stb_image_impl.cpp
|
third_party/stb/stb_image_impl.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -658,7 +658,7 @@ bool MetaCoreEditorApp::Initialize() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MetaCoreTraceStartup("metacore.app: initialize viewport");
|
MetaCoreTraceStartup("metacore.app: initialize viewport");
|
||||||
if (!ViewportRenderer_.Initialize(RenderDevice_)) {
|
if (!ViewportRenderer_.Initialize(RenderDevice_, Window_)) {
|
||||||
MetaCoreTraceStartup("metacore.app: initialize viewport failed");
|
MetaCoreTraceStartup("metacore.app: initialize viewport failed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -990,6 +990,10 @@ void MetaCoreEditorApp::DrawEditorFrame() {
|
|||||||
|
|
||||||
bool gizmoCanvasOpen = true;
|
bool gizmoCanvasOpen = true;
|
||||||
if (ImGui::Begin("MetaCoreSceneGizmoCanvas", &gizmoCanvasOpen, gizmoCanvasFlags)) {
|
if (ImGui::Begin("MetaCoreSceneGizmoCanvas", &gizmoCanvasOpen, gizmoCanvasFlags)) {
|
||||||
|
// 绘制 Filament 离屏渲染的 3D 画面
|
||||||
|
uint32_t texId = ViewportRenderer_.GetFilamentGLTextureId();
|
||||||
|
ImGui::Image((void*)(intptr_t)texId, ImVec2(viewportState.Width, viewportState.Height));
|
||||||
|
|
||||||
SceneInteractionService_.HandleGizmoManipulation(*EditorContext_);
|
SceneInteractionService_.HandleGizmoManipulation(*EditorContext_);
|
||||||
|
|
||||||
gizmoUsing = ImGuizmo::IsUsing();
|
gizmoUsing = ImGuizmo::IsUsing();
|
||||||
|
|||||||
@ -39,7 +39,7 @@ void MetaCoreTrace(const char* message) {
|
|||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
bool MetaCoreEditorViewportRenderer::Initialize(MetaCoreRenderDevice& renderDevice) {
|
bool MetaCoreEditorViewportRenderer::Initialize(MetaCoreRenderDevice& renderDevice, MetaCoreWindow& window) {
|
||||||
MetaCoreTrace("metacore.render: viewport init enter");
|
MetaCoreTrace("metacore.render: viewport init enter");
|
||||||
Shutdown();
|
Shutdown();
|
||||||
|
|
||||||
@ -48,6 +48,11 @@ bool MetaCoreEditorViewportRenderer::Initialize(MetaCoreRenderDevice& renderDevi
|
|||||||
MetaCoreTrace("metacore.render: viewport scene runtime bind failed");
|
MetaCoreTrace("metacore.render: viewport scene runtime bind failed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!FilamentSceneBridge_.Initialize(window)) {
|
||||||
|
MetaCoreTrace("metacore.render: viewport filament scene runtime bind failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
MetaCoreTrace("metacore.render: viewport scene runtime ready");
|
MetaCoreTrace("metacore.render: viewport scene runtime ready");
|
||||||
|
|
||||||
RenderDevice_ = &renderDevice;
|
RenderDevice_ = &renderDevice;
|
||||||
@ -56,12 +61,15 @@ bool MetaCoreEditorViewportRenderer::Initialize(MetaCoreRenderDevice& renderDevi
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void MetaCoreEditorViewportRenderer::Shutdown() {
|
void MetaCoreEditorViewportRenderer::Shutdown() {
|
||||||
SceneBridge_.Shutdown();
|
SceneBridge_.Shutdown();
|
||||||
|
FilamentSceneBridge_.Shutdown();
|
||||||
RenderDevice_ = nullptr;
|
RenderDevice_ = nullptr;
|
||||||
ViewportRect_ = MetaCoreViewportRect{};
|
ViewportRect_ = MetaCoreViewportRect{};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void MetaCoreEditorViewportRenderer::SetViewportRect(const MetaCoreViewportRect& viewportRect) {
|
void MetaCoreEditorViewportRenderer::SetViewportRect(const MetaCoreViewportRect& viewportRect) {
|
||||||
ViewportRect_ = viewportRect;
|
ViewportRect_ = viewportRect;
|
||||||
if (RenderDevice_ != nullptr) {
|
if (RenderDevice_ != nullptr) {
|
||||||
@ -75,12 +83,21 @@ void MetaCoreEditorViewportRenderer::RenderSceneToViewport(const MetaCoreScene&
|
|||||||
}
|
}
|
||||||
|
|
||||||
RenderDevice_->SetSceneViewportRect(ViewportRect_);
|
RenderDevice_->SetSceneViewportRect(ViewportRect_);
|
||||||
SceneBridge_.ApplySceneView(sceneView);
|
|
||||||
SceneBridge_.SyncScene(scene, false);
|
// 更新并渲染 Filament 桥接器
|
||||||
|
FilamentSceneBridge_.ApplySceneView(sceneView);
|
||||||
|
FilamentSceneBridge_.SyncScene(scene, false);
|
||||||
|
FilamentSceneBridge_.Render(); // 恢复 Render 调用,因为现在是离屏渲染
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void MetaCoreEditorViewportRenderer::SetProjectRootPath(const std::filesystem::path& projectRootPath) {
|
void MetaCoreEditorViewportRenderer::SetProjectRootPath(const std::filesystem::path& projectRootPath) {
|
||||||
SceneBridge_.SetProjectRootPath(projectRootPath);
|
SceneBridge_.SetProjectRootPath(projectRootPath);
|
||||||
|
FilamentSceneBridge_.SetProjectRootPath(projectRootPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t MetaCoreEditorViewportRenderer::GetFilamentGLTextureId() const {
|
||||||
|
return FilamentSceneBridge_.GetGLTextureId();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MetaCoreEditorViewportRenderer::TryGetObjectWorldMatrix(MetaCoreId objectId, glm::mat4& worldMatrix) const {
|
bool MetaCoreEditorViewportRenderer::TryGetObjectWorldMatrix(MetaCoreId objectId, glm::mat4& worldMatrix) const {
|
||||||
|
|||||||
408
Source/MetaCoreRender/Private/MetaCoreFilamentSceneBridge.cpp
Normal file
408
Source/MetaCoreRender/Private/MetaCoreFilamentSceneBridge.cpp
Normal file
@ -0,0 +1,408 @@
|
|||||||
|
#include "MetaCoreRender/MetaCoreFilamentSceneBridge.h"
|
||||||
|
#include "MetaCorePlatform/MetaCoreWindow.h"
|
||||||
|
#include "MetaCoreScene/MetaCoreScene.h"
|
||||||
|
#include "MetaCoreScene/MetaCoreComponents.h"
|
||||||
|
#include "MetaCoreRender/MetaCoreRenderTypes.h"
|
||||||
|
|
||||||
|
#include <filament/Engine.h>
|
||||||
|
#include <filament/Scene.h>
|
||||||
|
#include <filament/View.h>
|
||||||
|
#include <filament/Camera.h>
|
||||||
|
#include <filament/SwapChain.h>
|
||||||
|
#include <filament/Renderer.h>
|
||||||
|
#include <filament/Viewport.h>
|
||||||
|
#include <filament/TransformManager.h>
|
||||||
|
#include <filament/Texture.h>
|
||||||
|
#include <filament/RenderTarget.h>
|
||||||
|
#include <filament/LightManager.h>
|
||||||
|
|
||||||
|
#include <gltfio/AssetLoader.h>
|
||||||
|
#include <gltfio/FilamentAsset.h>
|
||||||
|
#include <gltfio/ResourceLoader.h>
|
||||||
|
#include <gltfio/MaterialProvider.h>
|
||||||
|
|
||||||
|
#include <utils/Entity.h>
|
||||||
|
#include <utils/EntityManager.h>
|
||||||
|
|
||||||
|
#define GLM_ENABLE_EXPERIMENTAL
|
||||||
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
// 引入 Windows 和 OpenGL 头文件以创建纹理
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <windows.h>
|
||||||
|
#include <GL/gl.h>
|
||||||
|
|
||||||
|
namespace MetaCore {
|
||||||
|
|
||||||
|
class MetaCoreFilamentSceneBridge::MetaCoreFilamentSceneBridgeImpl {
|
||||||
|
public:
|
||||||
|
MetaCoreFilamentSceneBridgeImpl() = default;
|
||||||
|
|
||||||
|
~MetaCoreFilamentSceneBridgeImpl() {
|
||||||
|
Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Initialize(MetaCoreWindow& window) {
|
||||||
|
std::cout << "FilamentSceneBridge: Initializing..." << std::endl;
|
||||||
|
|
||||||
|
// 创建 Filament Engine (不共享上下文,避免闪退)
|
||||||
|
Engine_ = filament::Engine::create();
|
||||||
|
|
||||||
|
if (!Engine_) {
|
||||||
|
std::cerr << "Failed to create Filament Engine with shared context!" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建无窗口的 1x1 交换链 (因为我们是离屏渲染,不需要绑定真实窗口,避免 OpenGL 上下文冲突)
|
||||||
|
SwapChain_ = Engine_->createSwapChain(1, 1, 0);
|
||||||
|
if (!SwapChain_) {
|
||||||
|
std::cerr << "Failed to create Filament headless SwapChain!" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建渲染器
|
||||||
|
Renderer_ = Engine_->createRenderer();
|
||||||
|
|
||||||
|
// 创建场景
|
||||||
|
Scene_ = Engine_->createScene();
|
||||||
|
|
||||||
|
// 创建默认灯光
|
||||||
|
Light_ = utils::EntityManager::get().create();
|
||||||
|
filament::LightManager::Builder(filament::LightManager::Type::DIRECTIONAL)
|
||||||
|
.color(filament::Color::toLinear<filament::ACCURATE>({ 1.0f, 1.0f, 1.0f }))
|
||||||
|
.intensity(100000.0f)
|
||||||
|
.direction({ 0.5f, -1.0f, -0.5f })
|
||||||
|
.castShadows(true)
|
||||||
|
.build(*Engine_, Light_);
|
||||||
|
Scene_->addEntity(Light_);
|
||||||
|
|
||||||
|
// 创建相机
|
||||||
|
utils::Entity cameraEntity = utils::EntityManager::get().create();
|
||||||
|
Camera_ = Engine_->createCamera(cameraEntity);
|
||||||
|
|
||||||
|
// 创建视图
|
||||||
|
View_ = Engine_->createView();
|
||||||
|
View_->setScene(Scene_);
|
||||||
|
View_->setCamera(Camera_);
|
||||||
|
|
||||||
|
// 初始化离屏渲染纹理
|
||||||
|
auto [width, height] = window.GetFramebufferSize();
|
||||||
|
|
||||||
|
// 1. 创建 OpenGL 纹理
|
||||||
|
glGenTextures(1, &GLTextureId_);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, GLTextureId_);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
|
// 2. 导入到 Filament 作为颜色附件
|
||||||
|
FilamentTexture_ = filament::Texture::Builder()
|
||||||
|
.width(static_cast<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. 创建深度纹理
|
||||||
|
DepthTexture_ = filament::Texture::Builder()
|
||||||
|
.width(static_cast<uint32_t>(width))
|
||||||
|
.height(static_cast<uint32_t>(height))
|
||||||
|
.usage(filament::Texture::Usage::DEPTH_ATTACHMENT)
|
||||||
|
.format(filament::Texture::InternalFormat::DEPTH24)
|
||||||
|
.build(*Engine_);
|
||||||
|
|
||||||
|
// 4. 创建 RenderTarget 并绑定
|
||||||
|
RenderTarget_ = filament::RenderTarget::Builder()
|
||||||
|
.texture(filament::RenderTarget::AttachmentPoint::COLOR, FilamentTexture_)
|
||||||
|
.texture(filament::RenderTarget::AttachmentPoint::DEPTH, DepthTexture_)
|
||||||
|
.build(*Engine_);
|
||||||
|
|
||||||
|
// 5. 设置到 View
|
||||||
|
View_->setRenderTarget(RenderTarget_);
|
||||||
|
View_->setViewport({0, 0, static_cast<uint32_t>(width), static_cast<uint32_t>(height)});
|
||||||
|
|
||||||
|
// 初始化 gltfio (使用 JIT Shader Provider,需要链接 filamat)
|
||||||
|
MaterialProvider_ = filament::gltfio::createJitShaderProvider(Engine_);
|
||||||
|
AssetLoader_ = filament::gltfio::AssetLoader::create({ Engine_, MaterialProvider_, nullptr });
|
||||||
|
|
||||||
|
std::cout << "FilamentSceneBridge: Initialized with Offscreen Texture ID: " << GLTextureId_ << std::endl;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shutdown() {
|
||||||
|
if (Engine_) {
|
||||||
|
std::cout << "FilamentSceneBridge: Shutting down..." << std::endl;
|
||||||
|
|
||||||
|
// 销毁所有加载的资产
|
||||||
|
for (auto& [id, asset] : LoadedAssets_) {
|
||||||
|
AssetLoader_->destroyAsset(asset);
|
||||||
|
}
|
||||||
|
LoadedAssets_.clear();
|
||||||
|
|
||||||
|
// 销毁 gltfio 资源
|
||||||
|
if (AssetLoader_) {
|
||||||
|
filament::gltfio::AssetLoader::destroy(&AssetLoader_);
|
||||||
|
AssetLoader_ = nullptr;
|
||||||
|
}
|
||||||
|
if (MaterialProvider_) {
|
||||||
|
MaterialProvider_->destroyMaterials();
|
||||||
|
delete MaterialProvider_;
|
||||||
|
MaterialProvider_ = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 销毁离屏渲染资源
|
||||||
|
if (RenderTarget_) {
|
||||||
|
Engine_->destroy(RenderTarget_);
|
||||||
|
RenderTarget_ = nullptr;
|
||||||
|
}
|
||||||
|
if (FilamentTexture_) {
|
||||||
|
Engine_->destroy(FilamentTexture_);
|
||||||
|
FilamentTexture_ = nullptr;
|
||||||
|
}
|
||||||
|
if (DepthTexture_) {
|
||||||
|
Engine_->destroy(DepthTexture_);
|
||||||
|
DepthTexture_ = nullptr;
|
||||||
|
}
|
||||||
|
if (GLTextureId_) {
|
||||||
|
glDeleteTextures(1, &GLTextureId_);
|
||||||
|
GLTextureId_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 销毁 View
|
||||||
|
Engine_->destroy(View_);
|
||||||
|
|
||||||
|
// 销毁相机组件和实体
|
||||||
|
if (Camera_) {
|
||||||
|
utils::Entity cameraEntity = Camera_->getEntity();
|
||||||
|
Engine_->destroyCameraComponent(cameraEntity);
|
||||||
|
utils::EntityManager::get().destroy(cameraEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 销毁其他资源
|
||||||
|
Engine_->destroy(Scene_);
|
||||||
|
Engine_->destroy(Renderer_);
|
||||||
|
Engine_->destroy(SwapChain_);
|
||||||
|
|
||||||
|
// 最后销毁 Engine
|
||||||
|
filament::Engine::destroy(&Engine_);
|
||||||
|
Engine_ = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetProjectRootPath(const std::filesystem::path& projectRootPath) {
|
||||||
|
ProjectRootPath_ = projectRootPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SyncScene(const MetaCoreScene& scene, bool compatibilityMeshOnly) {
|
||||||
|
if (!AssetLoader_) return;
|
||||||
|
|
||||||
|
for (const auto& gameObject : scene.GetGameObjects()) {
|
||||||
|
if (!gameObject.HasComponent<MetaCoreMeshRendererComponent>()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& meshRenderer = gameObject.GetComponent<MetaCoreMeshRendererComponent>();
|
||||||
|
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<char> buffer((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
|
||||||
|
|
||||||
|
filament::gltfio::FilamentAsset* asset = AssetLoader_->createAsset(
|
||||||
|
reinterpret_cast<const uint8_t*>(buffer.data()),
|
||||||
|
static_cast<uint32_t>(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<double>(viewport.width) / static_cast<double>(viewport.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置透视投影
|
||||||
|
double fov = sceneView.VerticalFieldOfViewDegrees;
|
||||||
|
double nearClip = 0.1;
|
||||||
|
double farClip = 1000.0;
|
||||||
|
|
||||||
|
Camera_->setProjection(fov, aspect, nearClip, farClip, filament::Camera::Fov::VERTICAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Render() {
|
||||||
|
if (Renderer_ && SwapChain_ && View_) {
|
||||||
|
filament::Renderer::ClearOptions options;
|
||||||
|
options.clearColor = { 1.0f, 0.0f, 1.0f, 1.0f }; // 粉色,方便辨认
|
||||||
|
options.clear = true;
|
||||||
|
Renderer_->setClearOptions(options);
|
||||||
|
|
||||||
|
if (Renderer_->beginFrame(SwapChain_)) {
|
||||||
|
Renderer_->render(View_);
|
||||||
|
Renderer_->endFrame();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t GetGLTextureId() const {
|
||||||
|
return GLTextureId_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TryGetObjectWorldMatrix(MetaCoreId objectId, glm::mat4& worldMatrix) const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HasRuntimeSyncFailure() const { return false; }
|
||||||
|
const std::string& GetLastRuntimeSyncFailure() const { return EmptyString_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void UpdateTransform(const MetaCoreGameObject& gameObject) {
|
||||||
|
auto it = LoadedAssets_.find(gameObject.GetId());
|
||||||
|
if (it == LoadedAssets_.end()) return;
|
||||||
|
|
||||||
|
filament::gltfio::FilamentAsset* asset = it->second;
|
||||||
|
utils::Entity rootEntity = asset->getRoot();
|
||||||
|
|
||||||
|
auto& tm = Engine_->getTransformManager();
|
||||||
|
auto instance = tm.getInstance(rootEntity);
|
||||||
|
if (instance) {
|
||||||
|
if (!gameObject.HasComponent<MetaCoreTransformComponent>()) return;
|
||||||
|
|
||||||
|
const auto& transform = gameObject.GetComponent<MetaCoreTransformComponent>();
|
||||||
|
|
||||||
|
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<const filament::math::mat4f*>(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<MetaCoreId, filament::gltfio::FilamentAsset*> LoadedAssets_;
|
||||||
|
|
||||||
|
GLuint GLTextureId_ = 0;
|
||||||
|
filament::Texture* FilamentTexture_ = nullptr;
|
||||||
|
filament::Texture* DepthTexture_ = nullptr;
|
||||||
|
filament::RenderTarget* RenderTarget_ = nullptr;
|
||||||
|
utils::Entity Light_;
|
||||||
|
|
||||||
|
std::filesystem::path ProjectRootPath_{};
|
||||||
|
std::string EmptyString_{};
|
||||||
|
};
|
||||||
|
|
||||||
|
MetaCoreFilamentSceneBridge::MetaCoreFilamentSceneBridge()
|
||||||
|
: Impl_(std::make_unique<MetaCoreFilamentSceneBridgeImpl>()) {}
|
||||||
|
|
||||||
|
MetaCoreFilamentSceneBridge::~MetaCoreFilamentSceneBridge() = default;
|
||||||
|
|
||||||
|
bool MetaCoreFilamentSceneBridge::Initialize(MetaCoreWindow& window) {
|
||||||
|
return Impl_->Initialize(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MetaCoreFilamentSceneBridge::Shutdown() {
|
||||||
|
Impl_->Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MetaCoreFilamentSceneBridge::SetProjectRootPath(const std::filesystem::path& projectRootPath) {
|
||||||
|
Impl_->SetProjectRootPath(projectRootPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MetaCoreFilamentSceneBridge::SyncScene(const MetaCoreScene& scene, bool compatibilityMeshOnly) {
|
||||||
|
Impl_->SyncScene(scene, compatibilityMeshOnly);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MetaCoreFilamentSceneBridge::ApplySceneView(const MetaCoreSceneView& sceneView) {
|
||||||
|
Impl_->ApplySceneView(sceneView);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MetaCoreFilamentSceneBridge::Render() {
|
||||||
|
Impl_->Render();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t MetaCoreFilamentSceneBridge::GetGLTextureId() const {
|
||||||
|
return Impl_->GetGLTextureId();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MetaCoreFilamentSceneBridge::TryGetObjectWorldMatrix(MetaCoreId objectId, glm::mat4& worldMatrix) const {
|
||||||
|
return Impl_->TryGetObjectWorldMatrix(objectId, worldMatrix);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MetaCoreFilamentSceneBridge::HasRuntimeSyncFailure() const {
|
||||||
|
return Impl_->HasRuntimeSyncFailure();
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& MetaCoreFilamentSceneBridge::GetLastRuntimeSyncFailure() const {
|
||||||
|
return Impl_->GetLastRuntimeSyncFailure();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace MetaCore
|
||||||
@ -1,30 +1,36 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "MetaCoreRender/MetaCorePandaSceneBridge.h"
|
#include "MetaCoreRender/MetaCorePandaSceneBridge.h"
|
||||||
|
#include "MetaCoreRender/MetaCoreFilamentSceneBridge.h"
|
||||||
#include "MetaCoreRender/MetaCoreRenderTypes.h"
|
#include "MetaCoreRender/MetaCoreRenderTypes.h"
|
||||||
|
|
||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace MetaCore {
|
namespace MetaCore {
|
||||||
|
|
||||||
class MetaCoreRenderDevice;
|
class MetaCoreRenderDevice;
|
||||||
|
class MetaCoreWindow;
|
||||||
class MetaCoreScene;
|
class MetaCoreScene;
|
||||||
|
|
||||||
class MetaCoreEditorViewportRenderer {
|
class MetaCoreEditorViewportRenderer {
|
||||||
public:
|
public:
|
||||||
bool Initialize(MetaCoreRenderDevice& renderDevice);
|
bool Initialize(MetaCoreRenderDevice& renderDevice, MetaCoreWindow& window);
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
void SetViewportRect(const MetaCoreViewportRect& viewportRect);
|
void SetViewportRect(const MetaCoreViewportRect& viewportRect);
|
||||||
void RenderSceneToViewport(const MetaCoreScene& scene, const MetaCoreSceneView& sceneView);
|
void RenderSceneToViewport(const MetaCoreScene& scene, const MetaCoreSceneView& sceneView);
|
||||||
void SetProjectRootPath(const std::filesystem::path& projectRootPath);
|
void SetProjectRootPath(const std::filesystem::path& projectRootPath);
|
||||||
|
[[nodiscard]] uint32_t GetFilamentGLTextureId() const;
|
||||||
|
|
||||||
[[nodiscard]] bool TryGetObjectWorldMatrix(MetaCoreId objectId, glm::mat4& worldMatrix) const;
|
[[nodiscard]] bool TryGetObjectWorldMatrix(MetaCoreId objectId, glm::mat4& worldMatrix) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MetaCoreRenderDevice* RenderDevice_ = nullptr;
|
MetaCoreRenderDevice* RenderDevice_ = nullptr;
|
||||||
MetaCorePandaSceneBridge SceneBridge_{};
|
MetaCorePandaSceneBridge SceneBridge_{};
|
||||||
|
MetaCoreFilamentSceneBridge FilamentSceneBridge_{};
|
||||||
MetaCoreViewportRect ViewportRect_{};
|
MetaCoreViewportRect ViewportRect_{};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace MetaCore
|
} // namespace MetaCore
|
||||||
|
|||||||
@ -0,0 +1,42 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "MetaCoreFoundation/MetaCoreId.h"
|
||||||
|
|
||||||
|
#include <glm/mat4x4.hpp>
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace MetaCore {
|
||||||
|
|
||||||
|
class MetaCoreWindow;
|
||||||
|
class MetaCoreScene;
|
||||||
|
struct MetaCoreSceneView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Filament 场景桥接器,负责将 MetaCore 的场景数据同步到 Filament 渲染引擎中
|
||||||
|
*/
|
||||||
|
class MetaCoreFilamentSceneBridge {
|
||||||
|
public:
|
||||||
|
MetaCoreFilamentSceneBridge();
|
||||||
|
~MetaCoreFilamentSceneBridge();
|
||||||
|
|
||||||
|
bool Initialize(MetaCoreWindow& window);
|
||||||
|
void Shutdown();
|
||||||
|
void SetProjectRootPath(const std::filesystem::path& projectRootPath);
|
||||||
|
void SyncScene(const MetaCoreScene& scene, bool compatibilityMeshOnly = false);
|
||||||
|
void ApplySceneView(const MetaCoreSceneView& sceneView);
|
||||||
|
void Render();
|
||||||
|
[[nodiscard]] uint32_t GetGLTextureId() const;
|
||||||
|
|
||||||
|
[[nodiscard]] bool TryGetObjectWorldMatrix(MetaCoreId objectId, glm::mat4& worldMatrix) const;
|
||||||
|
[[nodiscard]] bool HasRuntimeSyncFailure() const;
|
||||||
|
[[nodiscard]] const std::string& GetLastRuntimeSyncFailure() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
class MetaCoreFilamentSceneBridgeImpl;
|
||||||
|
std::unique_ptr<MetaCoreFilamentSceneBridgeImpl> Impl_{};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace MetaCore
|
||||||
51
cmake/MetaCoreFilament.cmake
Normal file
51
cmake/MetaCoreFilament.cmake
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
# Filament SDK configuration for MetaCore
|
||||||
|
|
||||||
|
set(METACORE_FILAMENT_ROOT "${CMAKE_SOURCE_DIR}/third_party/filament_installed" CACHE PATH "Path to installed Filament SDK")
|
||||||
|
set(METACORE_FILAMENT_INCLUDE_DIR "${METACORE_FILAMENT_ROOT}/include")
|
||||||
|
set(METACORE_FILAMENT_LIB_DIR "${METACORE_FILAMENT_ROOT}/lib/x86_64")
|
||||||
|
|
||||||
|
function(metacore_use_filament target_name)
|
||||||
|
if(NOT TARGET ${target_name})
|
||||||
|
message(FATAL_ERROR "Target ${target_name} does not exist.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
message(STATUS "Linking Filament to ${target_name}")
|
||||||
|
|
||||||
|
# 定义核心库
|
||||||
|
set(_filament_libs
|
||||||
|
"${METACORE_FILAMENT_LIB_DIR}/filament.lib"
|
||||||
|
"${METACORE_FILAMENT_LIB_DIR}/backend.lib"
|
||||||
|
"${METACORE_FILAMENT_LIB_DIR}/utils.lib"
|
||||||
|
"${METACORE_FILAMENT_LIB_DIR}/filabridge.lib"
|
||||||
|
"${METACORE_FILAMENT_LIB_DIR}/filaflat.lib"
|
||||||
|
"${METACORE_FILAMENT_LIB_DIR}/filamat.lib"
|
||||||
|
"${METACORE_FILAMENT_LIB_DIR}/shaders.lib"
|
||||||
|
"${METACORE_FILAMENT_LIB_DIR}/bluegl.lib"
|
||||||
|
"${METACORE_FILAMENT_LIB_DIR}/gltfio.lib"
|
||||||
|
"${METACORE_FILAMENT_LIB_DIR}/gltfio_core.lib"
|
||||||
|
"${METACORE_FILAMENT_LIB_DIR}/abseil.lib"
|
||||||
|
"${METACORE_FILAMENT_LIB_DIR}/perfetto.lib"
|
||||||
|
"${METACORE_FILAMENT_LIB_DIR}/dracodec.lib"
|
||||||
|
"${METACORE_FILAMENT_LIB_DIR}/geometry.lib"
|
||||||
|
"${METACORE_FILAMENT_LIB_DIR}/smol-v.lib"
|
||||||
|
"${METACORE_FILAMENT_LIB_DIR}/zstd.lib"
|
||||||
|
opengl32.lib
|
||||||
|
gdi32.lib
|
||||||
|
user32.lib
|
||||||
|
shlwapi.lib
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(${target_name} PRIVATE "${METACORE_FILAMENT_INCLUDE_DIR}")
|
||||||
|
target_link_libraries(${target_name} PRIVATE ${_filament_libs})
|
||||||
|
|
||||||
|
# Filament 需要 C++17 或更高版本
|
||||||
|
target_compile_features(${target_name} PRIVATE cxx_std_17)
|
||||||
|
|
||||||
|
# 针对 MSVC 的一些必要宏定义
|
||||||
|
if(MSVC)
|
||||||
|
target_compile_definitions(${target_name} PRIVATE
|
||||||
|
WIN32_LEAN_AND_MEAN
|
||||||
|
_CRT_SECURE_NO_WARNINGS
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
Loading…
Reference in New Issue
Block a user