Examples: OpenGL3: cleaned up to match features of OpenGL2 example

This commit is contained in:
omar 2014-12-03 18:40:28 +00:00
parent b02eed3e49
commit 52b5376d9b
2 changed files with 84 additions and 85 deletions

View File

@ -20,14 +20,9 @@ static ImVec2 mousePosScale(1.0f, 1.0f);
// Shader variables // Shader variables
static int shader_handle, vert_handle, frag_handle; static int shader_handle, vert_handle, frag_handle;
static int texture_location, ortho_location; static int texture_location, ortho_location;
static int position_location, uv_location, colour_location; static int position_location, uv_location, colour_location;
//streaming vbo static size_t vbo_max_size = 20000;
//we are going to use the same vertex buffer for all rendering of imgui
//so we need to use a large enough buffer as default.
//the buffer will be resized if needed in the rendering code, but it is not a "free" operation.
static size_t vbo_max_size = 1000000;
static unsigned int vbo_handle, vao_handle; static unsigned int vbo_handle, vao_handle;
// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) // This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure)
@ -65,19 +60,19 @@ static void ImImpl_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_c
glUniform1i(texture_location, 0); glUniform1i(texture_location, 0);
glUniformMatrix4fv(ortho_location, 1, GL_FALSE, &ortho_projection[0][0]); glUniformMatrix4fv(ortho_location, 1, GL_FALSE, &ortho_projection[0][0]);
// we will update the buffer in full, so we need to compute the total size of the buffer. // Grow our buffer according to what we need
size_t total_vtx_count = 0; size_t total_vtx_count = 0;
for (int n = 0; n < cmd_lists_count; n++) for (int n = 0; n < cmd_lists_count; n++)
total_vtx_count += cmd_lists[n]->vtx_buffer.size(); total_vtx_count += cmd_lists[n]->vtx_buffer.size();
glBindBuffer(GL_ARRAY_BUFFER, vbo_handle); glBindBuffer(GL_ARRAY_BUFFER, vbo_handle);
size_t neededBufferSize = total_vtx_count * sizeof(ImDrawVert); size_t neededBufferSize = total_vtx_count * sizeof(ImDrawVert);
if (neededBufferSize > vbo_max_size) if (neededBufferSize > vbo_max_size)
{ {
vbo_max_size = neededBufferSize; vbo_max_size = neededBufferSize + 5000; // Grow buffer
glBufferData(GL_ARRAY_BUFFER, total_vtx_count * sizeof(ImDrawVert), NULL, GL_STREAM_DRAW); glBufferData(GL_ARRAY_BUFFER, neededBufferSize, NULL, GL_STREAM_DRAW);
} }
// Copy and convert all vertices into a single contiguous buffer
unsigned char* buffer_data = (unsigned char*)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); unsigned char* buffer_data = (unsigned char*)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
if (!buffer_data) if (!buffer_data)
return; return;
@ -89,7 +84,6 @@ static void ImImpl_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_c
} }
glUnmapBuffer(GL_ARRAY_BUFFER); glUnmapBuffer(GL_ARRAY_BUFFER);
glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(vao_handle); glBindVertexArray(vao_handle);
int cmd_offset = 0; int cmd_offset = 0;
@ -107,11 +101,11 @@ static void ImImpl_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_c
cmd_offset = vtx_offset; cmd_offset = vtx_offset;
} }
// Restore modified state
glBindVertexArray(0); glBindVertexArray(0);
glUseProgram(0); glUseProgram(0);
glDisable(GL_SCISSOR_TEST); glDisable(GL_SCISSOR_TEST);
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, 0);
} }
static const char* ImImpl_GetClipboardTextFn() static const char* ImImpl_GetClipboardTextFn()
@ -159,7 +153,6 @@ static void glfw_char_callback(GLFWwindow* window, unsigned int c)
ImGui::GetIO().AddInputCharacter((unsigned short)c); ImGui::GetIO().AddInputCharacter((unsigned short)c);
} }
// OpenGL code based on http://open.gl tutorials // OpenGL code based on http://open.gl tutorials
void InitGL() void InitGL()
{ {
@ -183,11 +176,9 @@ void InitGL()
GLenum err = glewInit(); GLenum err = glewInit();
if (GLEW_OK != err) if (GLEW_OK != err)
{
fprintf(stderr, "Error: %s\n", glewGetErrorString(err)); fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
}
const GLchar *vertex_shader = \ const GLchar *vertex_shader =
"#version 330\n" "#version 330\n"
"uniform mat4 ortho;\n" "uniform mat4 ortho;\n"
"in vec2 Position;\n" "in vec2 Position;\n"
@ -202,7 +193,7 @@ void InitGL()
" gl_Position = ortho*vec4(Position.xy,0,1);\n" " gl_Position = ortho*vec4(Position.xy,0,1);\n"
"}\n"; "}\n";
const GLchar* fragment_shader = \ const GLchar* fragment_shader =
"#version 330\n" "#version 330\n"
"uniform sampler2D Texture;\n" "uniform sampler2D Texture;\n"
"in vec2 Frag_UV;\n" "in vec2 Frag_UV;\n"
@ -246,17 +237,19 @@ void InitGL()
glVertexAttribPointer(colour_location, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*) offsetof(ImDrawVert, col)); glVertexAttribPointer(colour_location, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*) offsetof(ImDrawVert, col));
glBindVertexArray(0); glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ARRAY_BUFFER, 0);
} }
void InitImGui() void InitImGui()
{ {
int w, h; int w, h;
int display_w, display_h;
glfwGetWindowSize(window, &w, &h); glfwGetWindowSize(window, &w, &h);
glfwGetFramebufferSize(window, &display_w, &display_h);
mousePosScale.x = (float)display_w / w; // Some screens e.g. Retina display have framebuffer size != from window size, and mouse inputs are given in window/screen coordinates.
mousePosScale.y = (float)display_h / h;
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
io.DisplaySize = ImVec2((float)w, (float)h); // Display size, in pixels. For clamping windows positions. io.DisplaySize = ImVec2((float)display_w, (float)display_h); // Display size, in pixels. For clamping windows positions.
io.DeltaTime = 1.0f / 60.0f; // Time elapsed since last frame, in seconds (in this sample app we'll override this every frame because our timestep is variable) io.DeltaTime = 1.0f / 60.0f; // Time elapsed since last frame, in seconds (in this sample app we'll override this every frame because our timestep is variable)
io.PixelCenterOffset = 0.5f; // Align OpenGL texels io.PixelCenterOffset = 0.5f; // Align OpenGL texels
io.KeyMap[ImGuiKey_Tab] = GLFW_KEY_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array. io.KeyMap[ImGuiKey_Tab] = GLFW_KEY_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array.
@ -309,9 +302,9 @@ void UpdateImGui()
// (we already got mouse wheel, keyboard keys & characters from glfw callbacks polled in glfwPollEvents()) // (we already got mouse wheel, keyboard keys & characters from glfw callbacks polled in glfwPollEvents())
double mouse_x, mouse_y; double mouse_x, mouse_y;
glfwGetCursorPos(window, &mouse_x, &mouse_y); glfwGetCursorPos(window, &mouse_x, &mouse_y);
io.MousePos = ImVec2((float)mouse_x, (float)mouse_y); // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.) io.MousePos = ImVec2((float)mouse_x * mousePosScale.x, (float)mouse_y * mousePosScale.y); // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.)
io.MouseDown[0] = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT) != 0; io.MouseDown[0] = mousePressed[0] || glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame.
io.MouseDown[1] = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_RIGHT) != 0; io.MouseDown[1] = mousePressed[1] || glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_RIGHT) != 0;
// Start the frame // Start the frame
ImGui::NewFrame(); ImGui::NewFrame();
@ -330,17 +323,19 @@ int main(int argc, char** argv)
glfwPollEvents(); glfwPollEvents();
UpdateImGui(); UpdateImGui();
// Create a simple window
// Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug"
static bool show_test_window = true; static bool show_test_window = true;
static bool show_another_window = false; static bool show_another_window = false;
// 1. Show a simple window
// Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug"
{
static float f; static float f;
ImGui::Text("Hello, world!"); ImGui::Text("Hello, world!");
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); ImGui::SliderFloat("float", &f, 0.0f, 1.0f);
show_test_window ^= ImGui::Button("Test Window"); show_test_window ^= ImGui::Button("Test Window");
show_another_window ^= ImGui::Button("Another Window"); show_another_window ^= ImGui::Button("Another Window");
// Calculate and show framerate // Calculate and show frame rate
static float ms_per_frame[120] = { 0 }; static float ms_per_frame[120] = { 0 };
static int ms_per_frame_idx = 0; static int ms_per_frame_idx = 0;
static float ms_per_frame_accum = 0.0f; static float ms_per_frame_accum = 0.0f;
@ -350,16 +345,9 @@ int main(int argc, char** argv)
ms_per_frame_idx = (ms_per_frame_idx + 1) % 120; ms_per_frame_idx = (ms_per_frame_idx + 1) % 120;
const float ms_per_frame_avg = ms_per_frame_accum / 120; const float ms_per_frame_avg = ms_per_frame_accum / 120;
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", ms_per_frame_avg, 1000.0f / ms_per_frame_avg); ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", ms_per_frame_avg, 1000.0f / ms_per_frame_avg);
// Show the ImGui test window
// Most of user example code is in ImGui::ShowTestWindow()
if (show_test_window)
{
ImGui::SetNewWindowDefaultPos(ImVec2(650, 20)); // Normally user code doesn't need/want to call it because positions are saved in .ini file anyway. Here we just want to make the demo initial state a bit more friendly!
ImGui::ShowTestWindow(&show_test_window);
} }
// Show another simple window // 2. Show another simple window, this time using an explicit Begin/End pair
if (show_another_window) if (show_another_window)
{ {
ImGui::Begin("Another Window", &show_another_window, ImVec2(200,100)); ImGui::Begin("Another Window", &show_another_window, ImVec2(200,100));
@ -367,6 +355,13 @@ int main(int argc, char** argv)
ImGui::End(); ImGui::End();
} }
// 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow()
if (show_test_window)
{
ImGui::SetNewWindowDefaultPos(ImVec2(650, 20)); // Normally user code doesn't need/want to call this, because positions are saved in .ini file. Here we just want to make the demo initial state a bit more friendly!
ImGui::ShowTestWindow(&show_test_window);
}
// Rendering // Rendering
glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y); glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y);
glClearColor(0.8f, 0.6f, 0.6f, 1.0f); glClearColor(0.8f, 0.6f, 0.6f, 1.0f);
@ -374,6 +369,8 @@ int main(int argc, char** argv)
ImGui::Render(); ImGui::Render();
glfwSwapBuffers(window); glfwSwapBuffers(window);
} }
// Cleanup
if (vao_handle) glDeleteVertexArrays(1, &vao_handle); if (vao_handle) glDeleteVertexArrays(1, &vao_handle);
if (vbo_handle) glDeleteBuffers(1, &vbo_handle); if (vbo_handle) glDeleteBuffers(1, &vbo_handle);
glDetachShader(shader_handle, vert_handle); glDetachShader(shader_handle, vert_handle);

View File

@ -305,7 +305,9 @@ int main(int argc, char** argv)
glfwSwapBuffers(window); glfwSwapBuffers(window);
} }
// Cleanup
ImGui::Shutdown(); ImGui::Shutdown();
glfwTerminate(); glfwTerminate();
return 0; return 0;
} }