Untitled
unknown
c_cpp
a year ago
9.4 kB
4
Indexable
#include "imgui.h"
#include "backends/imgui_impl_glfw.h"
#include "backends/imgui_impl_opengl3.h"
#include "glad/glad.h"
#include "GLFW/glfw3.h"
#include "glm/ext.hpp"
#include "config.h"
#include <array>
#include <fstream>
#include <iostream>
#include <optional>
cg::Window _window;
cg::Camera _camera;
constexpr auto window_width = 1280;
constexpr auto window_height = 720;
constexpr auto window_title = "OpenGL";
constexpr auto gl_major = 4;
constexpr auto gl_minor = 6;
constexpr auto glsl_version = "#version 460";
constexpr auto clear_color = glm::vec4(0.45f, 0.55f, 0.60f, 0.90f);
static unsigned int gl_print_error(void)
{
unsigned int error = glGetError();
if (error == 0)
std::cout << "No GL errors." << std::endl;
else
std::cerr << "GL Error: " << error << std::endl;
return error;
}
static void glfw_error_callback(int error, const char* description)
{
std::cerr << "GLFW Error: " << error << " " << description << std::endl;
}
static void key_callback(GLFWwindow* window,
int key,
int scancode,
int action,
int mode)
{
switch (key)
{
case GLFW_KEY_ESCAPE:
glfwSetWindowShouldClose(window, true);
break;
default:
break;
}
}
GLFWwindow* init_window(void)
{
glfwSetErrorCallback(glfw_error_callback);
if (glfwInit() == GLFW_FALSE)
return nullptr;
/*
* Required for Apple.
*/
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, gl_major);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, gl_minor);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
/*
* Create the graphics context and make it current.
*/
GLFWwindow* const window = glfwCreateWindow(window_width,
window_height,
window_title,
nullptr,
nullptr);
if (window == nullptr)
return nullptr;
glfwMakeContextCurrent(window);
/*
* Set event callbacks.
*/
glfwSetKeyCallback(window, key_callback);
/*
* Load OpenGL with GLAD.
* Crashes if GL functions are called without this.
*/
gladLoadGL();
return window;
}
static void init_ImGui(GLFWwindow* window)
{
/*
* ImGui context.
*/
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
/*
* ImGui style.
*/
ImGui::StyleColorsDark();
ImGui_ImplGlfw_InitForOpenGL(window, true);
ImGui_ImplOpenGL3_Init(glsl_version);
}
static void reset_viewport(GLFWwindow* window)
{
int display_w = 0;
int display_h = 0;
glfwGetFramebufferSize(window, &display_w, &display_h);
glViewport(0, 0, display_w, display_h);
}
static void clear(void)
{
glClearColor(clear_color.x * clear_color.w,
clear_color.y * clear_color.w,
clear_color.z * clear_color.w,
clear_color.w);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
static void render_ImGui(void)
{
bool show_demo_window = true;
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
if (show_demo_window == true)
{
ImGui::ShowDemoWindow(&show_demo_window);
}
ImGui::Render();
}
static void display_ImGui(void)
{
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
}
static void cleanup_ImGui(void)
{
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext();
}
static void cleanup_window(GLFWwindow* window)
{
glfwDestroyWindow(window);
glfwTerminate();
}
static std::optional<std::string> read_shader(const std::string& path)
{
std::string result;
std::ifstream in(path, std::ios::in | std::ios::binary);
if (in.good() == false)
return std::nullopt;
in.seekg(0, std::ios::end);
size_t size = in.tellg();
if (size == -1)
return std::nullopt;
result.resize(size);
in.seekg(0, std::ios::beg);
in.read(&result[0], size);
return result;
}
/*
* Copy the shader source string here just in case.
* c_str will point to garbage if a string reference goes out of scope.
*/
static unsigned int compile_shader(const std::string shader_source,
unsigned int type)
{
unsigned int shader = glCreateShader(type);
const char* c_str = shader_source.c_str();
glShaderSource(shader, 1, &c_str, nullptr);
glCompileShader(shader);
/*
* Compile error checking.
*/
int is_compiled = 0;
glGetShaderiv(shader, GL_COMPILE_STATUS, &is_compiled);
if (is_compiled == 0)
{
std::string log;
int length = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
log.resize(length);
glGetShaderInfoLog(shader, length, nullptr, &log[0]);
std::string type_s = type == GL_VERTEX_SHADER ? "vertex" : "fragment";
std::cerr << "Failed to compile " << type_s << " shader." << std::endl;
std::cerr << log << std::endl;
glDeleteShader(shader);
return 0;
}
return shader;
}
static unsigned int create_shader(const std::string& vertex_source,
const std::string& fragment_source)
{
unsigned int program = glCreateProgram();
unsigned int vertex_shader = compile_shader(vertex_source, GL_VERTEX_SHADER);
if (vertex_shader == 0)
return 0;
unsigned int fragment_shader = compile_shader(fragment_source, GL_FRAGMENT_SHADER);
if (fragment_shader == 0)
return 0;
glAttachShader(program, vertex_shader);
glAttachShader(program, fragment_shader);
glLinkProgram(program);
glValidateProgram(program);
glDeleteShader(vertex_shader);
glDeleteShader(fragment_shader);
glDetachShader(program, vertex_shader);
glDetachShader(program, fragment_shader);
return program;
}
static void init(void)
{
/*
* Enable z-buffer.
*/
glEnable(GL_DEPTH_TEST);
std::array vertices
{
-0.5f,-0.5f,-0.5f,
-0.5f,-0.5f, 0.5f,
-0.5f, 0.5f, 0.5f,
0.5f, 0.5f,-0.5f,
-0.5f,-0.5f,-0.5f,
-0.5f, 0.5f,-0.5f,
0.5f,-0.5f, 0.5f,
-0.5f,-0.5f,-0.5f,
0.5f,-0.5f,-0.5f,
0.5f, 0.5f,-0.5f,
0.5f,-0.5f,-0.5f,
-0.5f,-0.5f,-0.5f,
-0.5f,-0.5f,-0.5f,
-0.5f, 0.5f, 0.5f,
-0.5f, 0.5f,-0.5f,
0.5f,-0.5f, 0.5f,
-0.5f,-0.5f, 0.5f,
-0.5f,-0.5f,-0.5f,
-0.5f, 0.5f, 0.5f,
-0.5f,-0.5f, 0.5f,
0.5f,-0.5f, 0.5f,
0.5f, 0.5f, 0.5f,
0.5f,-0.5f,-0.5f,
0.5f, 0.5f,-0.5f,
0.5f,-0.5f,-0.5f,
0.5f, 0.5f, 0.5f,
0.5f,-0.5f, 0.5f,
0.5f, 0.5f, 0.5f,
0.5f, 0.5f,-0.5f,
-0.5f, 0.5f,-0.5f,
0.5f, 0.5f, 0.5f,
-0.5f, 0.5f,-0.5f,
-0.5f, 0.5f, 0.5f,
0.5f, 0.5f, 0.5f,
-0.5f, 0.5f, 0.5f,
0.5f,-0.5f, 0.5f
};
std::array triangle
{
-2.0f, 0.0f, 0.0f,
0.0f, 2.0f, 0.0f,
2.0f, 0.0f, 0.0f,
-2.0f, 0.0f, 0.0f,
-2.0f, -2.0f, 0.0f,
0.0f, -2.0f, 0.0f,
-2.0f, 0.0f, 0.0f,
0.0f, -2.0f, 0.0f,
2.0f, 0.0f, 0.0f
};
/*
* Load draw data to the GPU memory.
*/
unsigned int vbo = 0;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(triangle), &triangle[0], GL_STATIC_DRAW);
/*
* Specify the format of the data.
*/
unsigned int vao = 0;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glVertexAttribPointer(0, 3, GL_FLOAT, false, sizeof(float) * 3, 0);
glEnableVertexAttribArray(0);
std::cout << "Data init check:" << std::endl;
if (gl_print_error() != 0)
return;
/*
* Setup shaders.
*/
const auto vertex_source = read_shader("resources/shaders/vertex.glsl");
const auto fragment_source = read_shader("resources/shaders/fragment.glsl");
if (vertex_source.has_value() == false ||
fragment_source.has_value() == false)
{
std::cerr << "Failed to read shaders." << std::endl;
return;
}
unsigned int program = create_shader(vertex_source.value(),
fragment_source.value());
if (program == 0)
{
std::cerr << "Failed to compile shaders." << std::endl;
return;
}
glUseProgram(program);
/*
* Projection.
* FOV, Aspect, Z_NEAR, Z_FAR
*/
glm::mat4 projection = glm::perspective(45.0f, 4.0f / 3.0f, 1.0f, 100.0f);
/*
* View.
* Eye not in the center so we are outside the object.
* Center at 0.
* Up = y direction.
*/
glm::vec3 eye = glm::vec3(0.0f, 0.0f, 5.0f);
glm::vec3 center = glm::vec3(0.0f);
glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f);
glm::mat4 view = glm::lookAt(eye, center, up);
/*
* Model.
* Order of operations is important.
*/
glm::mat4 model = glm::mat4(1.0f);
model = glm::scale(model, glm::vec3(1.0f, 1.0f, 1.0f));
model = glm::rotate(model, 0.0f, glm::vec3(0.0f, 1.0f, 0.0f));
model = glm::translate(model, glm::vec3(0.0f, 0.5f, 0.0f));
/*
* Set PVM matrix.
*/
glm::mat4 pvm = projection * view * model;
unsigned int u_pvm = glGetUniformLocation(program, "u_pvm");
glUniformMatrix4fv(u_pvm, 1, GL_TRUE, glm::value_ptr(pvm));
}
static void render(void)
{
glDrawArrays(GL_TRIANGLES, 0, 9);
}
static void run(void)
{
GLFWwindow* window = init_window();
if (window == nullptr)
std::exit(1);
init_ImGui(window);
init();
/*
* Main loop.
* Runs every frame.
*/
while (glfwWindowShouldClose(window) == 0)
{
glfwPollEvents();
render_ImGui();
reset_viewport(window);
clear();
render();
display_ImGui();
glfwSwapBuffers(window);
}
/*
* Cleanup.
*/
cleanup_ImGui();
cleanup_window(window);
}
int main(void)
{
/*
* Keep main function brief.
*/
run();
}Editor is loading...
Leave a Comment