#include #include #include #include #include #include #include #include #include #include #include #include #include #include "MetaCoreRender/MetaCoreImGuiHelper.h" #include #include using namespace filament; int main() { constexpr std::uint32_t displayWidth = 1280; constexpr std::uint32_t displayHeight = 720; constexpr std::uint32_t viewportWidth = 800; constexpr std::uint32_t viewportHeight = 600; std::cout << "[Demo] Creating headless Filament engine..." << std::endl; // uiBlit currently ships OpenGL shader material data. The swap chain is // offscreen, while Filament's Linux OpenGL platform still requires X11. Engine* engine = Engine::create(Engine::Backend::OPENGL); if (engine == nullptr) { std::cerr << "[Demo] Failed to create Filament engine." << std::endl; return 1; } Renderer* renderer = engine->createRenderer(); SwapChain* swapChain = engine->createSwapChain(displayWidth, displayHeight); Scene* scene = engine->createScene(); View* sceneView = engine->createView(); View* uiView = engine->createView(); if (renderer == nullptr || swapChain == nullptr || scene == nullptr || sceneView == nullptr || uiView == nullptr) { std::cerr << "[Demo] Failed to create Filament headless resources." << std::endl; Engine::destroy(&engine); return 1; } utils::Entity cameraEntity = utils::EntityManager::get().create(); Camera* camera = engine->createCamera(cameraEntity); sceneView->setScene(scene); sceneView->setCamera(camera); Skybox* skybox = Skybox::Builder() .color({1.0F, 0.0F, 1.0F, 1.0F}) .build(*engine); scene->setSkybox(skybox); Texture* viewportTexture = Texture::Builder() .width(viewportWidth) .height(viewportHeight) .levels(1) .usage(Texture::Usage::COLOR_ATTACHMENT | Texture::Usage::SAMPLEABLE) .format(Texture::InternalFormat::RGBA8) .build(*engine); RenderTarget* renderTarget = RenderTarget::Builder() .texture(RenderTarget::AttachmentPoint::COLOR, viewportTexture) .build(*engine); sceneView->setRenderTarget(renderTarget); sceneView->setViewport({0, 0, viewportWidth, viewportHeight}); sceneView->setPostProcessingEnabled(true); uiView->setViewport({0, 0, displayWidth, displayHeight}); uiView->setPostProcessingEnabled(false); IMGUI_CHECKVERSION(); ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); io.DisplaySize = ImVec2(static_cast(displayWidth), static_cast(displayHeight)); io.DeltaTime = 1.0F / 60.0F; { MetaCore::MetaCoreImGuiHelper imguiHelper(engine, uiView, "", ImGui::GetCurrentContext()); imguiHelper.setDisplaySize(displayWidth, displayHeight); // This is a deterministic offscreen smoke demo rather than an interactive // platform window. A few frames are enough to exercise both render paths. for (int frame = 0; frame < 3; ++frame) { if (!renderer->beginFrame(swapChain)) { continue; } renderer->render(sceneView); ImGui::NewFrame(); ImGui::SetNextWindowSize(ImVec2(820.0F, 640.0F), ImGuiCond_Always); ImGui::Begin("3D Viewport"); ImGui::Image( reinterpret_cast(viewportTexture), ImVec2(static_cast(viewportWidth), static_cast(viewportHeight)), ImVec2(0.0F, 1.0F), ImVec2(1.0F, 0.0F) ); ImGui::End(); ImGui::Render(); imguiHelper.processImGuiCommands(ImGui::GetDrawData(), io); renderer->render(uiView); renderer->endFrame(); } } ImGui::DestroyContext(); engine->destroy(renderTarget); engine->destroy(viewportTexture); engine->destroy(skybox); engine->destroy(sceneView); engine->destroy(uiView); engine->destroy(scene); engine->destroyCameraComponent(cameraEntity); utils::EntityManager::get().destroy(cameraEntity); engine->destroy(renderer); engine->destroy(swapChain); Engine::destroy(&engine); std::cout << "[Demo] Headless render completed." << std::endl; return 0; }