1. 安装vcpkg
git clone https://github.com/microsoft/vcpkg
.\vcpkg\bootstrap-vcpkg.bat
.\vcpkg\vcpkg integrate install2. 安装imgui
./vcpkg install imgui[core,win32-binding,dx11-binding]3. 创建项目并写入代码
// Dear ImGui: 独立示例应用程序,使用DirectX 11
// 了解Dear ImGui:
// - 常见问题解答:https://dearimgui.com/faq
// - 入门指南:https://dearimgui.com/getting-started
// - 文档:https://dearimgui.com/docs (与本地的docs/文件夹相同)。
// - 介绍、链接和更多信息请见imgui.cpp顶部
#include <imgui.h>
#include <imgui_impl_win32.h>
#include <imgui_impl_dx11.h>
#include <d3d11.h>
#include <tchar.h>
// 数据
static ID3D11Device* g_pd3dDevice = nullptr; // 指向D3D11设备的指针
static ID3D11DeviceContext* g_pd3dDeviceContext = nullptr; // 指向D3D11设备上下文的指针
static IDXGISwapChain* g_pSwapChain = nullptr; // 指向交换链的指针
static bool g_SwapChainOccluded = false; // 交换链是否被遮挡
static UINT g_ResizeWidth = 0, g_ResizeHeight = 0; // 窗口调整大小的宽度和高度
static ID3D11RenderTargetView* g_mainRenderTargetView = nullptr; // 渲染目标视图的指针
// 帮助函数的前向声明
bool CreateDeviceD3D(HWND hWnd);
void CleanupDeviceD3D();
void CreateRenderTarget();
void CleanupRenderTarget();
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
// 主函数
int main(int, char**)
{
// 创建应用程序窗口
// ImGui_ImplWin32_EnableDpiAwareness();
WNDCLASSEXW wc = { sizeof(wc), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(nullptr), nullptr, nullptr, nullptr, nullptr, L"ImGui Example", nullptr };
::RegisterClassExW(&wc);
HWND hwnd = ::CreateWindowW(wc.lpszClassName, L"Dear ImGui DirectX11 Example", WS_OVERLAPPEDWINDOW, 100, 100, 1280, 800, nullptr, nullptr, wc.hInstance, nullptr);
// 初始化Direct3D
if (!CreateDeviceD3D(hwnd))
{
CleanupDeviceD3D();
::UnregisterClassW(wc.lpszClassName, wc.hInstance);
return 1;
}
// 显示窗口
::ShowWindow(hwnd, SW_SHOWDEFAULT);
::UpdateWindow(hwnd);
// 设置Dear ImGui上下文
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // 启用键盘控制
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // 启用游戏手柄控制
// 设置Dear ImGui样式
ImGui::StyleColorsDark();
// ImGui::StyleColorsLight();
// 设置平台/渲染器后端
ImGui_ImplWin32_Init(hwnd);
ImGui_ImplDX11_Init(g_pd3dDevice, g_pd3dDeviceContext);
// 加载字体
// - 如果未加载字体,dear imgui将使用默认字体。您还可以加载多个字体,并使用ImGui::PushFont()/PopFont()选择它们。
// - AddFontFromFileTTF()将返回ImFont*,如果需要在多个字体中选择,请存储它。
// - 如果文件无法加载,函数将返回nullptr。请在应用程序中处理这些错误(例如使用断言,或显示错误并退出)。
// - 在调用ImFontAtlas::Build()/GetTexDataAsXXXX()时,字体将在给定大小(带有过采样)下光栅化并存储到纹理中,ImGui_ImplXXXX_NewFrame将调用该方法。
// - 使用'#define IMGUI_ENABLE_FREETYPE'在imconfig文件中使用Freetype进行更高质量的字体渲染。
// - 阅读'docs/FONTS.md'获取更多说明和详细信息。
// - 请记住,在C/C++中,如果要在字符串文字中包含反斜杠\,需要编写双反斜杠\\!
// io.Fonts->AddFontDefault();
// io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf", 18.0f);
// io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
// io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
// io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
// ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, nullptr, io.Fonts->GetGlyphRangesJapanese());
// IM_ASSERT(font != nullptr);
// 我们的状态
bool show_demo_window = true; // 显示演示窗口
bool show_another_window = false; // 显示另一个窗口
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); // 清除颜色
// 主循环
bool done = false;
while (!done)
{
// 轮询和处理消息(输入、窗口调整大小等)
// 请参阅下面的WndProc()函数,以了解如何将事件分派到Win32后端。
MSG msg;
while (::PeekMessage(&msg, nullptr, 0U, 0U, PM_REMOVE))
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
if (msg.message == WM_QUIT)
done = true;
}
if (done)
break;
// 处理窗口被最小化或屏幕被锁定
if (g_SwapChainOccluded && g_pSwapChain->Present(0, DXGI_PRESENT_TEST) == DXGI_STATUS_OCCLUDED)
{
::Sleep(10);
continue;
}
g_SwapChainOccluded = false;
// 处理窗口调整大小(我们不会直接在WM_SIZE处理程序中调整大小)
if (g_ResizeWidth != 0 && g_ResizeHeight != 0)
{
CleanupRenderTarget();
g_pSwapChain->ResizeBuffers(0, g_ResizeWidth, g_ResizeHeight, DXGI_FORMAT_UNKNOWN, 0);
g_ResizeWidth = g_ResizeHeight = 0;
CreateRenderTarget();
}
// 开始Dear ImGui帧
ImGui_ImplDX11_NewFrame();
ImGui_ImplWin32_NewFrame();
ImGui::NewFrame();
// 1. 显示大演示窗口(大部分示例代码都在ImGui::ShowDemoWindow()中!您可以浏览其代码以了解更多关于Dear ImGui的知识!)。
if (show_demo_window)
ImGui::ShowDemoWindow(&show_demo_window);
// 2. 显示我们自己创建的简单窗口。我们使用Begin/End对来创建一个命名窗口。
{
static float f = 0.0f;
static int counter = 0;
ImGui::Begin("Hello, world!"); // 创建一个名为"Hello, world!"的窗口,并将其附加到其中。
ImGui::Text("This is some useful text."); // 显示一些有用的文本(您也可以使用格式字符串)
ImGui::Checkbox("Demo Window", &show_demo_window); // 编辑存储窗口打开/关闭状态的布尔值
ImGui::Checkbox("Another Window", &show_another_window);
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // 使用滑块从0.0f到1.0f编辑1个浮点数
ImGui::ColorEdit3("clear color", (float*)&clear_color); // 编辑表示颜色的3个浮点数
if (ImGui::Button("Button")) // 按钮在点击时返回true(大多数小部件在编辑/激活时返回true)
counter++;
ImGui::SameLine();
ImGui::Text("counter = %d", counter);
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
ImGui::End();
}
// 3. 显示另一个简单窗口。
if (show_another_window)
{
ImGui::Begin("Another Window", &show_another_window); // 传递一个指向我们的布尔变量的指针(窗口将有一个关闭按钮,点击时将清除该布尔值)
ImGui::Text("Hello from another window!");
if (ImGui::Button("Close Me"))
show_another_window = false;
ImGui::End();
}
// 渲染
ImGui::Render();
const float clear_color_with_alpha[4] = { clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w };
g_pd3dDeviceContext->OMSetRenderTargets(1, &g_mainRenderTargetView, nullptr);
g_pd3dDeviceContext->ClearRenderTargetView(g_mainRenderTargetView, clear_color_with_alpha);
ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
// 检查是否被遮挡
if (g_pSwapChain->Present(1, 0) == DXGI_STATUS_OCCLUDED)
{
g_SwapChainOccluded = true;
}
}
// 清理
ImGui_ImplDX11_Shutdown();
ImGui_ImplWin32_Shutdown();
ImGui::DestroyContext();
CleanupRenderTarget();
CleanupDeviceD3D();
::DestroyWindow(hwnd);
::UnregisterClassW(wc.lpszClassName, wc.hInstance);
return 0;
}
// 创建Direct3D设备并交换链
bool CreateDeviceD3D(HWND hWnd)
{
// 创建D3D设备
DXGI_SWAP_CHAIN_DESC sd = {};
sd.BufferCount = 2;
sd.BufferDesc.Width = 0;
sd.BufferDesc.Height = 0;
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
sd.BufferDesc.RefreshRate.Numerator = 60;
sd.BufferDesc.RefreshRate.Denominator = 1;
sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.OutputWindow = hWnd;
sd.SampleDesc.Count = 1;
sd.SampleDesc.Quality = 0;
sd.Windowed = TRUE;
sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
sd.Flags = 0;
UINT createDeviceFlags = 0;
D3D_FEATURE_LEVEL featureLevel;
const D3D_FEATURE_LEVEL featureLevelArray[2] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_0, };
if (D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, createDeviceFlags, featureLevelArray, 2, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &featureLevel, &g_pd3dDeviceContext) != S_OK)
return false;
CreateRenderTarget();
return true;
}
// 清理Direct3D设备和交换链
void CleanupDeviceD3D()
{
CleanupRenderTarget();
if (g_pSwapChain) { g_pSwapChain->Release(); g_pSwapChain = nullptr; }
if (g_pd3dDeviceContext) { g_pd3dDeviceContext->Release(); g_pd3dDeviceContext = nullptr; }
if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = nullptr; }
}
// 创建渲染目标
void CreateRenderTarget()
{
ID3D11Texture2D* pBackBuffer;
g_pSwapChain->GetBuffer(0, IID_PPV_ARGS(&pBackBuffer));
g_pd3dDevice->CreateRenderTargetView(pBackBuffer, nullptr, &g_mainRenderTargetView);
pBackBuffer->Release();
}
// 清理渲染目标
void CleanupRenderTarget()
{
if (g_mainRenderTargetView) { g_mainRenderTargetView->Release(); g_mainRenderTargetView = nullptr; }
}
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
// 处理Windows消息
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam))
return true;
switch (msg)
{
case WM_SIZE:
if (g_pd3dDevice != nullptr && wParam != SIZE_MINIMIZED)
{
g_ResizeWidth = (UINT)LOWORD(lParam);
g_ResizeHeight = (UINT)HIWORD(lParam);
}
return 0;
case WM_SYSCOMMAND:
if ((wParam & 0xfff0) == SC_KEYMENU) // 避免菜单快捷键Alt被解释为菜单条目
return 0;
break;
case WM_DESTROY:
::PostQuitMessage(0);
return 0;
}
return ::DefWindowProc(hWnd, msg, wParam, lParam);
}
4. 添加lib文件
在“链接器” -> “输入” -> “附加依赖项”中,添加以下库:
d3d11.lib dxgi.lib d3dcompiler.lib