parade/src/Application.cpp

673 lines
21 KiB
C++

#include "imgui.h"
#include "backends/imgui_impl_glfw.h"
#include "backends/imgui_impl_opengl3.h"
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <Camera.h>
#include <Objects.h>
struct Light
{
glm::vec4 position = glm::vec4(0.f, 0.f, 0.f, 1.f);
glm::vec4 diffuse_color = glm::vec4(0.8f, 0.8f, 0.8f, 1.f);
glm::vec4 specular_color = glm::vec4(1.f, 1.f, 1.f, 1.f);
glm::vec4 ambient_color = glm::vec4(.2f, 0.2f, 0.2f, 1.f);
};
float canvas[] = {
-1.0f, 1.0f, 0.0f,
-1.0f, -1.0f, 0.0f,
1.0f, 1.0f, 0.0f,
1.0f, -1.0f, 0.0f
};
unsigned int VBO;
unsigned int VAO;
namespace window
{
int size[] = { 1920, 1080};
}
namespace scene
{
Camera camera;
unsigned int shader = -1;
float angle = glm::pi<float>() / 2.0f;
float yaw = camera.yaw(); // Initial yaw for position (-1, 1, 1)
float pitch = camera.pitch(); // Initial pitch for position (-1, 1, 1)
std::vector<Primitive> primitiveData;
std::vector<Light> lightData;
glm::vec3 Lp = { 0.f, 1.f, 0.f }; // Light position
glm::vec3 La = { 124.0 / 255.0, 114.0 / 255.0, 160.0 / 255.0 }; // Light ambient color
glm::vec3 Ld = { 1.f, 1.f, 1.f }; // Light diffuse color
glm::vec3 Ls = { 1.f, 1.f, 1.f }; // Light specular color
float smoothing = 0.0f;
unsigned int l_vbo = -1;
unsigned int p_vbo = -1;
int object = 0;
}
namespace mouse
{
bool altPressed = false;
double xlast;
double ylast;
double xoffset;
double yoffset;
float sensitivity = 0.1f;
}
//Create a NULL-terminated string by reading the provided file
static char* ReadShaderSource(const char* shaderFile)
{
std::ifstream ifs(shaderFile, std::ios::in | std::ios::binary | std::ios::ate);
if (ifs.is_open())
{
unsigned int filesize = static_cast<unsigned int>(ifs.tellg());
ifs.seekg(0, std::ios::beg);
char* bytes = new char[filesize + 1];
memset(bytes, 0, filesize + 1);
ifs.read(bytes, filesize);
ifs.close();
return bytes;
}
return NULL;
}
void AddPrimitive(unsigned int primType)
{
Primitive newPrim(primType);
for (int i = 0; i < scene::primitiveData.size(); i++)
{
if (primType == scene::primitiveData[i].type) newPrim.dummy++;
}
scene::primitiveData.push_back(newPrim);
}
void RemovePrimitive(int *element)
{
//scene::primitiveData.erase(scene::primitiveData.begin() + *element);
//element--;
}
void AddLight()
{
Light newLight;
scene::lightData.push_back(newLight);
}
void InitPrimitive()
{
glGenBuffers(1, &scene::p_vbo);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, scene::p_vbo);
glBufferData(GL_SHADER_STORAGE_BUFFER, scene::primitiveData.size() * sizeof(Primitive), scene::primitiveData.data(), GL_DYNAMIC_DRAW);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, scene::p_vbo);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
}
void InitLights()
{
glGenBuffers(1, &scene::l_vbo);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, scene::l_vbo);
glBufferData(GL_SHADER_STORAGE_BUFFER, scene::lightData.size() * sizeof(Light), scene::lightData.data(), GL_DYNAMIC_DRAW);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, scene::l_vbo);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
}
void UpdatePrimitive()
{
glBindBuffer(GL_SHADER_STORAGE_BUFFER, scene::p_vbo);
glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, scene::primitiveData.size() * sizeof(Primitive), scene::primitiveData.data());
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
}
static unsigned int CompileShader(unsigned int type, const std::string& source)
{
unsigned int id = glCreateShader(type);
const char* src = source.c_str();
glShaderSource(id, 1, &src, nullptr);
glCompileShader(id);
int result;
glGetShaderiv(id, GL_COMPILE_STATUS, &result);
if (result == GL_FALSE)
{
int length;
glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length);
char* message = (char*)_malloca(length * sizeof(char));
glGetShaderInfoLog(id, length, &length, message);
std::cout << "Failed to compile " << (type == GL_VERTEX_SHADER ? "vertex" : "fragment") << " shader!" << std::endl;
std::cout << message << std::endl;
glDeleteShader(id);
return 0;
}
return id;
}
static unsigned int CreateShader(const std::string& vertexShaderFile, const std::string& fragmentShaderFile)
{
std::string vertexShader = ReadShaderSource(vertexShaderFile.c_str());
std::string fragmentShader = ReadShaderSource(fragmentShaderFile.c_str());
GLuint program = glCreateProgram();
unsigned int vs = CompileShader(GL_VERTEX_SHADER, vertexShader);
unsigned int fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);
glAttachShader(program, vs);
glAttachShader(program, fs);
glLinkProgram(program);
glValidateProgram(program);
glDeleteShader(vs);
glDeleteShader(fs);
return program;
}
void InitCanvas()
{
glBindAttribLocation(scene::shader, 0, "pos_attrib");
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(canvas), canvas, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, 0, 0, 0);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
std::string GetName(Primitive prim)
{
std::string name;
switch (prim.type)
{
case 0x00:
{
name = "Sphere";
break;
}
case 0x01:
{
name = "Torus";
break;
}
case 0x02:
{
name = "Cone";
break;
}
case 0x03:
{
name = "Cube";
break;
}
case 0x04:
{
name = "Rounded_Cube";
break;
}
default:
{
name = "Primitive";
break;
}
}
if (prim.dummy > 0) name += "_" + std::to_string(prim.dummy);
return name;
}
void PrimGUI(unsigned int obj)
{
ImGui::SliderFloat3("Position", glm::value_ptr(scene::primitiveData[obj].position), -2.0f, 2.0f);
switch (scene::primitiveData[obj].type)
{
case 0x00:
{
ImGui::SliderFloat("Radius", &scene::primitiveData[obj].radius, 0.f, 5.0f);
break;
}
case 0x01:
{
ImGui::SliderFloat("Outer Radius", &scene::primitiveData[obj].outer_radius, 0.f, 5.0f);
ImGui::SliderFloat("Inner Radius", &scene::primitiveData[obj].inner_radius, 0.f, 5.0f);
break;
}
case 0x02:
{
break;
}
case 0x03:
{
ImGui::SliderFloat("Size", &scene::primitiveData[obj].size, 0.f, 5.0f);
break;
}
case 0x04:
{
ImGui::SliderFloat("Size", &scene::primitiveData[obj].size, 0.f, 5.0f);
ImGui::SliderFloat("Radius", &scene::primitiveData[obj].radius, 0.f, 2.0f);
break;
}
//case 0xFF:
//{
// ImGui::SliderFloat("Size", &scene::primitiveData[obj].size, 0.f, 5.0f);
// ImGui::SliderFloat("Radius", &scene::primitiveData[obj].radius, 0.f, 2.0f);
// break;
//}
default:
{
break;
}
}
ImGui::Separator();
ImGui::ColorEdit3("Diffuse", glm::value_ptr(scene::primitiveData[obj].diffuse_color));
ImGui::ColorEdit3("Specular", glm::value_ptr(scene::primitiveData[obj].specular_color));
ImGui::ColorEdit3("Ambient", glm::value_ptr(scene::primitiveData[obj].ambient_color));
ImGui::SliderInt("Specular Exponent", &scene::primitiveData[obj].specular_exponent, 1, 500);
}
//Draw the ImGui user interface
void draw_gui(GLFWwindow* window)
{
//Begin ImGui Frame
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGuiIO& io = ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
ImGui::NewFrame();
static ImGuiDockNodeFlags dockspace_flags = ImGuiDockNodeFlags_PassthruCentralNode;
// We are using the ImGuiWindowFlags_NoDocking flag to make the parent window not dockable into,
// because it would be confusing to have two docking targets within each others.
ImGuiWindowFlags window_flags = ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking;
const ImGuiViewport* viewport = ImGui::GetMainViewport();
ImGui::SetNextWindowPos(viewport->WorkPos);
ImGui::SetNextWindowSize(viewport->WorkSize);
ImGui::SetNextWindowViewport(viewport->ID);
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove;
window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus;
window_flags |= ImGuiWindowFlags_NoBackground;
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
ImGui::Begin("DockSpace Demo", nullptr, window_flags);
ImGui::PopStyleVar(3);
// Submit the DockSpace
if (io.ConfigFlags & ImGuiConfigFlags_DockingEnable)
{
ImGuiID dockspace_id = ImGui::GetID("MyDockSpace");
ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), dockspace_flags);
}
if (ImGui::BeginMenuBar())
{
if (ImGui::BeginMenu("Options"))
{
ImGui::Text("Nothing Here Yet, Check Back Later!");
ImGui::EndMenu();
}
ImGui::EndMenuBar();
}
ImGui::End();
//Draw Gui
ImGui::Begin("Object Controls");
if (ImGui::Button("Quit"))
{
glfwSetWindowShouldClose(window, GLFW_TRUE);
}
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
ImGui::SliderFloat("Smoothing", &scene::smoothing, 0.0f, 1.0f);
for (int i = 0; i < scene::primitiveData.size(); i++)
{
std::string checkbox = "Subtract " + GetName(scene::primitiveData[i]);
ImGui::RadioButton(GetName(scene::primitiveData[i]).c_str(), &scene::object, i); ImGui::SameLine();
if (ImGui::Button(checkbox.c_str()))
{
scene::primitiveData[i].subtract = 1 - scene::primitiveData[i].subtract;
}
//if (ImGui::Button("Delete Object")) RemovePrimitive(&scene::object);
//scene::object--;
}
ImGui::Separator();
PrimGUI(scene::object);
ImGui::End();
ImGui::Begin("Primitives");
if (ImGui::Button("Sphere", ImVec2(ImGui::GetWindowSize().y * 0.5f, ImGui::GetWindowSize().y * 0.5f)))
{
AddPrimitive(P_SPHERE);
scene::object = scene::primitiveData.size() - 1;
InitPrimitive();
}ImGui::SameLine();
if (ImGui::Button("Torus", ImVec2(ImGui::GetWindowSize().y * 0.5f, ImGui::GetWindowSize().y * 0.5f)))
{
AddPrimitive(P_TORUS);
scene::object = scene::primitiveData.size() - 1;
InitPrimitive();
}ImGui::SameLine();
if (ImGui::Button("Cube", ImVec2(ImGui::GetWindowSize().y * 0.5f, ImGui::GetWindowSize().y * 0.5f)))
{
AddPrimitive(P_CUBE);
scene::object = scene::primitiveData.size() - 1;
InitPrimitive();
}ImGui::SameLine();
if (ImGui::Button("Rounded Cube", ImVec2(ImGui::GetWindowSize().y * 0.5f, ImGui::GetWindowSize().y * 0.5f)))
{
AddPrimitive(P_ROUNDED_CUBE);
scene::object = scene::primitiveData.size() - 1;
InitPrimitive();
}/*ImGui::SameLine();
if (ImGui::Button("Point Light", ImVec2(ImGui::GetWindowSize().y * 0.5f, ImGui::GetWindowSize().y * 0.5f)))
{
AddLight();
scene::object = scene::primitiveData.size() - 1;
InitPrimitive();
}*/
ImGui::End();
//End ImGui Frame
ImGui::Render();
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
}
void idle()
{
glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
}
void display(GLFWwindow* window)
{
glClearColor(1.0f, 0.f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glm::mat4 M = glm::rotate(scene::angle, glm::vec3(0.0f, 0.0f, 1.0f));
glm::mat4 V = glm::lookAt(scene::camera.position(), scene::camera.front(), scene::camera.up());
glm::mat4 P = glm::perspective(glm::pi<float>() / 2.0f, (float)window::size[0] / (float)window::size[1], 0.1f, 100.0f);
glViewport(0, 0, window::size[0], window::size[1]);
int P_loc = glGetUniformLocation(scene::shader, "P");
if (P_loc != -1)
{
glUniformMatrix4fv(P_loc, 1, false, glm::value_ptr(P));
}
int V_loc = glGetUniformLocation(scene::shader, "V");
if (V_loc != -1)
{
glUniformMatrix4fv(V_loc, 1, false, glm::value_ptr(V));
}
int M_loc = glGetUniformLocation(scene::shader, "M");
if (M_loc != -1)
{
glUniformMatrix4fv(M_loc, 1, false, glm::value_ptr(M));
}
int cam_pos_loc = glGetUniformLocation(scene::shader, "cam_pos");
if (cam_pos_loc != -1)
{
glUniform3fv(cam_pos_loc, 1, glm::value_ptr(scene::camera.position()));
}
int window_width_loc = glGetUniformLocation(scene::shader, "window_width");
if (window_width_loc != -1)
{
glUniform1i(window_width_loc, window::size[0]);
}
int window_height_loc = glGetUniformLocation(scene::shader, "window_height");
if (window_height_loc != -1)
{
glUniform1i(window_height_loc, window::size[1]);
}
int smoothing_loc = glGetUniformLocation(scene::shader, "smoothing");
if (smoothing_loc != -1)
{
glUniform1f(smoothing_loc, scene::smoothing);
}
UpdatePrimitive();
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLE_STRIP, 0, sizeof(canvas) / 3);
draw_gui(window);
glfwSwapBuffers(window);
}
void keyboard_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (action == GLFW_PRESS)
{
switch (key)
{
case GLFW_KEY_ESCAPE:
glfwSetWindowShouldClose(window, GLFW_TRUE);
break;
case GLFW_KEY_LEFT_ALT:
mouse::altPressed = true;
break;
case GLFW_KEY_RIGHT_ALT:
mouse::altPressed = true;
break;
}
}
if (action == GLFW_RELEASE)
{
switch (key)
{
case GLFW_KEY_LEFT_ALT:
mouse::altPressed = false;
break;
case GLFW_KEY_RIGHT_ALT:
mouse::altPressed = false;
break;
}
}
}
void orbit_camera()
{
scene::yaw += (float)mouse::xoffset;
scene::pitch += (float)mouse::yoffset;
scene::camera.orbit(scene::yaw, scene::pitch);
}
void pan_camera()
{
float translateSensitivity = 0.02f;
scene::camera.pan((float)mouse::xoffset * -translateSensitivity, (float)mouse::yoffset * translateSensitivity);
}
void zoom_camera()
{
scene::camera.zoom((float)mouse::yoffset * 0.01f);
}
void cursor_offset(double xcurrent, double ycurrent)
{
mouse::xoffset = xcurrent - mouse::xlast;
mouse::yoffset = ycurrent - mouse::ylast;
mouse::xlast = xcurrent;
mouse::ylast = ycurrent;
mouse::xoffset *= mouse::sensitivity;
mouse::yoffset *= mouse::sensitivity;
}
//This function gets called when the mouse moves over the window.
void cursor_pos_callback(GLFWwindow* window, double x, double y)
{
if (mouse::altPressed)
{
cursor_offset(x, y);
if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS) orbit_camera();
if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_MIDDLE) == GLFW_PRESS) pan_camera();
if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS) zoom_camera();
}
}
//This function gets called when a mouse button is pressed.
void mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
{
//std::cout << "button : " << button << ", action: " << action << ", mods: " << mods << std::endl;
if (action == GLFW_PRESS) glfwGetCursorPos(window, &mouse::xlast, &mouse::ylast);
}
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
{
scene::camera.zoom((float)yoffset * -0.1f);
}
void window_size_callback(GLFWwindow* window, int width, int height)
{
window::size[0] = width;
window::size[1] = height;
}
void init()
{
glewInit();
scene::shader = CreateShader("shaders/parade_vs.glsl", "shaders/parade_fs.glsl");
glUseProgram(scene::shader);
AddPrimitive(P_ROUNDED_CUBE);
Light l;
l.position = glm::vec4{ -sqrt(3.f) / 3.f, sqrt(3.f) / 3.f, -sqrt(3.f) / 3.f, 1.f };
l.diffuse_color = glm::vec4{ 142.f / 255.f, 202.f / 255.f, 230.f / 255.f, 1.f };
scene::lightData.push_back(l);
Light l2;
l2.position = glm::vec4{ sqrt(3.f) / 3.f, sqrt(3.f) / 3.f, sqrt(3.f) / 3.f, 1.f};
l2.diffuse_color = glm::vec4(255.f / 255.f, 183.f / 255.f, 3.f / 255.f, 1.f);
scene::lightData.push_back(l2);
Light l3;
l3.position = glm::vec4{ ((double)rand() / (RAND_MAX)) * 2 - 1, ((double)rand() / (RAND_MAX)) * 2 - 1, ((double)rand() / (RAND_MAX)) * 2 - 1, 1.f };
l3.diffuse_color = glm::vec4{ ((double)rand() / (RAND_MAX)), ((double)rand() / (RAND_MAX)), ((double)rand() / (RAND_MAX)), 1.f };
scene::lightData.push_back(l3);
Light l4;
l4.position = glm::vec4{ ((double)rand() / (RAND_MAX)) * 2 - 1, ((double)rand() / (RAND_MAX)) * 2 - 1, ((double)rand() / (RAND_MAX)) * 2 - 1, 1.f };
l4.diffuse_color = glm::vec4{ ((double)rand() / (RAND_MAX)), ((double)rand() / (RAND_MAX)), ((double)rand() / (RAND_MAX)), 1.f };
scene::lightData.push_back(l4);
Light l5;
l5.position = glm::vec4{ ((double)rand() / (RAND_MAX)) * 2 - 1, ((double)rand() / (RAND_MAX)) * 2 - 1, ((double)rand() / (RAND_MAX)) * 2 - 1, 1.f };
l5.diffuse_color = glm::vec4{ ((double)rand() / (RAND_MAX)), ((double)rand() / (RAND_MAX)), ((double)rand() / (RAND_MAX)), 1.f };
scene::lightData.push_back(l5);
Light l6;
l6.position = glm::vec4{ ((double)rand() / (RAND_MAX)) * 2 - 1, ((double)rand() / (RAND_MAX)) * 2 - 1, ((double)rand() / (RAND_MAX)) * 2 - 1, 1.f };
l6.diffuse_color = glm::vec4{ ((double)rand() / (RAND_MAX)), ((double)rand() / (RAND_MAX)), ((double)rand() / (RAND_MAX)), 1.f };
scene::lightData.push_back(l6);
Light l7;
l7.position = glm::vec4{ ((double)rand() / (RAND_MAX)) * 2 - 1, ((double)rand() / (RAND_MAX)) * 2 - 1, ((double)rand() / (RAND_MAX)) * 2 - 1, 1.f };
l7.diffuse_color = glm::vec4{ ((double)rand() / (RAND_MAX)), ((double)rand() / (RAND_MAX)), ((double)rand() / (RAND_MAX)), 1.f };
scene::lightData.push_back(l7);
Light l8;
l8.position = glm::vec4{ ((double)rand() / (RAND_MAX)) * 2 - 1, ((double)rand() / (RAND_MAX)) * 2 - 1, ((double)rand() / (RAND_MAX)) * 2 - 1, 1.f };
l8.diffuse_color = glm::vec4{ ((double)rand() / (RAND_MAX)), ((double)rand() / (RAND_MAX)), ((double)rand() / (RAND_MAX)), 1.f };
scene::lightData.push_back(l8);
Light l9;
l9.position = glm::vec4{ ((double)rand() / (RAND_MAX)) * 2 - 1, ((double)rand() / (RAND_MAX)) * 2 - 1, ((double)rand() / (RAND_MAX)) * 2 - 1, 1.f };
l9.diffuse_color = glm::vec4{ ((double)rand() / (RAND_MAX)), ((double)rand() / (RAND_MAX)), ((double)rand() / (RAND_MAX)), 1.f };
scene::lightData.push_back(l9);
Light l10;
l10.position = glm::vec4{ ((double)rand() / (RAND_MAX)) * 2 - 1, ((double)rand() / (RAND_MAX)) * 2 - 1, ((double)rand() / (RAND_MAX)) * 2 - 1, 1.f };
l10.diffuse_color = glm::vec4{ ((double)rand() / (RAND_MAX)), ((double)rand() / (RAND_MAX)), ((double)rand() / (RAND_MAX)), 1.f };
scene::lightData.push_back(l10);
InitCanvas();
InitPrimitive();
InitLights();
}
int main()
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow* window = glfwCreateWindow(window::size[0], window::size[1], "Parade", nullptr, nullptr);
if (window == nullptr)
{
std::cout << "Failed to create window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwSetKeyCallback(window, keyboard_callback);
glfwSetCursorPosCallback(window, cursor_pos_callback);
glfwSetMouseButtonCallback(window, mouse_button_callback);
glfwSetScrollCallback(window, scroll_callback);
glfwSetWindowSizeCallback(window, window_size_callback);
init();
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGui_ImplGlfw_InitForOpenGL(window, true);
ImGui_ImplOpenGL3_Init("#version 150");
while (!glfwWindowShouldClose(window))
{
idle();
display(window);
glfwPollEvents();
}
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext();
return 0;
}