SpaiR / imgui-java

JNI based binding for Dear ImGui
MIT License
547 stars 90 forks source link

Bug: ImGui is setting the font texture ID to zero everytime the font atlas is built. #214

Open Rusettsten opened 6 months ago

Rusettsten commented 6 months ago

Version

1.86.11

What happened?

When trying to add fonts, I noticed that no matter what file I loaded from memory or file made every texture appear pure black in OpenGL. After some testing, I determined that even when I set the textureID on the font, it still renders as ID 0.

I'm on Windows, 64-bit, with an NVIDIA 3080 GPU.

The font code is below.


private void setupDefaultFont() {
        final ImGuiIO io = ImGui.getIO();
        ImFontAtlas fontAtlas = ImGui.getIO().getFonts();
        fontAtlas.setLocked(false);
        defaultFont = io.getFonts().addFontDefault();
        final ImFontConfig fontConfig = new ImFontConfig();

        fontConfig.setMergeMode(true);
        fontConfig.setFontDataOwnedByAtlas(false);
        fontConfig.setGlyphRanges(fontAtlas.getGlyphRangesDefault());
        defaultFont = fontAtlas.addFontFromMemoryTTF(ResourceReader.loadBytesFromResources("/fonts/Roboto-Medium.ttf"), 5, fontConfig);

        fontAtlas.setTexID(581);
        System.out.println(fontAtlas.getTexID());
        fontAtlas.build();
        System.out.println(fontAtlas.getTexID());
        fontConfig.destroy();
    }

Reproduction

I loaded different fonts using a few different calls and determined the texture ID did not change.

Relevant log output

No response

Rusettsten commented 6 months ago

UPDATE: I was able to replicate the bug by creating a new project with the default ImGui pom.xml for Maven and use the following code.

`import static org.lwjgl.glfw.GLFW.glfwPollEvents; import static org.lwjgl.glfw.GLFW.glfwSwapBuffers; import static org.lwjgl.glfw.GLFW.glfwWindowShouldClose;

import java.awt.Color; import java.io.IOException; import java.net.URISyntaxException; import java.nio.IntBuffer; import java.nio.file.Files; import java.nio.file.Paths; import java.util.Objects;

import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFWErrorCallback; import org.lwjgl.glfw.GLFWVidMode; import org.lwjgl.opengl.GL; import org.lwjgl.opengl.GL32; import org.lwjgl.opengl.GLCapabilities; import org.lwjgl.system.MemoryStack; import org.lwjgl.system.MemoryUtil;

import imgui.ImFont; import imgui.ImFontAtlas; import imgui.ImFontConfig; import imgui.ImGui; import imgui.ImGuiIO; import imgui.flag.ImGuiConfigFlags; import imgui.gl3.ImGuiImplGl3; import imgui.glfw.ImGuiImplGlfw;

public class Main {

/*
 * VARIABLES
 */
private final ImGuiImplGlfw imGuiGlfw = new ImGuiImplGlfw();
private final ImGuiImplGl3 imGuiGl3 = new ImGuiImplGl3();

private String GLSLversion = "#version 150";
private Color colorBg = new Color(.2f, 0f, .4f, 1);

public long windowHandle;
private GLCapabilities capabilities;
private ImFont defaultFont = new ImFont();

/*
 * METHODS - MAIN
 */
public static void main(String[] args) {

    Main main = new Main();
    main.init();

    while(!glfwWindowShouldClose(main.windowHandle)) {
        main.processFrame();
    }
}

/*
 * METHODS - INIT
 */

public void init() {
    initWindow();
    ImGui.createContext();
    imGuiGlfw.init(windowHandle, true);
    imGuiGl3.init(GLSLversion);
    setupDefaultFont();
}

private void initWindow() {
    GLFWErrorCallback.createPrint(System.err).set();

    if (!GLFW.glfwInit()) {
        throw new IllegalStateException("Unable to initialize GLFW!");
    }

    //Set GLSL Version
    GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MAJOR, 3);
    GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MINOR, 2);
    GLFW.glfwWindowHint(GLFW.GLFW_OPENGL_PROFILE, GLFW.GLFW_OPENGL_CORE_PROFILE);  // 3.2+ only
    GLFW.glfwWindowHint(GLFW.GLFW_OPENGL_FORWARD_COMPAT, GLFW.GLFW_TRUE);  //Required for Mac Support

    GLFW.glfwWindowHint(GLFW.GLFW_VISIBLE, GLFW.GLFW_FALSE);

    final GLFWVidMode vidmode = Objects.requireNonNull(GLFW.glfwGetVideoMode(GLFW.glfwGetPrimaryMonitor()));

    windowHandle = GLFW.glfwCreateWindow(vidmode.width(), vidmode.height(), "Font Test", MemoryUtil.NULL, MemoryUtil.NULL);

    if (windowHandle == MemoryUtil.NULL) {
        throw new RuntimeException("Failed to create GUI GLFW window!");
    }

    try (MemoryStack stack = MemoryStack.stackPush()) {
        final IntBuffer pWidth = stack.mallocInt(1); // int*
        final IntBuffer pHeight = stack.mallocInt(1); // int*

        GLFW.glfwGetWindowSize(windowHandle, pWidth, pHeight);
        GLFW.glfwSetWindowPos(windowHandle, (vidmode.width() - pWidth.get(0)) / 2, (vidmode.height() - pHeight.get(0)) / 2);
    }

    GLFW.glfwMakeContextCurrent(windowHandle);
    GLFW.glfwSwapInterval(GLFW.GLFW_TRUE);
    GLFW.glfwShowWindow(windowHandle);
    GLFW.glfwMaximizeWindow(windowHandle);

    capabilities = GL.createCapabilities();
}

public static byte[] loadBytesFromResources(String name) {
    try {
        return Files.readAllBytes(Paths.get(Main.class.getResource(name).toURI()));
    } catch (IOException | URISyntaxException e) {
        e.printStackTrace();
    }
    return null;
}

private void setupDefaultFont() {
    final ImGuiIO io = ImGui.getIO();
    ImFontAtlas fontAtlas = ImGui.getIO().getFonts();
    fontAtlas.setLocked(false);
    defaultFont = io.getFonts().addFontDefault();
    final ImFontConfig fontConfig = new ImFontConfig();

    fontConfig.setMergeMode(true);
    fontConfig.setFontDataOwnedByAtlas(false);
    fontConfig.setGlyphRanges(fontAtlas.getGlyphRangesDefault());
    defaultFont = fontAtlas.addFontFromMemoryTTF(loadBytesFromResources("/fonts/Roboto-Medium.ttf"), 5, fontConfig);

    fontAtlas.build();
    fontConfig.destroy();
}

/*
 * METHODS - RUNNING
 */
public void processFrame() {
    startFrame();
    drawWindow();
    endFrame();
}

private void startFrame() {
    GLFW.glfwMakeContextCurrent(windowHandle);
    GL.setCapabilities(capabilities);
    GL32.glClearColor(colorBg.getRed(), colorBg.getGreen(), colorBg.getBlue(), colorBg.getAlpha());
    GL32.glClear(GL32.GL_COLOR_BUFFER_BIT | GL32.GL_DEPTH_BUFFER_BIT);
    imGuiGlfw.newFrame();
    ImGui.newFrame();
    ImGui.pushFont(defaultFont);
}

private void endFrame() {
    ImGui.popFont();
    ImGui.render();
    imGuiGl3.renderDrawData(ImGui.getDrawData());

    if (ImGui.getIO().hasConfigFlags(ImGuiConfigFlags.ViewportsEnable)) {
        final long backupWindowPtr = GLFW.glfwGetCurrentContext();
        ImGui.updatePlatformWindows();
        ImGui.renderPlatformWindowsDefault();
        GLFW.glfwMakeContextCurrent(backupWindowPtr);
    }

    glfwPollEvents();
    glfwSwapBuffers(windowHandle);
}

private void drawWindow() {
    if(ImGui.begin("Window")) {
        if(ImGui.button("hello")) {

        }
        ImGui.end();
    }
}

/*
 * CONSTRUCTOR
 */
public Main() {

}

} `