diff --git a/examples/directx9_example/main.cpp b/examples/directx9_example/main.cpp index 36be8a62..01cb3c6c 100644 --- a/examples/directx9_example/main.cpp +++ b/examples/directx9_example/main.cpp @@ -12,16 +12,15 @@ static LPDIRECT3D9 g_pD3D = NULL; // Used to create the D3DDevice static LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; // Our rendering device static LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL; // Buffer to hold vertices static LPDIRECT3DTEXTURE9 g_pTexture = NULL; // Our texture - struct CUSTOMVERTEX { D3DXVECTOR3 position; D3DCOLOR color; float tu, tv; }; - #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1) +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structuer) static void ImImpl_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_count) { size_t total_vtx_count = 0; @@ -30,31 +29,13 @@ static void ImImpl_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_c if (total_vtx_count == 0) return; - ImVector clip_rect_stack; - clip_rect_stack.push_back(ImVec4(-9999,-9999,+9999,+9999)); - - // Setup orthographic projection - // Set up world matrix - D3DXMATRIXA16 mat; - D3DXMatrixIdentity(&mat); - g_pd3dDevice->SetTransform(D3DTS_WORLD, &mat); - g_pd3dDevice->SetTransform(D3DTS_VIEW, &mat); - D3DXMatrixOrthoOffCenterLH(&mat, 0.0f, ImGui::GetIO().DisplaySize.x, ImGui::GetIO().DisplaySize.y, 0.0f, -1.0f, +1.0f); - g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &mat); - - D3DSURFACE_DESC texture_desc; - g_pTexture->GetLevelDesc(0, &texture_desc); - - // Fill the vertex buffer + // Copy and convert all vertices into a single contiguous buffer CUSTOMVERTEX* vtx_dst; if (g_pVB->Lock(0, total_vtx_count, (void**)&vtx_dst, D3DLOCK_DISCARD) < 0) return; - for (int n = 0; n < cmd_lists_count; n++) { const ImDrawList* cmd_list = cmd_lists[n]; - if (cmd_list->commands.empty() || cmd_list->vtx_buffer.empty()) - continue; const ImDrawVert* vtx_src = &cmd_list->vtx_buffer[0]; for (size_t i = 0; i < cmd_list->vtx_buffer.size(); i++) { @@ -73,11 +54,10 @@ static void ImImpl_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_c g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof( CUSTOMVERTEX ) ); g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX ); - // Setup render state: alpha-blending enabled, no face culling, no depth testing + // Setup render state: alpha-blending, no face culling, no depth testing g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE ); g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, false ); g_pd3dDevice->SetRenderState( D3DRS_ZENABLE, false ); - g_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, true ); g_pd3dDevice->SetRenderState( D3DRS_BLENDOP, D3DBLENDOP_ADD ); g_pd3dDevice->SetRenderState( D3DRS_ALPHATESTENABLE, false ); @@ -94,17 +74,29 @@ static void ImImpl_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_c g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE ); g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE ); - int vtx_consumed = 0; // offset in vertex buffer. each command consume ImDrawCmd::vtx_count of those - bool clip_rect_dirty = true; + // Setup orthographic projection matrix + D3DXMATRIXA16 mat; + D3DXMatrixIdentity(&mat); + g_pd3dDevice->SetTransform(D3DTS_WORLD, &mat); + g_pd3dDevice->SetTransform(D3DTS_VIEW, &mat); + D3DXMatrixOrthoOffCenterLH(&mat, 0.0f, ImGui::GetIO().DisplaySize.x, ImGui::GetIO().DisplaySize.y, 0.0f, -1.0f, +1.0f); + g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &mat); + // Render command lists + int vtx_consumed = 0; // offset in vertex buffer. each command consume ImDrawCmd::vtx_count of those for (int n = 0; n < cmd_lists_count; n++) { const ImDrawList* cmd_list = cmd_lists[n]; - if (cmd_list->commands.empty() || cmd_list->vtx_buffer.empty()) - continue; + + // Setup stack of clipping rectangles + bool clip_rect_dirty = true; + int clip_rect_buf_consumed = 0; + ImVector clip_rect_stack; + clip_rect_stack.push_back(ImVec4(-9999,-9999,+9999,+9999)); + + // Render command list const ImDrawCmd* pcmd = &cmd_list->commands.front(); const ImDrawCmd* pcmd_end = &cmd_list->commands.back(); - int clip_rect_buf_consumed = 0; // offset in cmd_list->clip_rect_buffer. each PushClipRect command consume 1 of those. while (pcmd <= pcmd_end) { const ImDrawCmd& cmd = *pcmd++; @@ -289,7 +281,6 @@ void InitImGui() io.RenderDrawListsFn = ImImpl_RenderDrawLists; io.SetClipboardTextFn = ImImpl_SetClipboardTextFn; io.GetClipboardTextFn = ImImpl_GetClipboardTextFn; - // Create the vertex buffer if (g_pd3dDevice->CreateVertexBuffer(10000 * sizeof(CUSTOMVERTEX), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL) < 0) @@ -396,13 +387,15 @@ int WINAPI wWinMain(HINSTANCE hInst, HINSTANCE, LPWSTR, int) ImGui::End(); } - // 3) Render + // 3) Rendering + // Clear frame buffer g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, false); g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false); g_pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, false); - g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(204, 153, 153), 1.0f, 0); // Clear the backbuffer and the zbuffer + g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(204, 153, 153), 1.0f, 0); if (g_pd3dDevice->BeginScene() >= 0) { + // Render ImGui ImGui::Render(); g_pd3dDevice->EndScene(); } diff --git a/examples/opengl_example/main.cpp b/examples/opengl_example/main.cpp index f6a026de..76989320 100644 --- a/examples/opengl_example/main.cpp +++ b/examples/opengl_example/main.cpp @@ -18,6 +18,7 @@ static GLuint fontTex; static GLint uniMVP; static GLint uniClipRect; +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structuer) static void ImImpl_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_count) { size_t total_vtx_count = 0; @@ -26,24 +27,7 @@ static void ImImpl_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_c if (total_vtx_count == 0) return; - int read_pos_clip_rect_buf = 0; // offset in 'clip_rect_buffer'. each PushClipRect command consume 1 of those. - - ImVector clip_rect_stack; - clip_rect_stack.push_back(ImVec4(-9999,-9999,+9999,+9999)); - - // Setup orthographic projection - const float L = 0.0f; - const float R = ImGui::GetIO().DisplaySize.x; - const float B = ImGui::GetIO().DisplaySize.y; - const float T = 0.0f; - const float mvp[4][4] = - { - { 2.0f/(R-L), 0.0f, 0.0f, 0.0f }, - { 0.0f, 2.0f/(T-B), 0.0f, 0.0f }, - { 0.0f, 0.0f, -1.0f, 0.0f }, - { -(R+L)/(R-L), -(T+B)/(T-B), 0.0f, 1.0f }, - }; - + // Copy all vertices into a single contiguous GL buffer glBindBuffer(GL_ARRAY_BUFFER, vbo); glBindVertexArray(vao); glBufferData(GL_ARRAY_BUFFER, total_vtx_count * sizeof(ImDrawVert), NULL, GL_STREAM_DRAW); @@ -54,37 +38,51 @@ static void ImImpl_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_c for (int n = 0; n < cmd_lists_count; n++) { const ImDrawList* cmd_list = cmd_lists[n]; - if (!cmd_list->vtx_buffer.empty()) - { - memcpy(buffer_data, &cmd_list->vtx_buffer[0], cmd_list->vtx_buffer.size() * sizeof(ImDrawVert)); - buffer_data += cmd_list->vtx_buffer.size() * sizeof(ImDrawVert); - vtx_consumed += cmd_list->vtx_buffer.size(); - } + memcpy(buffer_data, &cmd_list->vtx_buffer[0], cmd_list->vtx_buffer.size() * sizeof(ImDrawVert)); + buffer_data += cmd_list->vtx_buffer.size() * sizeof(ImDrawVert); + vtx_consumed += cmd_list->vtx_buffer.size(); } glUnmapBuffer(GL_ARRAY_BUFFER); - glUseProgram(shaderProgram); - glUniformMatrix4fv(uniMVP, 1, GL_FALSE, &mvp[0][0]); - // Setup render state: alpha-blending enabled, no face culling, no depth testing glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); + // Bind texture and enable our shader glBindTexture(GL_TEXTURE_2D, fontTex); + glUseProgram(shaderProgram); - vtx_consumed = 0; // offset in vertex buffer. each command consume ImDrawCmd::vtx_count of those - bool clip_rect_dirty = true; + // Setup orthographic projection matrix + const float L = 0.0f; + const float R = ImGui::GetIO().DisplaySize.x; + const float B = ImGui::GetIO().DisplaySize.y; + const float T = 0.0f; + const float mvp[4][4] = + { + { 2.0f/(R-L), 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/(T-B), 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -(R+L)/(R-L), -(T+B)/(T-B), 0.0f, 1.0f }, + }; + glUniformMatrix4fv(uniMVP, 1, GL_FALSE, &mvp[0][0]); + // Render command lists + vtx_consumed = 0; // offset in vertex buffer. each command consume ImDrawCmd::vtx_count of those for (int n = 0; n < cmd_lists_count; n++) { const ImDrawList* cmd_list = cmd_lists[n]; - if (cmd_list->commands.empty() || cmd_list->vtx_buffer.empty()) - continue; + + // Setup stack of clipping rectangles + bool clip_rect_dirty = true; + int clip_rect_buf_consumed = 0; + ImVector clip_rect_stack; + clip_rect_stack.push_back(ImVec4(-9999,-9999,+9999,+9999)); + + // Render command list const ImDrawCmd* pcmd = &cmd_list->commands.front(); const ImDrawCmd* pcmd_end = &cmd_list->commands.back(); - int clip_rect_buf_consumed = 0; // offset in cmd_list->clip_rect_buffer. each PushClipRect command consume 1 of those. while (pcmd <= pcmd_end) { const ImDrawCmd& cmd = *pcmd++; @@ -132,7 +130,6 @@ static void ImImpl_SetClipboardTextFn(const char* text, const char* text_end) } // Shader sources -// FIXME-OPT: clip at vertex level const GLchar* vertexSource = "#version 150 core\n" "uniform mat4 MVP;" @@ -164,6 +161,7 @@ const GLchar* fragmentSource = " o_col.w *= (step(ClipRect.x,pixel_pos.x) * step(ClipRect.y,pixel_pos.y) * step(pixel_pos.x,ClipRect.z) * step(pixel_pos.y,ClipRect.w));" // Clipping: branch-less, set alpha 0.0f "}"; +// GLFW callbacks to get events static void glfw_error_callback(int error, const char* description) { fputs(description, stderr); @@ -251,7 +249,6 @@ void InitImGui() io.SetClipboardTextFn = ImImpl_SetClipboardTextFn; io.GetClipboardTextFn = ImImpl_GetClipboardTextFn; - // Setup graphics backend GLint status = GL_TRUE; GLenum err = GL_NO_ERROR; @@ -394,7 +391,7 @@ int main(int argc, char** argv) ImGui::End(); } - // 3) Render + // 3) Rendering glClearColor(0.8f, 0.6f, 0.6f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); ImGui::Render(); @@ -403,6 +400,5 @@ int main(int argc, char** argv) } Shutdown(); - return 0; }