|
|
|
@ -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<ImVec4> 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<ImVec4> 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; |
|
|
|
|
} |
|
|
|
|