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.
This commit is contained in:
ocornut 2015-08-29 17:44:52 +01:00
parent f2c68109a6
commit 0bb46c824e
3 changed files with 33 additions and 15 deletions

View File

@ -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 Binaries of some of those demos are available at http://www.miracleworld.net/imgui/binaries
TL;DR; 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. 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. 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. OpenGL example, using GLFW + fixed pipeline.
This is simple and should work for all OpenGL enabled applications. This is simple and should work for all OpenGL enabled applications.
Prefer following this example to learn how ImGui works! 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/ opengl3_example/
OpenGL example, using GLFW/GL3W + programmable pipeline. OpenGL example, using GLFW/GL3W + programmable pipeline.
This uses more modern OpenGL calls and custom shaders. This uses more modern OpenGL calls and custom shaders. It's more messy.
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.
directx9_example/ directx9_example/
DirectX9 example, Windows only. DirectX9 example, Windows only.

View File

@ -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) // - 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) static void ImGui_ImplGlfwGL3_RenderDrawLists(ImDrawData* draw_data)
{ {
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled // Backup GL state
GLint last_program, last_texture; GLint last_program, last_texture, last_array_buffer, last_element_array_buffer, last_vertex_array;
glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); glGetIntegerv(GL_CURRENT_PROGRAM, &last_program);
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); 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); glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD); glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
@ -87,13 +92,13 @@ static void ImGui_ImplGlfwGL3_RenderDrawLists(ImDrawData* draw_data)
} }
} }
// Restore modified state // Restore modified GL state
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glUseProgram(last_program); glUseProgram(last_program);
glDisable(GL_SCISSOR_TEST);
glBindTexture(GL_TEXTURE_2D, last_texture); 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() static const char* ImGui_ImplGlfwGL3_GetClipboardText()
@ -162,6 +167,12 @@ void ImGui_ImplGlfwGL3_CreateFontsTexture()
bool ImGui_ImplGlfwGL3_CreateDeviceObjects() 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 = const GLchar *vertex_shader =
"#version 330\n" "#version 330\n"
"uniform mat4 ProjMtx;\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_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)); glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col));
#undef OFFSETOF #undef OFFSETOF
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
ImGui_ImplGlfwGL3_CreateFontsTexture(); 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; return true;
} }

View File

@ -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! // 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. // 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. // 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); glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT);
glEnable(GL_BLEND); glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 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_COLOR_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_VERTEX_ARRAY);
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, last_texture);
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
glPopMatrix(); glPopMatrix();
glMatrixMode(GL_PROJECTION); glMatrixMode(GL_PROJECTION);
@ -147,6 +149,8 @@ bool ImGui_ImplGlfw_CreateDeviceObjects()
io.Fonts->GetTexDataAsAlpha8(&pixels, &width, &height); io.Fonts->GetTexDataAsAlpha8(&pixels, &width, &height);
// Create texture // Create texture
GLint last_texture;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
glGenTextures(1, &g_FontTexture); glGenTextures(1, &g_FontTexture);
glBindTexture(GL_TEXTURE_2D, g_FontTexture); glBindTexture(GL_TEXTURE_2D, g_FontTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 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) // Cleanup (don't clear the input data if you want to append new fonts later)
io.Fonts->ClearInputData(); io.Fonts->ClearInputData();
io.Fonts->ClearTexData(); io.Fonts->ClearTexData();
glBindTexture(GL_TEXTURE_2D, last_texture);
return true; return true;
} }