Examples: OpenGL: fix for retina screens + io.DisplayFramebufferScale storage (#287)

This commit is contained in:
ocornut 2015-08-27 19:51:02 +01:00
parent a36001212f
commit e58f99179a
6 changed files with 31 additions and 22 deletions

View File

@ -42,15 +42,18 @@ static void ImGui_ImplGlfwGL3_RenderDrawLists(ImDrawData* draw_data)
glEnable(GL_SCISSOR_TEST); glEnable(GL_SCISSOR_TEST);
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
// Handle cases of screen coordinates != from framebuffer coordinates (e.g. retina displays)
ImGuiIO& io = ImGui::GetIO();
float fb_height = io.DisplaySize.y * io.DisplayFramebufferScale.y;
draw_data->ScaleClipRects(io.DisplayFramebufferScale);
// Setup orthographic projection matrix // Setup orthographic projection matrix
const float width = ImGui::GetIO().DisplaySize.x;
const float height = ImGui::GetIO().DisplaySize.y;
const float ortho_projection[4][4] = const float ortho_projection[4][4] =
{ {
{ 2.0f/width, 0.0f, 0.0f, 0.0f }, { 2.0f/io.DisplaySize.x, 0.0f, 0.0f, 0.0f },
{ 0.0f, 2.0f/-height, 0.0f, 0.0f }, { 0.0f, 2.0f/-io.DisplaySize.y, 0.0f, 0.0f },
{ 0.0f, 0.0f, -1.0f, 0.0f }, { 0.0f, 0.0f, -1.0f, 0.0f },
{ -1.0f, 1.0f, 0.0f, 1.0f }, {-1.0f, 1.0f, 0.0f, 1.0f },
}; };
glUseProgram(g_ShaderHandle); glUseProgram(g_ShaderHandle);
glUniform1i(g_AttribLocationTex, 0); glUniform1i(g_AttribLocationTex, 0);
@ -77,7 +80,7 @@ static void ImGui_ImplGlfwGL3_RenderDrawLists(ImDrawData* draw_data)
else else
{ {
glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId);
glScissor((int)pcmd->ClipRect.x, (int)(height - pcmd->ClipRect.w), (int)(pcmd->ClipRect.z - pcmd->ClipRect.x), (int)(pcmd->ClipRect.w - pcmd->ClipRect.y)); glScissor((int)pcmd->ClipRect.x, (int)(fb_height - pcmd->ClipRect.w), (int)(pcmd->ClipRect.z - pcmd->ClipRect.x), (int)(pcmd->ClipRect.w - pcmd->ClipRect.y));
glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer_offset); glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer_offset);
} }
idx_buffer_offset += pcmd->ElemCount; idx_buffer_offset += pcmd->ElemCount;
@ -307,7 +310,8 @@ void ImGui_ImplGlfwGL3_NewFrame()
int display_w, display_h; int display_w, display_h;
glfwGetWindowSize(g_Window, &w, &h); glfwGetWindowSize(g_Window, &w, &h);
glfwGetFramebufferSize(g_Window, &display_w, &display_h); glfwGetFramebufferSize(g_Window, &display_w, &display_h);
io.DisplaySize = ImVec2((float)display_w, (float)display_h); io.DisplaySize = ImVec2((float)w, (float)h);
io.DisplayFramebufferScale = ImVec2((float)display_w / w, (float)display_h / h);
// Setup time step // Setup time step
double current_time = glfwGetTime(); double current_time = glfwGetTime();
@ -320,9 +324,7 @@ void ImGui_ImplGlfwGL3_NewFrame()
{ {
double mouse_x, mouse_y; double mouse_x, mouse_y;
glfwGetCursorPos(g_Window, &mouse_x, &mouse_y); glfwGetCursorPos(g_Window, &mouse_x, &mouse_y);
mouse_x *= (float)display_w / w; // Convert mouse coordinates to pixels io.MousePos = ImVec2((float)mouse_x, (float)mouse_y); // Mouse position in screen coordinates (set to -1,-1 if no mouse / on another screen, etc.)
mouse_y *= (float)display_h / h;
io.MousePos = ImVec2((float)mouse_x, (float)mouse_y); // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.)
} }
else else
{ {

View File

@ -53,7 +53,6 @@ int main(int, char**)
// Main loop // Main loop
while (!glfwWindowShouldClose(window)) while (!glfwWindowShouldClose(window))
{ {
ImGuiIO& io = ImGui::GetIO();
glfwPollEvents(); glfwPollEvents();
ImGui_ImplGlfwGL3_NewFrame(); ImGui_ImplGlfwGL3_NewFrame();
@ -86,7 +85,9 @@ int main(int, char**)
} }
// Rendering // Rendering
glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y); int display_w, display_h;
glfwGetFramebufferSize(window, &display_w, &display_h);
glViewport(0, 0, display_w, display_h);
glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w); glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
ImGui::Render(); ImGui::Render();

View File

@ -40,13 +40,16 @@ static void ImGui_ImplGlfw_RenderDrawLists(ImDrawData* draw_data)
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
//glUseProgram(0); // You may want this if using this code in an OpenGL 3+ context //glUseProgram(0); // You may want this if using this code in an OpenGL 3+ context
// Handle cases of screen coordinates != from framebuffer coordinates (e.g. retina displays)
ImGuiIO& io = ImGui::GetIO();
float fb_height = io.DisplaySize.y * io.DisplayFramebufferScale.y;
draw_data->ScaleClipRects(io.DisplayFramebufferScale);
// Setup orthographic projection matrix // Setup orthographic projection matrix
const float width = ImGui::GetIO().DisplaySize.x;
const float height = ImGui::GetIO().DisplaySize.y;
glMatrixMode(GL_PROJECTION); glMatrixMode(GL_PROJECTION);
glPushMatrix(); glPushMatrix();
glLoadIdentity(); glLoadIdentity();
glOrtho(0.0f, width, height, 0.0f, -1.0f, +1.0f); glOrtho(0.0f, io.DisplaySize.x, io.DisplaySize.y, 0.0f, -1.0f, +1.0f);
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
glPushMatrix(); glPushMatrix();
glLoadIdentity(); glLoadIdentity();
@ -72,7 +75,7 @@ static void ImGui_ImplGlfw_RenderDrawLists(ImDrawData* draw_data)
else else
{ {
glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId);
glScissor((int)pcmd->ClipRect.x, (int)(height - pcmd->ClipRect.w), (int)(pcmd->ClipRect.z - pcmd->ClipRect.x), (int)(pcmd->ClipRect.w - pcmd->ClipRect.y)); glScissor((int)pcmd->ClipRect.x, (int)(fb_height - pcmd->ClipRect.w), (int)(pcmd->ClipRect.z - pcmd->ClipRect.x), (int)(pcmd->ClipRect.w - pcmd->ClipRect.y));
glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer); glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer);
} }
idx_buffer += pcmd->ElemCount; idx_buffer += pcmd->ElemCount;
@ -231,7 +234,8 @@ void ImGui_ImplGlfw_NewFrame()
int display_w, display_h; int display_w, display_h;
glfwGetWindowSize(g_Window, &w, &h); glfwGetWindowSize(g_Window, &w, &h);
glfwGetFramebufferSize(g_Window, &display_w, &display_h); glfwGetFramebufferSize(g_Window, &display_w, &display_h);
io.DisplaySize = ImVec2((float)display_w, (float)display_h); io.DisplaySize = ImVec2((float)w, (float)h);
io.DisplayFramebufferScale = ImVec2((float)display_w / w, (float)display_h / h);
// Setup time step // Setup time step
double current_time = glfwGetTime(); double current_time = glfwGetTime();
@ -244,9 +248,7 @@ void ImGui_ImplGlfw_NewFrame()
{ {
double mouse_x, mouse_y; double mouse_x, mouse_y;
glfwGetCursorPos(g_Window, &mouse_x, &mouse_y); glfwGetCursorPos(g_Window, &mouse_x, &mouse_y);
mouse_x *= (float)display_w / w; // Convert mouse coordinates to pixels io.MousePos = ImVec2((float)mouse_x, (float)mouse_y); // Mouse position in screen coordinates (set to -1,-1 if no mouse / on another screen, etc.)
mouse_y *= (float)display_h / h;
io.MousePos = ImVec2((float)mouse_x, (float)mouse_y); // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.)
} }
else else
{ {

View File

@ -77,7 +77,9 @@ int main(int, char**)
} }
// Rendering // Rendering
glViewport(0, 0, (int)ImGui::GetIO().DisplaySize.x, (int)ImGui::GetIO().DisplaySize.y); int display_w, display_h;
glfwGetFramebufferSize(window, &display_w, &display_h);
glViewport(0, 0, display_w, display_h);
glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w); glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
ImGui::Render(); ImGui::Render();

View File

@ -678,6 +678,7 @@ ImGuiIO::ImGuiIO()
LogFilename = "imgui_log.txt"; LogFilename = "imgui_log.txt";
Fonts = &GImDefaultFontAtlas; Fonts = &GImDefaultFontAtlas;
FontGlobalScale = 1.0f; FontGlobalScale = 1.0f;
DisplayFramebufferScale = ImVec2(1.0f, 1.0f);
MousePos = ImVec2(-1,-1); MousePos = ImVec2(-1,-1);
MousePosPrev = ImVec2(-1,-1); MousePosPrev = ImVec2(-1,-1);
MouseDoubleClickTime = 0.30f; MouseDoubleClickTime = 0.30f;

View File

@ -676,6 +676,7 @@ struct ImGuiIO
ImFontAtlas* Fonts; // <auto> // Load and assemble one or more fonts into a single tightly packed texture. Output to Fonts array. ImFontAtlas* Fonts; // <auto> // Load and assemble one or more fonts into a single tightly packed texture. Output to Fonts array.
float FontGlobalScale; // = 1.0f // Global scale all fonts float FontGlobalScale; // = 1.0f // Global scale all fonts
bool FontAllowUserScaling; // = false // Allow user scaling text of individual window with CTRL+Wheel. bool FontAllowUserScaling; // = false // Allow user scaling text of individual window with CTRL+Wheel.
ImVec2 DisplayFramebufferScale; // = (1.0f,1.0f) // For retina display or other situations where window coordinates are different from framebuffer coordinates. User storage only, presently not used by ImGui.
ImVec2 DisplayVisibleMin; // <unset> (0.0f,0.0f) // If you use DisplaySize as a virtual space larger than your screen, set DisplayVisibleMin/Max to the visible area. ImVec2 DisplayVisibleMin; // <unset> (0.0f,0.0f) // If you use DisplaySize as a virtual space larger than your screen, set DisplayVisibleMin/Max to the visible area.
ImVec2 DisplayVisibleMax; // <unset> (0.0f,0.0f) // If the values are the same, we defaults to Min=(0.0f) and Max=DisplaySize ImVec2 DisplayVisibleMax; // <unset> (0.0f,0.0f) // If the values are the same, we defaults to Min=(0.0f) and Max=DisplaySize