SparrowRenderer/src/guimesh.cpp

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