From 0bb46c824e205481bdbf35f9ae0b03503968f1ed Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 29 Aug 2015 17:44:52 +0100 Subject: [PATCH] Examples: OpenGL2/3: save/restore some more state correctly. Might save an hour of staring at blank-screen to 5% of the population, worth it. --- examples/README.txt | 9 +++--- .../opengl3_example/imgui_impl_glfw_gl3.cpp | 32 +++++++++++++------ examples/opengl_example/imgui_impl_glfw.cpp | 7 +++- 3 files changed, 33 insertions(+), 15 deletions(-) diff --git a/examples/README.txt b/examples/README.txt index eb167d08..01fe515a 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -2,7 +2,7 @@ Those are standalone ready-to-build applications to demonstrate ImGui. Binaries of some of those demos are available at http://www.miracleworld.net/imgui/binaries TL;DR; - Refer to 'opengl_example' (not 'opengl3_example') to understand how the library is setup. + Refer to 'opengl_example' to understand how the library is setup, because it is the simplest one. Copy the imgui_impl_xxx.cpp/.h files you need if you are using one of provided rendering/IO backends. If using different or your own backend, copy opengl_example/imgui_impl_opengl.cpp/.h to get started. @@ -25,13 +25,12 @@ opengl_example/ OpenGL example, using GLFW + fixed pipeline. This is simple and should work for all OpenGL enabled applications. Prefer following this example to learn how ImGui works! + (You can use this code in a GL3/GL4 context but make sure you disable the programmable pipeline + by calling "glUseProgram(0)" before ImGui::Render.) opengl3_example/ OpenGL example, using GLFW/GL3W + programmable pipeline. - This uses more modern OpenGL calls and custom shaders. - Even if your application is using modern OpenGL you are better off copying the code from the fixed - pipeline version! I don't think there is an advantage using this over the simpler example, but it is - provided for reference. + This uses more modern OpenGL calls and custom shaders. It's more messy. directx9_example/ DirectX9 example, Windows only. diff --git a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp index 63eb3ab9..6b41753e 100644 --- a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp +++ b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp @@ -30,10 +30,15 @@ static unsigned int g_VboHandle = 0, g_VaoHandle = 0, g_ElementsHandle = 0; // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) static void ImGui_ImplGlfwGL3_RenderDrawLists(ImDrawData* draw_data) { - // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled - GLint last_program, last_texture; + // Backup GL state + GLint last_program, last_texture, last_array_buffer, last_element_array_buffer, last_vertex_array; glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer); + glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &last_element_array_buffer); + glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array); + + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled glEnable(GL_BLEND); glBlendEquation(GL_FUNC_ADD); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -87,13 +92,13 @@ static void ImGui_ImplGlfwGL3_RenderDrawLists(ImDrawData* draw_data) } } - // Restore modified state - glBindVertexArray(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + // Restore modified GL state glUseProgram(last_program); - glDisable(GL_SCISSOR_TEST); glBindTexture(GL_TEXTURE_2D, last_texture); + glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, last_element_array_buffer); + glBindVertexArray(last_vertex_array); + glDisable(GL_SCISSOR_TEST); } static const char* ImGui_ImplGlfwGL3_GetClipboardText() @@ -162,6 +167,12 @@ void ImGui_ImplGlfwGL3_CreateFontsTexture() bool ImGui_ImplGlfwGL3_CreateDeviceObjects() { + // Backup GL state + GLint last_texture, last_array_buffer, last_vertex_array; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer); + glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array); + const GLchar *vertex_shader = "#version 330\n" "uniform mat4 ProjMtx;\n" @@ -220,11 +231,14 @@ bool ImGui_ImplGlfwGL3_CreateDeviceObjects() glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); #undef OFFSETOF - glBindVertexArray(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); ImGui_ImplGlfwGL3_CreateFontsTexture(); + // Restore modified GL state + glBindTexture(GL_TEXTURE_2D, last_texture); + glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer); + glBindVertexArray(last_vertex_array); + return true; } diff --git a/examples/opengl_example/imgui_impl_glfw.cpp b/examples/opengl_example/imgui_impl_glfw.cpp index 088be115..5d499a67 100644 --- a/examples/opengl_example/imgui_impl_glfw.cpp +++ b/examples/opengl_example/imgui_impl_glfw.cpp @@ -28,6 +28,8 @@ static void ImGui_ImplGlfw_RenderDrawLists(ImDrawData* draw_data) // We are using the OpenGL fixed pipeline to make the example code simpler to read! // A probable faster way to render would be to collate all vertices from all cmd_lists into a single vertex buffer. // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers. + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -87,7 +89,7 @@ static void ImGui_ImplGlfw_RenderDrawLists(ImDrawData* draw_data) glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); - glBindTexture(GL_TEXTURE_2D, 0); + glBindTexture(GL_TEXTURE_2D, last_texture); glMatrixMode(GL_MODELVIEW); glPopMatrix(); glMatrixMode(GL_PROJECTION); @@ -147,6 +149,8 @@ bool ImGui_ImplGlfw_CreateDeviceObjects() io.Fonts->GetTexDataAsAlpha8(&pixels, &width, &height); // Create texture + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); glGenTextures(1, &g_FontTexture); glBindTexture(GL_TEXTURE_2D, g_FontTexture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); @@ -159,6 +163,7 @@ bool ImGui_ImplGlfw_CreateDeviceObjects() // Cleanup (don't clear the input data if you want to append new fonts later) io.Fonts->ClearInputData(); io.Fonts->ClearTexData(); + glBindTexture(GL_TEXTURE_2D, last_texture); return true; }