External Publication
Visit Post

Vlog 03: Integrating Dear ImGui (1.92.0+) with latest jME3: Initial Findings, Traps, and Architecture Choices

jMonkeyEngine Hub June 9, 2026
Source

Hi everyone,

I am currently running some integration tests between the latest versions of the imgui-java wrapper (specifically targeting Dear ImGui 1.92.0+) and jMonkeyEngine 3.10.0+.

My goal is to build a robust, desktop-targeted UI integration layer. During my initial research and implementation phases, I encountered a few architectural shifts in both ecosystems that drastically change how we used to integrate ImGui in the past.

I wanted to share my current findings with the community as a personal study. Please note: these notes represent the current state of my ongoing tests. Some assumptions might be partial or subject to change as I dive deeper into the engine’s source code, so feedback or corrections from anyone more experienced are highly welcome!

Here is a summary of the pros, cons, and structural gotchas that have emerged from my test environment so far.


1. The jME Backend Shift: GLFW vs SDL3

The latest iterations of jME3 default to an SDL-based backend rather than the classic GLFW configuration.

  • Pros: From what I can see, this is a great move for framework stability. SDL handles modern gamepads, complex multi-monitor environments, and Windows 11 DPI quirks much more robustly out of the box.
  • Cons (for ImGui): This shift breaks immediate compatibility with standard ImGui setups. If you were relying on the well-tested ImGuiImplGlfw backend, you can no longer use it seamlessly if jME initializes the window context via SDL.

2. The Multi-Viewport Dilemma in Java

  • Current Status: In the imgui-java wrapper, the Multi-Viewport binding wrapper for SDL3 (ImGuiImplSdl3) does not seem to be fully completed or exposed yet, whereas it is fully operational in ImGuiImplGlfw.
  • The Catch: * If you stick with jME’s new SDL backend , you might have to sacrifice Multi-Viewports for now, disabling ImGuiConfigFlags.ViewportsEnable and keeping all UI windows docked internally.

3. Graphics API: OpenGL Desktop vs ANGLE (OpenGLES)

jME 3.10.0 introduces ANGLE as a default option (translating GLES3 commands into DirectX/Vulkan). On the other hand, the standard ImGuiImplGl3 renderer bundled in imgui-java performs hard-coded queries to the desktop org.lwjgl.opengl.GL subsystem.

  • The Crash Trap: If you boot jME with AppSettings.ANGLE_GLES3, imgui-java will crash instantly during init() with an LWJGL IllegalStateException: setFunctionMissingAddresses has been called already. This happens because LWJGL does not allow initializing both Desktop GL and OpenGLES capabilities simultaneously on the same thread context.
  • Current Workaround: For a pure desktop target, forcing OpenGL Core Profile explicitly via AppSettings.LWJGL_OPENGL32.
  • (Note: Supporting ANGLE would technically require duplicating the ImGui renderer class and manually swapping all standard OpenGL static imports withorg.lwjgl.opengles.GLES30 counterparts, which might not be worth the overhead unless cross-platform mobile/web parity is required).

4. Mandatory Frame-by-Frame Sizing (io.setDisplaySize)

  • What changed: In ImGui 1.92.0+, updating io.setDisplaySize(logicalWidth, logicalHeight) on every single frame inside your update/render loop is highly recommended, if not mandatory.
  • Why it matters: With Windows 11 dynamic DPI scaling, moving a window across monitors with different scale factors instantly alters the logical bounds even if the pixel resolution looks identical. Updating this frame-by-frame prevents mouse misalignment and viewport stuttering.

5. Input Sinking & Custom Adapters

Because of these backend shifts, relying on automatic platform callbacks from ImGui can cause conflicts. Writing a custom JmeImGuiInputAdapter (subclassing RawInputListener) seems to be the most reliable path.

  • Pros: It allows for precise input consumption. You can check if ImGui wants the mouse/keyboard and call evt.setConsumed() to stop inputs from bleeding into your game’s camera or character controllers.
  • Cons: It requires a fair amount of boilerplate code to manually map every jME KeyInputEvent or MouseButtonEvent to their corresponding ImGuiKey enums.

Current Conclusion for my Setup

Based on these early tests, if your target is strictly a Desktop Tool/Game :

  1. Forcing jME to run on OpenGL Desktop (LWJGL_OPENGL33) feels like the safest choice to keep ImGui stable and performant.
  2. If docked (internal) UI windows are enough for your project, sticking with jME’s new SDL standard is likely the best future-proof path. If you absolutely need floating OS viewports , falling back to the GLFW window context might be required until the Java SDL bindings mature.

I am completely open to any thoughts, workarounds, or alternative viewpoints on this topic. If you have managed to get this combination working differently, or if any of my assumptions need a correction, please let me know!

  • Dear ImGui (1.92.0+) with latest jME3

Note: keep in mind that the latest versions of imgui-java now strictly require Java 17 to compile the project

plugins {
    id 'java'
    id 'application'
}

group = 'com.jme3.imgui'
version = '1.0.0-SNAPSHOT'

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(17)
    }
}

ext {
//    jmeVersion = '3.9.0-stable'
    jmeVersion = '3.10.0-beta1'
    imguiVersion = '1.92.0'
}

repositories {
    mavenCentral()
}

dependencies {
    // jMonkeyEngine
    implementation "org.jmonkeyengine:jme3-core:${jmeVersion}"
    implementation "org.jmonkeyengine:jme3-desktop:${jmeVersion}"
    implementation "org.jmonkeyengine:jme3-lwjgl3:${jmeVersion}"
    runtimeOnly "org.jmonkeyengine:jme3-awt-dialogs:${jmeVersion}"

    // ImGui Java
    implementation "io.github.spair:imgui-java-app:${imguiVersion}"
    implementation "io.github.spair:imgui-java-binding:${imguiVersion}"

    // Native libraries (multi-platform)
    runtimeOnly "io.github.spair:imgui-java-natives-windows:${imguiVersion}"
    runtimeOnly "io.github.spair:imgui-java-natives-linux:${imguiVersion}"
    runtimeOnly "io.github.spair:imgui-java-natives-macos:${imguiVersion}"
}

application {
    mainClass = 'com.jme3.imgui.TestImGuiApplication'
}

tasks.withType(JavaCompile).configureEach {
    options.encoding = 'UTF-8'
}

Discussion in the ATmosphere

Loading comments...