Skip to content

Commit 224fe6c

Browse files
committed
Sync OpenGL code with imgui/backends/imgui_impl_opengl2
1 parent 5c3027a commit 224fe6c

File tree

1 file changed

+133
-56
lines changed

1 file changed

+133
-56
lines changed

imgui-SFML.cpp

Lines changed: 133 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -381,8 +381,8 @@ void Update(sf::Window& window, sf::RenderTarget& target, sf::Time dt) {
381381

382382
void Update(const sf::Vector2i& mousePos, const sf::Vector2f& displaySize, sf::Time dt) {
383383
ImGuiIO& io = ImGui::GetIO();
384-
io.DisplaySize = ImVec2(displaySize.x, displaySize.y);
385384

385+
io.DisplaySize = ImVec2(displaySize.x, displaySize.y);
386386
io.DeltaTime = dt.asSeconds();
387387

388388
if (s_windowHasFocus) {
@@ -440,8 +440,10 @@ void Update(const sf::Vector2i& mousePos, const sf::Vector2f& displaySize, sf::T
440440

441441
void Render(sf::RenderTarget& target) {
442442
target.resetGLStates();
443+
target.pushGLStates();
443444
ImGui::Render();
444445
RenderDrawLists(ImGui::GetDrawData());
446+
target.popGLStates();
445447
}
446448

447449
void Render() {
@@ -450,7 +452,7 @@ void Render() {
450452
}
451453

452454
void Shutdown() {
453-
ImGui::GetIO().Fonts->TexID = (ImTextureID)NULL;
455+
ImGui::GetIO().Fonts->SetTexID(0);
454456

455457
if (s_fontTexture) { // if internal texture was created, we delete it
456458
delete s_fontTexture;
@@ -480,7 +482,8 @@ void UpdateFontTexture() {
480482
texture.create(width, height);
481483
texture.update(pixels);
482484

483-
io.Fonts->TexID = convertGLTextureHandleToImTextureID(texture.getNativeHandle());
485+
ImTextureID texID = convertGLTextureHandleToImTextureID(texture.getNativeHandle());
486+
io.Fonts->SetTexID(texID);
484487
}
485488

486489
sf::Texture& GetFontTexture() {
@@ -705,6 +708,51 @@ GLuint convertImTextureIDToGLTextureHandle(ImTextureID textureID) {
705708
return glTextureHandle;
706709
}
707710

711+
// copied from imgui/backends/imgui_impl_opengl2.cpp
712+
void SetupRenderState(ImDrawData* draw_data, int fb_width, int fb_height) {
713+
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor
714+
// enabled, vertex/texcoord/color pointers, polygon fill.
715+
glEnable(GL_BLEND);
716+
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
717+
// glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); //
718+
// In order to composite our output buffer we need to preserve alpha
719+
glDisable(GL_CULL_FACE);
720+
glDisable(GL_DEPTH_TEST);
721+
glDisable(GL_STENCIL_TEST);
722+
glDisable(GL_LIGHTING);
723+
glDisable(GL_COLOR_MATERIAL);
724+
glEnable(GL_SCISSOR_TEST);
725+
glEnableClientState(GL_VERTEX_ARRAY);
726+
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
727+
glEnableClientState(GL_COLOR_ARRAY);
728+
glDisableClientState(GL_NORMAL_ARRAY);
729+
glEnable(GL_TEXTURE_2D);
730+
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
731+
glShadeModel(GL_SMOOTH);
732+
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
733+
734+
// Setup viewport, orthographic projection matrix
735+
// Our visible imgui space lies from draw_data->DisplayPos (top left) to
736+
// draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single
737+
// viewport apps.
738+
glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height);
739+
glMatrixMode(GL_PROJECTION);
740+
glPushMatrix();
741+
glLoadIdentity();
742+
#ifdef GL_VERSION_ES_CL_1_1
743+
glOrthof(draw_data->DisplayPos.x, draw_data->DisplayPos.x + draw_data->DisplaySize.x,
744+
draw_data->DisplayPos.y + draw_data->DisplaySize.y, draw_data->DisplayPos.y, -1.0f,
745+
+1.0f);
746+
#else
747+
glOrtho(draw_data->DisplayPos.x, draw_data->DisplayPos.x + draw_data->DisplaySize.x,
748+
draw_data->DisplayPos.y + draw_data->DisplaySize.y, draw_data->DisplayPos.y, -1.0f,
749+
+1.0f);
750+
#endif
751+
glMatrixMode(GL_MODELVIEW);
752+
glPushMatrix();
753+
glLoadIdentity();
754+
}
755+
708756
// Rendering callback
709757
void RenderDrawLists(ImDrawData* draw_data) {
710758
ImGui::GetDrawData();
@@ -715,86 +763,115 @@ void RenderDrawLists(ImDrawData* draw_data) {
715763
ImGuiIO& io = ImGui::GetIO();
716764
assert(io.Fonts->TexID != (ImTextureID)NULL); // You forgot to create and set font texture
717765

718-
// scale stuff (needed for proper handling of window resize)
719-
int fb_width = static_cast<int>(io.DisplaySize.x * io.DisplayFramebufferScale.x);
720-
int fb_height = static_cast<int>(io.DisplaySize.y * io.DisplayFramebufferScale.y);
721-
if (fb_width == 0 || fb_height == 0) {
722-
return;
723-
}
766+
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates !=
767+
// framebuffer coordinates)
768+
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x);
769+
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y);
770+
if (fb_width == 0 || fb_height == 0) return;
724771
draw_data->ScaleClipRects(io.DisplayFramebufferScale);
725772

726-
#ifdef GL_VERSION_ES_CL_1_1
727-
GLint last_program, last_texture, last_array_buffer, last_element_array_buffer;
773+
// Backup GL state
774+
// Backup GL state
775+
GLint last_texture;
728776
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
777+
GLint last_polygon_mode[2];
778+
glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode);
779+
GLint last_viewport[4];
780+
glGetIntegerv(GL_VIEWPORT, last_viewport);
781+
GLint last_scissor_box[4];
782+
glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box);
783+
GLint last_shade_model;
784+
glGetIntegerv(GL_SHADE_MODEL, &last_shade_model);
785+
GLint last_tex_env_mode;
786+
glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &last_tex_env_mode);
787+
788+
#ifdef GL_VERSION_ES_CL_1_1
789+
GLint last_array_buffer;
729790
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer);
791+
GLint last_element_array_buffer;
730792
glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &last_element_array_buffer);
731793
#else
732794
glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT);
733795
#endif
734796

735-
glEnable(GL_BLEND);
736-
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
737-
glDisable(GL_CULL_FACE);
738-
glDisable(GL_DEPTH_TEST);
739-
glEnable(GL_SCISSOR_TEST);
740-
glEnable(GL_TEXTURE_2D);
741-
glDisable(GL_LIGHTING);
742-
glEnableClientState(GL_VERTEX_ARRAY);
743-
glEnableClientState(GL_COLOR_ARRAY);
744-
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
745-
746-
glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height);
797+
// Setup desired GL state
798+
SetupRenderState(draw_data, fb_width, fb_height);
747799

748-
glMatrixMode(GL_TEXTURE);
749-
glLoadIdentity();
800+
// Will project scissor/clipping rectangles into framebuffer space
801+
ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports
802+
ImVec2 clip_scale = draw_data->FramebufferScale; // (1,1) unless using retina display which are
803+
// often (2,2)
750804

751-
glMatrixMode(GL_PROJECTION);
752-
glLoadIdentity();
753-
754-
#ifdef GL_VERSION_ES_CL_1_1
755-
glOrthof(0.0f, io.DisplaySize.x, io.DisplaySize.y, 0.0f, -1.0f, +1.0f);
756-
#else
757-
glOrtho(0.0f, io.DisplaySize.x, io.DisplaySize.y, 0.0f, -1.0f, +1.0f);
758-
#endif
759-
760-
glMatrixMode(GL_MODELVIEW);
761-
glLoadIdentity();
762-
763-
for (int n = 0; n < draw_data->CmdListsCount; ++n) {
805+
// Render command lists
806+
for (int n = 0; n < draw_data->CmdListsCount; n++) {
764807
const ImDrawList* cmd_list = draw_data->CmdLists[n];
765-
const unsigned char* vtx_buffer = (const unsigned char*)&cmd_list->VtxBuffer.front();
766-
const ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front();
767-
808+
const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data;
809+
const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data;
768810
glVertexPointer(2, GL_FLOAT, sizeof(ImDrawVert),
769-
(void*)(vtx_buffer + offsetof(ImDrawVert, pos)));
811+
(const GLvoid*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, pos)));
770812
glTexCoordPointer(2, GL_FLOAT, sizeof(ImDrawVert),
771-
(void*)(vtx_buffer + offsetof(ImDrawVert, uv)));
813+
(const GLvoid*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, uv)));
772814
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ImDrawVert),
773-
(void*)(vtx_buffer + offsetof(ImDrawVert, col)));
815+
(const GLvoid*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, col)));
774816

775-
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.size(); ++cmd_i) {
817+
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) {
776818
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
777819
if (pcmd->UserCallback) {
778-
pcmd->UserCallback(cmd_list, pcmd);
820+
// User callback, registered via ImDrawList::AddCallback()
821+
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to
822+
// request the renderer to reset render state.)
823+
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
824+
SetupRenderState(draw_data, fb_width, fb_height);
825+
else
826+
pcmd->UserCallback(cmd_list, pcmd);
779827
} else {
780-
GLuint textureHandle = convertImTextureIDToGLTextureHandle(pcmd->TextureId);
781-
glBindTexture(GL_TEXTURE_2D, textureHandle);
782-
glScissor((int)pcmd->ClipRect.x, (int)(fb_height - pcmd->ClipRect.w),
783-
(int)(pcmd->ClipRect.z - pcmd->ClipRect.x),
784-
(int)(pcmd->ClipRect.w - pcmd->ClipRect.y));
785-
glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT,
786-
idx_buffer);
828+
// Project scissor/clipping rectangles into framebuffer space
829+
ImVec4 clip_rect;
830+
clip_rect.x = (pcmd->ClipRect.x - clip_off.x) * clip_scale.x;
831+
clip_rect.y = (pcmd->ClipRect.y - clip_off.y) * clip_scale.y;
832+
clip_rect.z = (pcmd->ClipRect.z - clip_off.x) * clip_scale.x;
833+
clip_rect.w = (pcmd->ClipRect.w - clip_off.y) * clip_scale.y;
834+
835+
if (clip_rect.x < fb_width && clip_rect.y < fb_height && clip_rect.z >= 0.0f &&
836+
clip_rect.w >= 0.0f) {
837+
// Apply scissor/clipping rectangle
838+
glScissor((int)clip_rect.x, (int)(fb_height - clip_rect.w),
839+
(int)(clip_rect.z - clip_rect.x), (int)(clip_rect.w - clip_rect.y));
840+
841+
// Bind texture, Draw
842+
GLuint textureHandle = convertImTextureIDToGLTextureHandle(pcmd->TextureId);
843+
glBindTexture(GL_TEXTURE_2D, textureHandle);
844+
glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT,
845+
idx_buffer);
846+
}
787847
}
788848
idx_buffer += pcmd->ElemCount;
789849
}
790850
}
851+
852+
// Restore modified GL state
853+
glDisableClientState(GL_COLOR_ARRAY);
854+
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
855+
glDisableClientState(GL_VERTEX_ARRAY);
856+
glBindTexture(GL_TEXTURE_2D, (GLuint)last_texture);
857+
glMatrixMode(GL_MODELVIEW);
858+
glPopMatrix();
859+
glMatrixMode(GL_PROJECTION);
860+
glPopMatrix();
861+
glPopAttrib();
862+
glPolygonMode(GL_FRONT, (GLenum)last_polygon_mode[0]);
863+
glPolygonMode(GL_BACK, (GLenum)last_polygon_mode[1]);
864+
glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2],
865+
(GLsizei)last_viewport[3]);
866+
glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2],
867+
(GLsizei)last_scissor_box[3]);
868+
glShadeModel(last_shade_model);
869+
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, last_tex_env_mode);
870+
791871
#ifdef GL_VERSION_ES_CL_1_1
792-
glBindTexture(GL_TEXTURE_2D, last_texture);
793872
glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer);
794873
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, last_element_array_buffer);
795874
glDisable(GL_SCISSOR_TEST);
796-
#else
797-
glPopAttrib();
798875
#endif
799876
}
800877

0 commit comments

Comments
 (0)