#include "glad/gl.h" #include "GLFW/glfw3.h" #include "spdlog/spdlog.h" #include "glm/glm.hpp" #include "glm/ext/matrix_clip_space.hpp" #include "glm/ext/matrix_transform.hpp" #define STB_IMAGE_IMPLEMENTATION #include "stb_image.h" #include "Model.h" #include "ModelLoader.h" #include "ShaderLoader.h" #include "ShaderProgram.h" #include "Texture.h" #include "TextureLoader.h" GLFWwindow* gWindow = nullptr; int gWindowWidth = 800; int gWindowHeight = 600; int glVersionMajor = 0; int glVersionMinor = 0; auto cameraPosition = glm::vec3{0, 0, 0}; auto view = glm::mat4{0}; auto projection = glm::mat4{0}; void glfw_error_callback(int error, const char* description); void glfw_key_callback(GLFWwindow* window, int key, int scancode, int action, int mods); void glfw_framebuffer_size_callback(GLFWwindow* window, int width, int height); void init_glfw(); void create_main_window(); void load_gl(); void init_camera(); void loop(); std::shared_ptr load_model(std::string_view _path); int main() { spdlog::info("b_engine start"); init_glfw(); create_main_window(); load_gl(); stbi_set_flip_vertically_on_load(true); init_camera(); // create a default texture unsigned char defaultDiffuseData[4] = {static_cast(255), 255, 255, 255}; TextureLoader::textures["default_diffuse"] = TextureLoader::load_from_data(reinterpret_cast(&defaultDiffuseData), 1, 1, 4); // create a default specular map unsigned char defaultSpecularData[4] = {static_cast(128), 128, 128, 255}; TextureLoader::textures["default_specular"] = TextureLoader::load_from_data(reinterpret_cast(&defaultSpecularData), 1, 1, 4); ShaderLoader::shaders["phong_shader"] = ShaderLoader::load("./resources/standard.vert", "./resources/standard.frag"); if (ShaderLoader::shaders["phong_shader"] == nullptr) { std::exit(1); } ModelLoader::models["cube"] = ModelLoader::load_from_file("./resources/cube.obj"); loop(); glfwDestroyWindow(gWindow); glfwTerminate(); return 0; } void glfw_error_callback(int error, const char* description) { spdlog::error("glfw error: {}", description); } void glfw_key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) { if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) { glfwSetWindowShouldClose(window, GL_TRUE); } } void glfw_framebuffer_size_callback(GLFWwindow *window, int width, int height) { glViewport(0, 0, width, height); } void init_glfw() { if (!glfwInit()) { spdlog::error("could not initialize glfw"); std::exit(1); } glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwSetErrorCallback(glfw_error_callback); } void create_main_window() { gWindow = glfwCreateWindow(gWindowWidth, gWindowHeight, "b_engine v0.0.1", nullptr, nullptr); if (!gWindow) { spdlog::error("failed to create glfw window"); std::exit(1); } glfwMakeContextCurrent(gWindow); glfwSetKeyCallback(gWindow, glfw_key_callback); glfwSetFramebufferSizeCallback(gWindow, glfw_framebuffer_size_callback); } void load_gl() { int version = gladLoadGL(glfwGetProcAddress); glVersionMajor = GLAD_VERSION_MAJOR(version); glVersionMinor = GLAD_VERSION_MINOR(version); spdlog::info("gl version {}.{}", glVersionMajor, glVersionMinor); if (gWindow) { int fbWidth, fbHeight; glfwGetFramebufferSize(gWindow, &fbWidth, &fbHeight); glViewport(0, 0, fbWidth, fbHeight); } } void init_camera() { cameraPosition = glm::vec3{0, 5, 5}; auto cameraTarget = glm::vec3{0, 0, 0}; auto behind = glm::normalize(cameraPosition - cameraTarget); auto right = glm::normalize(glm::cross(glm::vec3{0, 1, 0}, behind)); auto up = glm::normalize(glm::cross(right, behind)); view = glm::lookAt(cameraPosition, cameraTarget, up); float aspectRatio = static_cast(gWindowWidth) / static_cast(gWindowHeight); projection = glm::perspective(glm::radians(75.f), aspectRatio, 0.1f, 100.0f); } void loop() { Texture* defaultDiffuse = TextureLoader::textures["default_diffuse"].get(); Texture* defaultSpecular = TextureLoader::textures["default_specular"].get(); while (!glfwWindowShouldClose(gWindow)) { auto modelMatrix = glm::identity(); glfwPollEvents(); glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); ShaderProgram* shader = ShaderLoader::shaders["phong_shader"].get(); Model* model = ModelLoader::models["cube"].get(); if (shader && model) { Material* mat = model->materials[0].get(); shader->bind(); shader->setMat4("projection", projection); shader->setMat4("view", view); shader->setMat4("model", modelMatrix); shader->setVec3("viewPosition", cameraPosition); if (mat) { shader->setVec3("phongAmbient", mat->phong.ambient); shader->setVec3("phongDiffuse", mat->phong.diffuse); shader->setVec3("phongSpecular", mat->phong.specular); shader->setFloat("phongShininess", mat->phong.shininess); } shader->setVec3("lightPosition", glm::vec3(5.f, 5.f, 5.f)); shader->setVec3("lightAmbient", glm::vec3{.1f, .1f, .1f}); shader->setVec3("lightDiffuse", glm::vec3{.8f, .8f, .8f}); shader->setVec3("lightSpecular", glm::vec3{1.f, 1.f, 1.f}); glActiveTexture(GL_TEXTURE0); defaultDiffuse->bind(); shader->setInt("diffuse1", 0); glActiveTexture(GL_TEXTURE1); defaultSpecular->bind(); shader->setInt("specular1", 1); for (auto mesh: model->meshes) { glBindVertexArray(mesh.get()->vao); glDrawElements(GL_TRIANGLES, mesh->numIndices, GL_UNSIGNED_INT, 0); } } glfwSwapBuffers(gWindow); } }