ImGuiの導入
ImGuiとは
ImGuiとは,楽に組み込みができて,簡易的なGUIを提供するライブラリです。
https://github.com/ocornut/imgui
例えば,このようなコードを書くと,
ImGui::Begin("Stats", nullptr, window_flags); ImGui::LabelText("", "FPS:%4.2f (%4.2f ms)", s_Fps); ImGui::LabelText("", "Camera Pos:(%.2f, %.2f, %.2f )", cameraPosition.x, cameraPosition.y, cameraPosition.z); ImGui::Spacing(); ImGui::SetNextTreeNodeOpen(true, ImGuiSetCond_Once); if (ImGui::CollapsingHeader("PostEffect")) { if (ImGui::TreeNode("Tonemap")) { ImGui::SliderFloat("Gamma", &pfxDesc.Tonemap.Gamma, 0.0f, 4.0f); // ... ImGui::TreePop(); } // ... ImGui::TreePop(); } //... ImGui::End(); ImGui::Render();
こんな感じでGUIが作れます。
手続き的にImGuiのnamespaceのAPIをコールするだけで,それっぽいGUIが出来上がるのでとても便利です。
ImGuiの組み込み方法
ソースコードを持ってくる
ImGuiのリポジトリからソースを持ってきて,自分のプロジェクトに必要なソースとヘッダを組み込みます。 必要なファイルは
です。自分のライブラリに組み込むような場合は,imgui.hのみ公開ヘッダとすれば大丈夫かと思います。
プラットフォームに合わせた実装をする
(簡単) examplesを利用する方法
ImGuiを利用するためには,描画部分とマウスやキーボードの入力部分を実装しなければいけません。
その実装例がImGuiのリポジトリのexamplesディレクトリ以下に格納されているので,面倒ならばこのサンプルをそのまま使っても良いと思います。
例としてDX11版の実装を見てみます。 imgui_impl_dx11.hを見ると,
IMGUI_API bool ImGui_ImplDX11_Init(void* hwnd, ID3D11Device* device, ID3D11DeviceContext* device_context); IMGUI_API void ImGui_ImplDX11_Shutdown(); IMGUI_API void ImGui_ImplDX11_NewFrame(); IMGUI_API void ImGui_ImplDX11_InvalidateDeviceObjects(); IMGUI_API bool ImGui_ImplDX11_CreateDeviceObjects();
というAPIが定義されていて,Init()で初期化を行い,デバイスの作成・破棄が行われたらInvalidateDeviceObjects(),CreateDeviceObjects()をコールします。 ImGui名前空間のAPIをコールする前には,NewFrame()を呼ぶ必要があります。また,WindowsAPIのイベントを取得するために,
IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
ImGui_ImplDX11_WndProcHandler()をグローバルな名前空間にexternで定義しておいて,組み込み先のアプリケーションのWNDPROCのコールバック内部でコールするようにします。
これだけで,とりあえずは自分のプロジェクトでImGuiを動作させるところまでは持っていくことができます。 DX11以外のプラットフォームでも同じような感じで組み込めるかと思います。
真面目に組み込む方法
- examplesに自分の使いたいプラットフォームが無い
- 独自に抽象化されたフレームワークを利用している,もしくは作成している
という場合には,自分で真面目にImGui::GetIO()を利用してImGuiの描画部分と入力部分を実装する必要があります。 これもexampleのサンプルコードの中身を参考にすれば良いです。 ImGuiIO::KeyMapやImGuiIO::MousePosなどに入力値を格納しておけばImGui内部で利用する入力として利用してくれます。
描画部分は,ImGuiIO::RenderDrawListsFnにImGui内部で利用するImDrawData構造体のを引数に,描画処理を行うコールバックを実装する必要があります。 ImDrawDataには描画に利用する頂点データや行列変換の定数バッファが格納されていて,これを利用して描画を行うことになります。 そのために,ImGui利用前にプラットフォーム固有のシェーダーや,Font用のテクスチャを作成する必要があります。
ひっかかり
シェーダーリフレクションを利用してシェーダーコードからInputLayoutを作っていたので,
ImGuiの組み込みをしたときに,渡される頂点バッファのColor部分のデータが8bitUNORMのフォーマットだったことに少し躓きました。
DX11の場合はリフレクションで8bitフォーマットかどうかはわからないので,手動でInputLayoutを作成する必要があります。