#include "../include/RenderBackend/OpenGL/opengl.hpp" #include "../include/RenderBackend/OpenGL/Shader.hpp" #include "../include/RenderBackend/OpenGL/ShaderProgram.hpp" #include "../include/RenderBackend/OpenGL/DeviceMemory.hpp" #include "../include/RenderBackend/OpenGL/DeviceFrame.hpp" #include "../include/Triangle.hpp" #include #include // TODO: Creating buffers etc should be somehow created/drawn using the window object, since they are associated with the window // opengl context using namespace amalgine; using namespace std; static void glfwErrorHandler(int errorCode, const char *errorDescription); static void initGlfw(); static void initGlew(); static GLFWwindow *createWindow(); static std::unique_ptr load_shader_from_file(const char *filepath, Shader::Type shader_type); static std::unique_ptr build_shader_program_from_shaders(const std::vector &shaders); int main() { initGlfw(); glfwSetErrorCallback(glfwErrorHandler); GLFWwindow *window = createWindow(); int window_width = 1; int window_height = 1; glfwGetWindowSize(window, &window_width, &window_height); DeviceFrame frame; std::array cpuTriangle = { Triangle3D( Vertex3D(0.0f, 0.0f, 0.0f), Vertex3D(1.0f, 0.0f, 0.0f), Vertex3D(0.0f, 1.0f, 0.0f) ), Triangle3D( Vertex3D(1.0f, 0.0f, 0.0f), Vertex3D(1.0f, 1.0f, 0.0f), Vertex3D(0.0f, 1.0f, 0.0f) ), }; DataView cpuTriangles(cpuTriangle.data(), cpuTriangle.size()); DeviceMemory *gpuTriangle = frame.alloc(); gpuTriangle->copy(cpuTriangles, DeviceMemory::StorageType::STATIC); std::unique_ptr vertex_shader = load_shader_from_file("shaders/vertex.vert", Shader::Type::VERTEX); std::unique_ptr pixel_shader = load_shader_from_file("shaders/fragment.frag", Shader::Type::PIXEL); std::unique_ptr shader_program = build_shader_program_from_shaders({ vertex_shader.get(), pixel_shader.get() }); shader_program->set_vertex_input("position", *gpuTriangle); Result proj_uniform = shader_program->get_uniform_by_name("proj"); glm::mat4 proj = glm::perspective(glm::radians(75.0f), (float)window_width / (float)window_height, 0.2f, 1000.0f); proj_uniform->set(proj); Result triangle_color_uniform = shader_program->get_uniform_by_name("triangle_color"); triangle_color_uniform->set(vec3f{ 1.0f, 0.0f, 0.0f }); Result view_uniform = shader_program->get_uniform_by_name("view"); Result model_uniform = shader_program->get_uniform_by_name("model"); glm::vec3 character_pos(0.0f, 3.0f, 3.0f); auto t_start = std::chrono::high_resolution_clock::now(); while(!glfwWindowShouldClose(window)) { glfwPollEvents(); if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) glfwSetWindowShouldClose(window, GL_TRUE); auto t_now = std::chrono::high_resolution_clock::now(); float time_delta = std::chrono::duration_cast>(t_now - t_start).count(); t_start = t_now; if(glfwGetKey(window, GLFW_KEY_W)) character_pos.y -= time_delta; if(glfwGetKey(window, GLFW_KEY_S)) character_pos.y += time_delta; glm::mat4 view = glm::lookAt( character_pos, character_pos - glm::vec3(0.0f, 3.0f, 3.0f), glm::vec3(0.0f, 0.0f, 1.0f) ); view_uniform->set(view); glm::mat4 model = glm::mat4(1.0f); model = glm::rotate( model, 0.0f, glm::vec3(0.0f, 0.0f, 1.0f) ); model_uniform->set(model); // Set color for clearing glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Do the actual screen clearing, using the color set using glClearColor glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); frame.draw(shader_program.get()); glfwSwapBuffers(window); } glfwTerminate(); return 0; } void glfwErrorHandler(int errorCode, const char *errorDescription) { printf("GLFW error code: %d, description: %s\n", errorCode, errorDescription); } void initGlfw() { if(!glfwInit()) { fprintf(stderr, "Failed to initialize GLFW\n"); exit(-1); } glfwWindowHint(GLFW_SAMPLES, 4); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5); glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); } void initGlew() { glewExperimental = true; if(glewInit() != GLEW_OK) { fprintf(stderr, "Failed to initialize GLEW\n"); glfwTerminate(); exit(-1); } } GLFWwindow* createWindow() { GLFWwindow *window = glfwCreateWindow(1280, 720, "Amalgine", nullptr, nullptr); if(!window) { fprintf(stderr, "Failed to open GLFW window\n"); glfwTerminate(); exit(10); } glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_FALSE); glfwMakeContextCurrent(window); glfwSwapInterval(0); initGlew(); return window; } static int file_read_all(const char *filepath, std::string &result) { FILE *file = fopen(filepath, "rb"); if(!file) { perror("file_read_all"); return errno; } fseek(file, 0, SEEK_END); size_t file_size = ftell(file); fseek(file, 0, SEEK_SET); result.resize(file_size); fread(&result[0], 1, result.size(), file); fclose(file); return 0; } std::unique_ptr load_shader_from_file(const char *filepath, Shader::Type shader_type) { std::string file_content; if(file_read_all(filepath, file_content) != 0) exit(13); Result> vertex_shader_result = Shader::compile(shader_type, file_content.data(), file_content.size()); if(!vertex_shader_result) { fprintf(stderr, "Failed to compile shader, error: %s\n", vertex_shader_result.getErrorMsg().c_str()); exit(12); } return std::move(vertex_shader_result.unwrap()); } std::unique_ptr build_shader_program_from_shaders(const std::vector &shaders) { Result> shader_program_result = ShaderProgram::build(shaders); if(!shader_program_result) { fprintf(stderr, "Failed to link shaders, error: %s\n", shader_program_result.getErrorMsg().c_str()); exit(13); } return std::move(shader_program_result.unwrap()); }