178 lines
6.4 KiB
C++
178 lines
6.4 KiB
C++
#include "guimesh.h"
|
|
#include "opengl.h"
|
|
#include "imgui/imgui.h"
|
|
|
|
void GuiMesh::initGL()
|
|
{
|
|
const GLchar *vertex_shader =
|
|
"#version 330\n"
|
|
"uniform mat4 ProjMtx;\n"
|
|
"layout(location = 0)in vec2 Position;\n"
|
|
"layout(location = 1)in vec2 UV;\n"
|
|
"layout(location = 2)in vec4 Color;\n"
|
|
"out vec2 Frag_UV;\n"
|
|
"out vec4 Frag_Color;\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
" Frag_UV = UV;\n"
|
|
" Frag_Color = Color;\n"
|
|
" gl_Position = ProjMtx * vec4(Position.xy,0,1);\n"
|
|
"}\n";
|
|
|
|
const GLchar* fragment_shader =
|
|
"#version 330\n"
|
|
"uniform sampler2D Texture;\n"
|
|
"in vec2 Frag_UV;\n"
|
|
"in vec4 Frag_Color;\n"
|
|
"out vec4 Out_Color;\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
" Out_Color = Frag_Color * texture( Texture, Frag_UV.st);\n"
|
|
"}\n";
|
|
|
|
ShaderHandle = glCreateProgram();
|
|
VertHandle = glCreateShader(GL_VERTEX_SHADER);
|
|
FragHandle = glCreateShader(GL_FRAGMENT_SHADER);
|
|
glShaderSource(VertHandle, 1, &vertex_shader, 0);
|
|
glShaderSource(FragHandle, 1, &fragment_shader, 0);
|
|
glCompileShader(VertHandle);
|
|
glCompileShader(FragHandle);
|
|
glAttachShader(ShaderHandle, VertHandle);
|
|
glAttachShader(ShaderHandle, FragHandle);
|
|
glLinkProgram(ShaderHandle);
|
|
|
|
AttribLocationTex = glGetUniformLocation(ShaderHandle, "Texture");
|
|
AttribLocationProjMtx = glGetUniformLocation(ShaderHandle, "ProjMtx");
|
|
|
|
glGenBuffers(1, &VboHandle);
|
|
glGenBuffers(1, &ElementsHandle);
|
|
|
|
glGenVertexArrays(1, &VaoHandle);
|
|
glBindVertexArray(VaoHandle);
|
|
glBindBuffer(GL_ARRAY_BUFFER, VboHandle);
|
|
|
|
|
|
#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT))
|
|
glEnableVertexAttribArray(0);
|
|
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos));
|
|
|
|
glEnableVertexAttribArray(1);
|
|
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv));
|
|
|
|
glEnableVertexAttribArray(2);
|
|
glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col));
|
|
#undef OFFSETOF
|
|
|
|
// Build texture atlas
|
|
ImGuiIO& io = ImGui::GetIO();
|
|
unsigned char* pixels;
|
|
int width, height;
|
|
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory.
|
|
|
|
// Upload texture to graphics system
|
|
glGenTextures(1, &FontTexture);
|
|
glBindTexture(GL_TEXTURE_2D, FontTexture);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
|
|
|
// Store our identifier
|
|
io.Fonts->TexID = (void *)(intptr_t)FontTexture;
|
|
}
|
|
|
|
void GuiMesh::drawGL()
|
|
{
|
|
ImGui::Render();
|
|
|
|
ImDrawData* draw_data = ImGui::GetDrawData();
|
|
|
|
ImGuiIO& io = ImGui::GetIO();
|
|
int fb_width = (int)(io.DisplaySize.x * io.DisplayFramebufferScale.x);
|
|
int fb_height = (int)(io.DisplaySize.y * io.DisplayFramebufferScale.y);
|
|
if (fb_width == 0 || fb_height == 0)
|
|
return;
|
|
draw_data->ScaleClipRects(io.DisplayFramebufferScale);
|
|
|
|
// Setup render state: scissor enabled
|
|
glEnable(GL_SCISSOR_TEST);
|
|
glActiveTexture(GL_TEXTURE0);
|
|
|
|
// Setup viewport, orthographic projection matrix
|
|
glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height);
|
|
const float ortho_projection[4][4] =
|
|
{
|
|
{ 2.0f/io.DisplaySize.x, 0.0f, 0.0f, 0.0f },
|
|
{ 0.0f, 2.0f/-io.DisplaySize.y, 0.0f, 0.0f },
|
|
{ 0.0f, 0.0f, -1.0f, 0.0f },
|
|
{-1.0f, 1.0f, 0.0f, 1.0f },
|
|
};
|
|
glUseProgram(ShaderHandle);
|
|
glUniform1i(AttribLocationTex, 0);
|
|
glUniformMatrix4fv(AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]);
|
|
glBindVertexArray(VaoHandle);
|
|
|
|
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
|
{
|
|
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
|
const ImDrawIdx* idx_buffer_offset = 0;
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, VboHandle);
|
|
glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)cmd_list->VtxBuffer.Size * sizeof(ImDrawVert), (const GLvoid*)cmd_list->VtxBuffer.Data, GL_STREAM_DRAW);
|
|
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ElementsHandle);
|
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx), (const GLvoid*)cmd_list->IdxBuffer.Data, GL_STREAM_DRAW);
|
|
|
|
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
|
|
{
|
|
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
|
|
if (pcmd->UserCallback)
|
|
{
|
|
pcmd->UserCallback(cmd_list, pcmd);
|
|
}
|
|
else
|
|
{
|
|
glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId);
|
|
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, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer_offset);
|
|
}
|
|
idx_buffer_offset += pcmd->ElemCount;
|
|
}
|
|
}
|
|
|
|
glDisable(GL_SCISSOR_TEST);
|
|
}
|
|
|
|
void GuiMesh::resizeGL(int w, int h)
|
|
{
|
|
ImGuiIO& io = ImGui::GetIO();
|
|
width = w;
|
|
height = h;
|
|
io.DisplaySize = ImVec2(w, h);
|
|
}
|
|
|
|
void GuiMesh::destroyGL()
|
|
{
|
|
if (VaoHandle) glDeleteVertexArrays(1, &VaoHandle);
|
|
if (VboHandle) glDeleteBuffers(1, &VboHandle);
|
|
if (ElementsHandle) glDeleteBuffers(1, &ElementsHandle);
|
|
VaoHandle = VboHandle = ElementsHandle = 0;
|
|
|
|
if (ShaderHandle && VertHandle) glDetachShader(ShaderHandle, VertHandle);
|
|
if (VertHandle) glDeleteShader(VertHandle);
|
|
VertHandle = 0;
|
|
|
|
if (ShaderHandle && FragHandle) glDetachShader(ShaderHandle, FragHandle);
|
|
if (FragHandle) glDeleteShader(FragHandle);
|
|
FragHandle = 0;
|
|
|
|
if (ShaderHandle) glDeleteProgram(ShaderHandle);
|
|
ShaderHandle = 0;
|
|
|
|
if (FontTexture)
|
|
{
|
|
glDeleteTextures(1, &FontTexture);
|
|
ImGui::GetIO().Fonts->TexID = 0;
|
|
FontTexture = 0;
|
|
}
|
|
}
|