pyimgui / pyimgui

Cython-based Python bindings for dear imgui
https://pyimgui.readthedocs.io
BSD 3-Clause "New" or "Revised" License
1.35k stars 180 forks source link

pyimgui + Pygame + PyOpenGL: lack of glBindBuffer(GL_ARRAY_BUFFER,0) causes GUI to not display #314

Open WojtekPachowiak opened 1 year ago

WojtekPachowiak commented 1 year ago

Context

I'm using pyimgui with Pygame and PyOpenGL. I wanted to add GUI to the PyOpenGL application I'm making, but after adding the code from this example: https://github.com/pyimgui/pyimgui/blob/master/doc/examples/integrations_pygame.py No GUI was displayed to me. However, when I ran this example on its own, the GUI was displayed correctly.

Disclaimer

My pyimgui version is the one suggested in this issue (I had a bug in the pip install imgui[pygame] version): https://github.com/pyimgui/pyimgui/issues/210#issuecomment-1036571753

Problematic example

from __future__ import absolute_import

import sys

import pygame
import OpenGL.GL as gl

from imgui.integrations.pygame import PygameRenderer
import imgui

def main():
    pygame.init()
    size = 800, 600

    pygame.display.set_mode(size, pygame.DOUBLEBUF | pygame.OPENGL | pygame.RESIZABLE)

    imgui.create_context()
    impl = PygameRenderer()
    io = imgui.get_io()
    io.display_size = size

    ################# NON DEMO CODE ######################################
    import numpy as np

    VAO = gl.glGenVertexArrays(1)
    VBO = gl.glGenBuffers(1)

    gl.glBindVertexArray(VAO)
    gl.glBindBuffer(gl.GL_ARRAY_BUFFER, VBO)
    # 420 and np.array([1,2,3]) are completely made up
    gl.glBufferData(gl.GL_ARRAY_BUFFER, 420, np.array([1,2,3]), gl.GL_STATIC_DRAW)

    gl.glBindVertexArray(0)
    #gl.glBindBuffer(gl.GL_ARRAY_BUFFER,0)

    ############################################################

    while 1:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()

            impl.process_event(event)

        imgui.new_frame()

        if imgui.begin_main_menu_bar():
            if imgui.begin_menu("File", True):

                clicked_quit, selected_quit = imgui.menu_item(
                    "Quit", 'Cmd+Q', False, True
                )

                if clicked_quit:
                    exit(1)

                imgui.end_menu()
            imgui.end_main_menu_bar()

        imgui.show_test_window()

        imgui.begin("Custom window", True)
        imgui.text("Bar")
        imgui.text_colored("Eggs", 0.2, 1., 0.)
        imgui.end()

        # note: cannot use screen.fill((1, 1, 1)) because pygame's screen
        #       does not support fill() on OpenGL sufraces
        gl.glClearColor(1, 1, 1, 1)
        gl.glClear(gl.GL_COLOR_BUFFER_BIT)
        imgui.render()
        impl.render(imgui.get_draw_data())

        pygame.display.flip()

if __name__ == "__main__":
    main()

The only change is that the code block annotated NON DEMO CODE was added.

Solution

By uncommenting glBindBuffer(GL_ARRAY_BUFFER,0) the GUI is finally displayed correctly.

I'm new to pyimgui repo, but I imagine that in it there must be some OpenGL code which breaks, because the array buffer hasn't been unbinded. Probably, putting glBindBuffer(GL_ARRAY_BUFFER,0) at the beginning of this code would fix the issue.

(optional) What's my application like

What I've presented here is just for demonstration. In my application the PyOpenGL code is bigger and makes more sense. It is based on this tutorial: https://learnopengl.com/Advanced-OpenGL/Instancing And its Python translation: https://github.com/Zuzu-Typ/LearnOpenGL-Python/blob/bcd4c427a5c8d92eaaff400eb7575e711e2a4fff/src/4.advanced_opengl/10.3.asteroids_instanced I found the solution to my bug by putting return statement in different places in the following function: https://github.com/Zuzu-Typ/LearnOpenGL-Python/blob/bcd4c427a5c8d92eaaff400eb7575e711e2a4fff/src/4.advanced_opengl/10.3.asteroids_instanced/mesh.py#L79

WojtekPachowiak commented 1 year ago

Update

Actually the bug still persists even after adding glBindBuffer(GL_ARRAY_BUFFER,0). What finally fixed my issue was also adding glUseProgram(0) after I'm done with using a shader to set some uniform data.