Dear ImGui renderer backend for Direct3D 7 with a minimal Win32 example app.
- Overview
- Features
- Requirements
- Getting Started
- How It Works
- Usage in Your App
- Textures
- Resizing & Device Reset
- Limitations & Notes
- Troubleshooting
- FAQ
- Roadmap / TODO
- License
- Acknowledgments
This repository provides a legacy renderer backend for Dear ImGui targeting Direct3D 7 (IDirect3DDevice7
+ IDirectDraw7
). It also includes a small Win32 example that demonstrates creating a D3D7 device, uploading the ImGui font atlas, submitting draw calls, and presenting to the primary surface.
This is primarily for retro / demo / archival purposes. Modern projects should prefer DX9+, OpenGL, Vulkan, Metal, or DX12 backends.
- ✅ User texture binding (
ImTextureID = LPDIRECTDRAWSURFACE7
). - ✅ Large meshes via
ImGuiBackendFlags_RendererHasVtxOffset
. - ✅
IMGUI_USE_BGRA_PACKED_COLOR
supported. - ✅ Per-command clipping in software (emulates scissor using Sutherland–Hodgman polygon clipping against
ImDrawCmd::ClipRect
).
- OS: Windows 98/2000/XP and later (tested primarily on modern Windows via legacy SDK headers).
- Compiler: MSVC (Visual Studio 2019+ recommended). MinGW may work with compatible headers/libs.
- SDK/Libraries:
ddraw.h
,d3d.h
(DirectX 7 era headers)- Link with
ddraw.lib
anddxguid.lib
- Dear ImGui source (e.g.,
ImGui/
folder)
Note: You do not need the full “DirectX 7 SDK” if your compiler already ships legacy DirectDraw/Direct3D 7 headers/libs. On modern setups these typically come with the Windows SDK / VS toolchain for compatibility.
<root>/
ImGui/
imgui.h
imgui.cpp
imgui_demo.cpp (optional)
imgui_draw.cpp
imgui_tables.cpp
imgui_widgets.cpp
imgui_internal.h
imgui_impl_win32.h
imgui_impl_win32.cpp
imconfig.h (optional)
# stb_* headers, etc.
imgui_impl_dx7.h
imgui_impl_dx7.cpp # The D3D7 renderer backend
example_win32_directx7.cpp # Win32 + D3D7 sample entry point
imgui.ini # Runtime settings (generated)
- Create a Win32 or Console C/C++ project.
- Add source files to the project:
imgui_impl_dx7.cpp
ImGui/imgui_impl_win32.cpp
example_win32_directx7.cpp
- ImGui core:
ImGui/imgui.cpp
,ImGui/imgui_draw.cpp
,ImGui/imgui_tables.cpp
,ImGui/imgui_widgets.cpp
(optional:ImGui/imgui_demo.cpp
)
- Include directories:
.
(project root)ImGui
- Linker → Input → Additional Dependencies:
ddraw.lib; dxguid.lib;
(plus defaults)
- Subsystem:
- Windows (GUI app) or Console — both work with this sample.
- Build Win32 (x86) for maximum compatibility, or x64 if desired.
cmake_minimum_required(VERSION 3.16)
project(D3D7imgui LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# WIN32 builds a GUI app without a console. Remove WIN32 to keep a console window.
add_executable(D3D7imgui WIN32
imgui_impl_dx7.cpp
example_win32_directx7.cpp
ImGui/imgui.cpp
ImGui/imgui_draw.cpp
ImGui/imgui_tables.cpp
ImGui/imgui_widgets.cpp
ImGui/imgui_demo.cpp # optional: remove if you don't want the demo window
ImGui/imgui_impl_win32.cpp
)
target_include_directories(D3D7imgui PRIVATE . ImGui)
target_link_libraries(D3D7imgui PRIVATE ddraw dxguid)
Tip: If the linker can’t find
ddraw.lib
/dxguid.lib
, ensure your Windows SDK is installed and the correct VC toolset is active.
- Vertex format: Pre-transformed XYZRHW with packed ARGB color and one set of UVs (
FVF = D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1
). - Color packing: ImGui packs ABGR by default; converted to D3D’s ARGB when
IMGUI_USE_BGRA_PACKED_COLOR
is not defined. - Software clipping: D3D7 lacks native scissor testing. Each
ImDrawCmd
’s triangles are clipped against itsClipRect
via Sutherland–Hodgman polygon clipping. The result is submitted withDrawIndexedPrimitive
. - State backup: Only a minimal set of transforms, render states, texture stage states, and texture bindings are backed up and restored around the ImGui pass.
- Font texture: The ImGui font atlas is uploaded into a
IDirectDrawSurface7
texture (prefer A8B8G8R8, fallback to A8R8G8B8 with channel swap on upload).
Minimal integration points (pseudocode):
// Init (once)
ImGui::CreateContext();
ImGui_ImplWin32_Init(hwnd);
ImGui_ImplDX7_Init(d3dDevice, ddraw);
ImGui_ImplDX7_CreateDeviceObjects(); // uploads font texture
// Per-frame
ImGui_ImplWin32_NewFrame();
ImGui_ImplDX7_NewFrame();
ImGui::NewFrame();
// ... build your UI ...
ImGui::Render();
ImGui_ImplDX7_RenderDrawData(ImGui::GetDrawData());
// Shutdown
ImGui_ImplDX7_InvalidateDeviceObjects();
ImGui_ImplDX7_Shutdown();
ImGui_ImplWin32_Shutdown();
ImGui::DestroyContext();
- ImTextureID is a raw
LPDIRECTDRAWSURFACE7
. Create textures withDDSCAPS_TEXTURE
(and preferably video memory). The backend assumes 32-bit ARGB if possible. - For user textures, set
ImGui::Image((ImTextureID)mySurface, ImVec2(w,h));
.
- The example queues resize events (
WM_SIZE
) and recreates the offscreen render target accordingly. - Before destroying/recreating surfaces or losing the device, call
ImGui_ImplDX7_InvalidateDeviceObjects()
; after re-creation, callImGui_ImplDX7_CreateDeviceObjects()
. - Viewport and basic render states are re-applied after reset.
- No hardware scissor: all clipping is done on CPU; very large UI meshes may cost extra CPU.
- 16-bit indices only: D3D7 requires
ImDrawIdx
to be 16-bit (asserts if not). - Texture formats: Prefer A8B8G8R8, fallback to A8R8G8B8 with R/B swap during upload.
- Community-level backend: Not officially maintained by the ImGui project; fewer tests than DX9+/GL/Vulkan backends.
- Legacy API: Expect quirks on modern drivers; vsync and presentation behavior vary.
The window shows but nothing is rendered
- Ensure
DrawIndexedPrimitive
is called betweenBeginScene
/EndScene
. - Verify your
ImGui::Render()
is called andGetDrawData()
returns non-empty.
Fonts are garbled or invisible
- Confirm the font atlas surface is 32-bit ARGB and the R/B channel swap matches your
IMGUI_USE_BGRA_PACKED_COLOR
define. - Make sure
io.Fonts->SetTexID(g_FontTexture);
is called after uploading.
Clipping looks wrong / triangles disappear
- Check the transform to framebuffer space:
(pos - DisplayPos) * FramebufferScale
must be applied. - Verify the clip rect is clamped to framebuffer bounds before clipping.
Linker can’t find ddraw/dxguid
- Install the Windows SDK and ensure your VS toolset uses it. Add
ddraw.lib; dxguid.lib;
to Additional Dependencies.
Resize flicker or artifacts
- Ensure you fully release and recreate the offscreen render target and reset viewport states.
Why D3D7?
For fun, education, retro-compatibility, and demos targeting very old hardware/VMs.
Will this work on Windows 11?
Yes, as long as the legacy headers/libs are available and the driver stack cooperates. This is unsupported territory—test on your target machines.
Can I enable 24/32-bit depth?
This sample disables depth entirely; ImGui doesn’t need it. You can enable Z if your app requires it.
- Optional: batch software clipping to reduce allocations.
- Optional: add a simple texture helper (create/destroy/update) for user images.
- Optional: support paletted textures for true retro flavor.
- Optional: add vsync / timing controls and FPS cap.
- Omar Cornut and all Dear ImGui contributors.
- Microsoft DirectX team (for keeping legacy headers around).
- Everyone still shipping retro D3D games and tools.