Using PyOpenGL with GLU and PyGame.
I have a VAO with a VBO and IBO behind it that provide the vertex and index data for the faces. In addition I have a simple vertex and fragment shader. Things render find.
However, I'd like to add ImGUI to my application. So I did the following:
def main():
width = 800
height = 800
display = (width, height)
pygame.init()
pygame.display.set_caption('OpenGL VAO with pygame')
pygame.display.set_mode(display, pygame.DOUBLEBUF | pygame.OPENGL | pygame.RESIZABLE)
pygame.display.gl_set_attribute(pygame.GL_CONTEXT_MAJOR_VERSION, 4)
pygame.display.gl_set_attribute(pygame.GL_CONTEXT_MINOR_VERSION, 1)
pygame.display.gl_set_attribute(pygame.GL_CONTEXT_PROFILE_MASK, pygame.GL_CONTEXT_PROFILE_CORE)
imgui.create_context()
impl = PygameRenderer()
io = imgui.get_io()
#io.set_WantCaptureMouse(True)
io.display_size = width, height
init()
clock = pygame.time.Clock()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
impl.process_event(event)
render(time=clock, imgui_impl=impl)
pygame.display.flip()
pygame.time.wait(10)
if __name__ == '__main__':
main()
There are two important functions here:
init()
- loads and compiles the shaders into a program, creates the VBO and IBO and binds themrender()
- clears depth and color buffers, creates and binds the VAO, turns on the shaders, renders the contents of the VAO etc.The render()
function looks similar to this:
def render(time, imgui_impl):
glClearColor(0.0, 0.0, 0.0, 0.0)
glClearDepth(1.0)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glUseProgram(program)
glBindVertexArray(vao)
fElapsedTime = pygame.time.get_ticks() / 1000.0
for func in g_instanceList:
transformMatrix = func(fElapsedTime)
glUniformMatrix4fv(modelToCameraMatrixUnif, 1, GL_FALSE, transformMatrix.transpose())
glDrawElements(GL_TRIANGLES, len(indexData), GL_UNSIGNED_SHORT, None)
glBindVertexArray(0)
glUseProgram(0)
imgui.new_frame()
imgui.begin('Controls', True)
changed, strings = imgui.input_text('Path to OBJ', '...', imgui.INPUT_TEXT_READ_ONLY)
imgui.same_line()
if imgui.button('Load'):
print('Loading', strings)
imgui.end()
imgui.end_frame()
imgui.render()
print(imgui.get_draw_data().valid)
imgui_impl.render(imgui.get_draw_data())
My problem is that ImGUI doesn't show at all. I checked the validity of the ImGui draw data object
imgui.get_draw_data().valid
and it returns True
.
How should I handle the ImGUI data? I do turn of the program (shaders) so the only issue I am thinking of is the VAO and that is somehow affects the rendering of the UI.
I found this post that mentions an issue that appears to be similar to mine. However, the source of the problem for that OP is different. The attempt they made to solve it though worked for me, namely unbind all buffers before calling the ImGui procedures.
In my original code I am unbinding the VAO and also disabling the shader program. It appears that unbinding the VBO is enough even though I did that for the IBO too:
def render(time, imgui_impl):
glClearColor(0.0, 0.0, 0.0, 0.0)
glClearDepth(1.0)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glUseProgram(program)
glBindVertexArray(vao)
fElapsedTime = pygame.time.get_ticks() / 1000.0
for func in g_instanceList:
transformMatrix = func(fElapsedTime)
glUniformMatrix4fv(modelToCameraMatrixUnif, 1, GL_FALSE, transformMatrix.transpose())
glDrawElements(GL_TRIANGLES, len(indexData), GL_UNSIGNED_SHORT, None)
glBindVertexArray(0) # Disable the VAO
glBindBuffer(GL_ARRAY_BUFFER, 0) # Disable the VBO
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) # Disable the IBO (not required)
glUseProgram(0) # Disable the shader program
imgui.new_frame()
# Add ImGUI contents
imgui.end_frame()
imgui.render()
imgui_impl.render(imgui.get_draw_data())