Updated OpenGL3 imgui backend to once again support multi-viewports

This commit is contained in:
WerWolv 2021-01-30 18:01:23 +01:00
parent a3d71b1dca
commit 3bd01c0d98

View file

@ -5,6 +5,7 @@
// Implemented features: // Implemented features:
// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID! // [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// [x] Renderer: Desktop GL only: Support for large meshes (64k+ vertices) with 16-bit indices. // [x] Renderer: Desktop GL only: Support for large meshes (64k+ vertices) with 16-bit indices.
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
@ -13,6 +14,7 @@
// CHANGELOG // CHANGELOG
// (minor and older changes stripped away, please see git history for details) // (minor and older changes stripped away, please see git history for details)
// 2021-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2021-01-03: OpenGL: Backup, setup and restore GL_STENCIL_TEST state. // 2021-01-03: OpenGL: Backup, setup and restore GL_STENCIL_TEST state.
// 2020-10-23: OpenGL: Backup, setup and restore GL_PRIMITIVE_RESTART state. // 2020-10-23: OpenGL: Backup, setup and restore GL_PRIMITIVE_RESTART state.
// 2020-10-15: OpenGL: Use glGetString(GL_VERSION) instead of glGetIntegerv(GL_MAJOR_VERSION, ...) when the later returns zero (e.g. Desktop GL 2.x) // 2020-10-15: OpenGL: Use glGetString(GL_VERSION) instead of glGetIntegerv(GL_MAJOR_VERSION, ...) when the later returns zero (e.g. Desktop GL 2.x)
@ -150,6 +152,10 @@ static GLint g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0;
static GLuint g_AttribLocationVtxPos = 0, g_AttribLocationVtxUV = 0, g_AttribLocationVtxColor = 0; // Vertex attributes location static GLuint g_AttribLocationVtxPos = 0, g_AttribLocationVtxUV = 0, g_AttribLocationVtxColor = 0; // Vertex attributes location
static unsigned int g_VboHandle = 0, g_ElementsHandle = 0; static unsigned int g_VboHandle = 0, g_ElementsHandle = 0;
// Forward Declarations
static void ImGui_ImplOpenGL3_InitPlatformInterface();
static void ImGui_ImplOpenGL3_ShutdownPlatformInterface();
// Functions // Functions
bool ImGui_ImplOpenGL3_Init(const char* glsl_version) bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
{ {
@ -177,6 +183,7 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
if (g_GlVersion >= 320) if (g_GlVersion >= 320)
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
#endif #endif
io.BackendFlags |= ImGuiBackendFlags_RendererHasViewports; // We can create multi-viewports on the Renderer side (optional)
// Store GLSL version string so we can refer to it later in case we recreate shaders. // Store GLSL version string so we can refer to it later in case we recreate shaders.
// Note: GLSL version is NOT the same as GL version. Leave this to NULL if unsure. // Note: GLSL version is NOT the same as GL version. Leave this to NULL if unsure.
@ -228,11 +235,15 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
GLint current_texture; GLint current_texture;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &current_texture); glGetIntegerv(GL_TEXTURE_BINDING_2D, &current_texture);
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
ImGui_ImplOpenGL3_InitPlatformInterface();
return true; return true;
} }
void ImGui_ImplOpenGL3_Shutdown() void ImGui_ImplOpenGL3_Shutdown()
{ {
ImGui_ImplOpenGL3_ShutdownPlatformInterface();
ImGui_ImplOpenGL3_DestroyDeviceObjects(); ImGui_ImplOpenGL3_DestroyDeviceObjects();
} }
@ -279,12 +290,12 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid
if (!clip_origin_lower_left) { float tmp = T; T = B; B = tmp; } // Swap top and bottom if origin is upper left if (!clip_origin_lower_left) { float tmp = T; T = B; B = tmp; } // Swap top and bottom if origin is upper left
#endif #endif
const float ortho_projection[4][4] = const float ortho_projection[4][4] =
{ {
{ 2.0f/(R-L), 0.0f, 0.0f, 0.0f }, { 2.0f/(R-L), 0.0f, 0.0f, 0.0f },
{ 0.0f, 2.0f/(T-B), 0.0f, 0.0f }, { 0.0f, 2.0f/(T-B), 0.0f, 0.0f },
{ 0.0f, 0.0f, -1.0f, 0.0f }, { 0.0f, 0.0f, -1.0f, 0.0f },
{ (R+L)/(L-R), (T+B)/(B-T), 0.0f, 1.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.0f, 1.0f },
}; };
glUseProgram(g_ShaderHandle); glUseProgram(g_ShaderHandle);
glUniform1i(g_AttribLocationTex, 0); glUniform1i(g_AttribLocationTex, 0);
glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]);
@ -408,7 +419,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
glDrawElementsBaseVertex(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx)), (GLint)pcmd->VtxOffset); glDrawElementsBaseVertex(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx)), (GLint)pcmd->VtxOffset);
else else
#endif #endif
glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx))); glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx)));
} }
} }
} }
@ -541,104 +552,104 @@ bool ImGui_ImplOpenGL3_CreateDeviceObjects()
sscanf(g_GlslVersionString, "#version %d", &glsl_version); sscanf(g_GlslVersionString, "#version %d", &glsl_version);
const GLchar* vertex_shader_glsl_120 = const GLchar* vertex_shader_glsl_120 =
"uniform mat4 ProjMtx;\n" "uniform mat4 ProjMtx;\n"
"attribute vec2 Position;\n" "attribute vec2 Position;\n"
"attribute vec2 UV;\n" "attribute vec2 UV;\n"
"attribute vec4 Color;\n" "attribute vec4 Color;\n"
"varying vec2 Frag_UV;\n" "varying vec2 Frag_UV;\n"
"varying vec4 Frag_Color;\n" "varying vec4 Frag_Color;\n"
"void main()\n" "void main()\n"
"{\n" "{\n"
" Frag_UV = UV;\n" " Frag_UV = UV;\n"
" Frag_Color = Color;\n" " Frag_Color = Color;\n"
" gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n"
"}\n"; "}\n";
const GLchar* vertex_shader_glsl_130 = const GLchar* vertex_shader_glsl_130 =
"uniform mat4 ProjMtx;\n" "uniform mat4 ProjMtx;\n"
"in vec2 Position;\n" "in vec2 Position;\n"
"in vec2 UV;\n" "in vec2 UV;\n"
"in vec4 Color;\n" "in vec4 Color;\n"
"out vec2 Frag_UV;\n" "out vec2 Frag_UV;\n"
"out vec4 Frag_Color;\n" "out vec4 Frag_Color;\n"
"void main()\n" "void main()\n"
"{\n" "{\n"
" Frag_UV = UV;\n" " Frag_UV = UV;\n"
" Frag_Color = Color;\n" " Frag_Color = Color;\n"
" gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n"
"}\n"; "}\n";
const GLchar* vertex_shader_glsl_300_es = const GLchar* vertex_shader_glsl_300_es =
"precision mediump float;\n" "precision mediump float;\n"
"layout (location = 0) in vec2 Position;\n" "layout (location = 0) in vec2 Position;\n"
"layout (location = 1) in vec2 UV;\n" "layout (location = 1) in vec2 UV;\n"
"layout (location = 2) in vec4 Color;\n" "layout (location = 2) in vec4 Color;\n"
"uniform mat4 ProjMtx;\n" "uniform mat4 ProjMtx;\n"
"out vec2 Frag_UV;\n" "out vec2 Frag_UV;\n"
"out vec4 Frag_Color;\n" "out vec4 Frag_Color;\n"
"void main()\n" "void main()\n"
"{\n" "{\n"
" Frag_UV = UV;\n" " Frag_UV = UV;\n"
" Frag_Color = Color;\n" " Frag_Color = Color;\n"
" gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n"
"}\n"; "}\n";
const GLchar* vertex_shader_glsl_410_core = const GLchar* vertex_shader_glsl_410_core =
"layout (location = 0) in vec2 Position;\n" "layout (location = 0) in vec2 Position;\n"
"layout (location = 1) in vec2 UV;\n" "layout (location = 1) in vec2 UV;\n"
"layout (location = 2) in vec4 Color;\n" "layout (location = 2) in vec4 Color;\n"
"uniform mat4 ProjMtx;\n" "uniform mat4 ProjMtx;\n"
"out vec2 Frag_UV;\n" "out vec2 Frag_UV;\n"
"out vec4 Frag_Color;\n" "out vec4 Frag_Color;\n"
"void main()\n" "void main()\n"
"{\n" "{\n"
" Frag_UV = UV;\n" " Frag_UV = UV;\n"
" Frag_Color = Color;\n" " Frag_Color = Color;\n"
" gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n"
"}\n"; "}\n";
const GLchar* fragment_shader_glsl_120 = const GLchar* fragment_shader_glsl_120 =
"#ifdef GL_ES\n" "#ifdef GL_ES\n"
" precision mediump float;\n" " precision mediump float;\n"
"#endif\n" "#endif\n"
"uniform sampler2D Texture;\n" "uniform sampler2D Texture;\n"
"varying vec2 Frag_UV;\n" "varying vec2 Frag_UV;\n"
"varying vec4 Frag_Color;\n" "varying vec4 Frag_Color;\n"
"void main()\n" "void main()\n"
"{\n" "{\n"
" gl_FragColor = Frag_Color * texture2D(Texture, Frag_UV.st);\n" " gl_FragColor = Frag_Color * texture2D(Texture, Frag_UV.st);\n"
"}\n"; "}\n";
const GLchar* fragment_shader_glsl_130 = const GLchar* fragment_shader_glsl_130 =
"uniform sampler2D Texture;\n" "uniform sampler2D Texture;\n"
"in vec2 Frag_UV;\n" "in vec2 Frag_UV;\n"
"in vec4 Frag_Color;\n" "in vec4 Frag_Color;\n"
"out vec4 Out_Color;\n" "out vec4 Out_Color;\n"
"void main()\n" "void main()\n"
"{\n" "{\n"
" Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n" " Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n"
"}\n"; "}\n";
const GLchar* fragment_shader_glsl_300_es = const GLchar* fragment_shader_glsl_300_es =
"precision mediump float;\n" "precision mediump float;\n"
"uniform sampler2D Texture;\n" "uniform sampler2D Texture;\n"
"in vec2 Frag_UV;\n" "in vec2 Frag_UV;\n"
"in vec4 Frag_Color;\n" "in vec4 Frag_Color;\n"
"layout (location = 0) out vec4 Out_Color;\n" "layout (location = 0) out vec4 Out_Color;\n"
"void main()\n" "void main()\n"
"{\n" "{\n"
" Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n" " Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n"
"}\n"; "}\n";
const GLchar* fragment_shader_glsl_410_core = const GLchar* fragment_shader_glsl_410_core =
"in vec2 Frag_UV;\n" "in vec2 Frag_UV;\n"
"in vec4 Frag_Color;\n" "in vec4 Frag_Color;\n"
"uniform sampler2D Texture;\n" "uniform sampler2D Texture;\n"
"layout (location = 0) out vec4 Out_Color;\n" "layout (location = 0) out vec4 Out_Color;\n"
"void main()\n" "void main()\n"
"{\n" "{\n"
" Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n" " Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n"
"}\n"; "}\n";
// Select shaders matching our GLSL versions // Select shaders matching our GLSL versions
const GLchar* vertex_shader = NULL; const GLchar* vertex_shader = NULL;
@ -717,3 +728,31 @@ void ImGui_ImplOpenGL3_DestroyDeviceObjects()
ImGui_ImplOpenGL3_DestroyFontsTexture(); ImGui_ImplOpenGL3_DestroyFontsTexture();
} }
//--------------------------------------------------------------------------------------------------------
// MULTI-VIEWPORT / PLATFORM INTERFACE SUPPORT
// This is an _advanced_ and _optional_ feature, allowing the backend to create and handle multiple viewports simultaneously.
// If you are new to dear imgui or creating a new binding for dear imgui, it is recommended that you completely ignore this section first..
//--------------------------------------------------------------------------------------------------------
static void ImGui_ImplOpenGL3_RenderWindow(ImGuiViewport* viewport, void*)
{
if (!(viewport->Flags & ImGuiViewportFlags_NoRendererClear))
{
ImVec4 clear_color = ImVec4(0.0f, 0.0f, 0.0f, 1.0f);
glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
glClear(GL_COLOR_BUFFER_BIT);
}
ImGui_ImplOpenGL3_RenderDrawData(viewport->DrawData);
}
static void ImGui_ImplOpenGL3_InitPlatformInterface()
{
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
platform_io.Renderer_RenderWindow = ImGui_ImplOpenGL3_RenderWindow;
}
static void ImGui_ImplOpenGL3_ShutdownPlatformInterface()
{
ImGui::DestroyPlatformWindows();
}