diff --git a/CMakeLists.txt b/CMakeLists.txt index 07a53be..c235773 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,6 @@ set(CMAKE_CXX_STANDARD 20) set (GLAD_SOURCE_DIR _ThirdParty/glad/src) set (GLAD_INCLUDE_DIR _ThirdParty/glad/include) - include_directories(${GLAD_INCLUDE_DIR}) set (GLFW_BUILD_EXAMPLES OFF) @@ -20,7 +19,9 @@ add_subdirectory(_ThirdParty/assimp) add_subdirectory(glm) -add_executable(${PROJECT_NAME} src/main.cpp ${GLAD_SOURCE_DIR}/gl.c +add_executable(${PROJECT_NAME} + src/main.cpp + ${GLAD_SOURCE_DIR}/gl.c src/Mesh.cpp src/Mesh.h src/Model.cpp @@ -31,8 +32,11 @@ add_executable(${PROJECT_NAME} src/main.cpp ${GLAD_SOURCE_DIR}/gl.c src/ModelLoader.h src/ShaderProgram.cpp src/ShaderProgram.h - src/Texture.cpp - src/Texture.h) + src/Texture.h + src/TextureLoader.cpp + src/TextureLoader.h + src/ShaderLoader.cpp + src/ShaderLoader.h) target_link_libraries(${PROJECT_NAME} glfw spdlog assimp glm) target_include_directories(${PROJECT_NAME} PRIVATE ${ASSIMP_INCLUDE_INSTALL_DIR}) diff --git a/resources/cube.obj b/resources/cube.obj new file mode 100644 index 0000000..8b0a83f --- /dev/null +++ b/resources/cube.obj @@ -0,0 +1,46 @@ +# Blender v2.76 (sub 0) OBJ File: '' +# www.blender.org +mtllib cube.mtl +o Cube +v 1.000000 -1.000000 -1.000000 +v 1.000000 -1.000000 1.000000 +v -1.000000 -1.000000 1.000000 +v -1.000000 -1.000000 -1.000000 +v 1.000000 1.000000 -0.999999 +v 0.999999 1.000000 1.000001 +v -1.000000 1.000000 1.000000 +v -1.000000 1.000000 -1.000000 +vt 1.000000 0.333333 +vt 1.000000 0.666667 +vt 0.666667 0.666667 +vt 0.666667 0.333333 +vt 0.666667 0.000000 +vt 0.000000 0.333333 +vt 0.000000 0.000000 +vt 0.333333 0.000000 +vt 0.333333 1.000000 +vt 0.000000 1.000000 +vt 0.000000 0.666667 +vt 0.333333 0.333333 +vt 0.333333 0.666667 +vt 1.000000 0.000000 +vn 0.000000 -1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 1.000000 0.000000 0.000000 +vn -0.000000 0.000000 1.000000 +vn -1.000000 -0.000000 -0.000000 +vn 0.000000 0.000000 -1.000000 +usemtl Material +s off +f 2/1/1 3/2/1 4/3/1 +f 8/1/2 7/4/2 6/5/2 +f 5/6/3 6/7/3 2/8/3 +f 6/8/4 7/5/4 3/4/4 +f 3/9/5 7/10/5 8/11/5 +f 1/12/6 4/13/6 8/11/6 +f 1/4/1 2/1/1 4/3/1 +f 5/14/2 8/1/2 6/5/2 +f 1/12/3 5/6/3 2/8/3 +f 2/12/4 6/8/4 3/4/4 +f 4/13/5 3/9/5 8/11/5 +f 5/6/6 1/12/6 8/11/6 diff --git a/src/Material.h b/src/Material.h index 8351d83..6278cc7 100644 --- a/src/Material.h +++ b/src/Material.h @@ -5,23 +5,27 @@ #ifndef B_ENGINE_MATERIAL_H #define B_ENGINE_MATERIAL_H +#include + #include #include "Texture.h" typedef struct { - alignas(16) glm::vec3 ambient; - alignas(16) glm::vec3 diffuse; - alignas(16) glm::vec3 specular; + glm::vec3 ambient; + glm::vec3 diffuse; + glm::vec3 specular; float shininess; } PhongProperties; typedef struct { - Texture* diffuse; - Texture* specular; - Texture* normal; + std::shared_ptr diffuse; + std::shared_ptr specular; + std::shared_ptr normal; + + std::string name; PhongProperties phong; } Material; diff --git a/src/Mesh.cpp b/src/Mesh.cpp index fcf695c..5d6a149 100644 --- a/src/Mesh.cpp +++ b/src/Mesh.cpp @@ -6,6 +6,7 @@ Mesh::Mesh(const std::vector &positions, const std::vector &uvs, const std::vector &normals, const std::vector &indices) { vao = 0; ebo = 0; + numIndices = indices.size(); glGenVertexArrays(1, &vao); glBindVertexArray(vao); @@ -27,6 +28,7 @@ Mesh::Mesh(const std::vector &positions, const std::vector &uvs, c glBindBuffer(GL_ARRAY_BUFFER, normalVbo); glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(float), normals.data(), GL_STATIC_DRAW); + glGenBuffers(1, &ebo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), indices.data(), GL_STATIC_DRAW); diff --git a/src/Mesh.h b/src/Mesh.h index ff5ec40..b3e594d 100644 --- a/src/Mesh.h +++ b/src/Mesh.h @@ -20,6 +20,7 @@ public: GLuint vao; GLuint ebo; + unsigned int numIndices; }; #endif //B_ENGINE_MESH_H \ No newline at end of file diff --git a/src/Model.h b/src/Model.h index 2d3defb..f7e151e 100644 --- a/src/Model.h +++ b/src/Model.h @@ -5,7 +5,7 @@ #ifndef B_ENGINE_MODEL_H #define B_ENGINE_MODEL_H -#include +#include #include #include "Mesh.h" @@ -14,9 +14,10 @@ class Model { public: - int numMeshes; - std::vector meshes; - std::vector materials; + static std::shared_ptr load_from_file(std::string_view filename); + + std::vector> meshes; + std::vector> materials; }; #endif //B_ENGINE_MODEL_H \ No newline at end of file diff --git a/src/ModelLoader.cpp b/src/ModelLoader.cpp index d12b12b..6547d6f 100644 --- a/src/ModelLoader.cpp +++ b/src/ModelLoader.cpp @@ -10,16 +10,23 @@ #include #include +#include + +std::unordered_map> ModelLoader::models; + void process_ai_node(aiNode* node, const aiScene* scene, Model* model); -Mesh process_ai_mesh(aiMesh* aiMesh, const aiScene* scene, Model* model); + +Mesh process_ai_mesh(const aiMesh* aiMesh); +Material process_ai_material(aiMaterial* mat); std::shared_ptr ModelLoader::load_from_file(std::string_view _path) { Assimp::Importer importer; const aiScene* scene = importer.ReadFile(_path.data(), - /*aiProcess_CalcTangentSpace |*/ - aiProcess_Triangulate | aiProcess_GenSmoothNormals | aiProcess_FlipUVs | + aiProcess_Triangulate | + aiProcess_GenSmoothNormals | + aiProcess_FlipUVs | aiProcess_CalcTangentSpace); if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) @@ -30,21 +37,29 @@ std::shared_ptr ModelLoader::load_from_file(std::string_view _path) auto model = std::make_shared(); - process_ai_node(scene->mRootNode, scene, model.get()); + model->materials.resize(scene->mNumMaterials); + for (unsigned int i = 0; i < scene->mNumMaterials; i++) { + aiMaterial* mat = scene->mMaterials[i]; + model->materials[i] = std::make_shared(process_ai_material(mat)); + } + + model->meshes.resize(scene->mNumMeshes); + for (unsigned int i = 0; i < scene->mNumMeshes; i++) { + aiMesh* mesh = scene->mMeshes[i]; + model->meshes[i] = std::make_shared(process_ai_mesh(mesh)); + } return model; } void process_ai_node(aiNode* node, const aiScene* scene, Model* model) { - for (unsigned int i = 0; i < node->mNumMeshes; i++) - { - aiMesh* mesh = scene->mMeshes[node->mMeshes[i]]; - model->meshes.push_back(process_ai_mesh(mesh, scene, model)); + for (unsigned int i = 0; i < node->mNumChildren; i++) { + } } -Mesh process_ai_mesh(aiMesh* aiMesh, const aiScene* scene, Model* model) +Mesh process_ai_mesh(const aiMesh* aiMesh) { auto positions = std::vector(aiMesh->mNumVertices * 3); auto uvs = std::vector(aiMesh->mNumVertices * 2); @@ -92,3 +107,48 @@ Mesh process_ai_mesh(aiMesh* aiMesh, const aiScene* scene, Model* model) return {positions, uvs, normals, indices}; } + +Material process_ai_material(aiMaterial *mat) { + aiString matName; + aiReturn ret = mat->Get(AI_MATKEY_NAME, matName); + if (ret != AI_SUCCESS) { + spdlog::error("Could not find material name"); + } + + aiColor3D ambientColor {0.f, 0.f, 0.f}; + ret = mat->Get(AI_MATKEY_COLOR_DIFFUSE, ambientColor); + if (ret != AI_SUCCESS) { + spdlog::error("Could not find ambient color for material: {}", matName.C_Str()); + ambientColor = {.3f, .3f, .3f}; + } + + aiColor3D diffuseColor {1.f, 1.f, 1.f}; + ret = mat->Get(AI_MATKEY_COLOR_DIFFUSE, diffuseColor); + if (ret != AI_SUCCESS) { + spdlog::error("Could not find diffuse color for material: {}", matName.C_Str()); + diffuseColor = {1.f, 1.f, 1.f}; + } + + aiColor3D specularColor {1.f, 1.f, 1.f}; + ret = mat->Get(AI_MATKEY_COLOR_SPECULAR, specularColor); + if (ret != AI_SUCCESS) { + spdlog::error("Could not find specular color for material: {}", matName.C_Str()); + specularColor = {1.f, 1.f, 1.f}; + } + + float shininess = 32.f; + ret = mat->Get(AI_MATKEY_SHININESS, shininess); + if (ret != AI_SUCCESS) { + spdlog::error("Could not find shininess for material: {}", matName.C_Str()); + shininess = 32.f; + } + + Material material; + material.name = matName.C_Str(); + material.phong.ambient = glm::vec3{ambientColor.r, ambientColor.g, ambientColor.b}; + material.phong.diffuse = glm::vec3{diffuseColor.r, diffuseColor.g, diffuseColor.b}; + material.phong.specular = glm::vec3{specularColor.r, specularColor.g, specularColor.b}; + material.phong.shininess = shininess; + + return material; +} diff --git a/src/ModelLoader.h b/src/ModelLoader.h index c423319..1cec3e6 100644 --- a/src/ModelLoader.h +++ b/src/ModelLoader.h @@ -13,6 +13,8 @@ class ModelLoader { public: + static std::unordered_map> models; + static std::shared_ptr load_from_file(std::string_view _path); }; diff --git a/src/ShaderLoader.cpp b/src/ShaderLoader.cpp new file mode 100644 index 0000000..088a13b --- /dev/null +++ b/src/ShaderLoader.cpp @@ -0,0 +1,97 @@ +// +// Created by slinky on 5/1/26. +// + +#include "ShaderLoader.h" + +#include "glad/gl.h" + +#include +#include + +#include + +void log_shader_compile_errors(GLuint shader, std::string_view shaderType); +void log_program_compile_errors(GLuint program); + +std::unordered_map> ShaderLoader::shaders; + +std::shared_ptr ShaderLoader::load(std::string_view vertexPath, std::string_view fragmentPath) +{ + std::string vertexSource; + std::string fragmentSource; + + std::ifstream vertexFile {}; + std::ifstream fragmentFile {}; + + try + { + vertexFile.open(vertexPath.data()); + fragmentFile.open(fragmentPath.data()); + + std::stringstream vertexSourceStream {}; + vertexSourceStream << vertexFile.rdbuf(); + vertexSource = vertexSourceStream.str(); + + std::stringstream fragmentSourceStream {}; + fragmentSourceStream << fragmentFile.rdbuf(); + fragmentSource = fragmentSourceStream.str(); + + vertexFile.close(); + fragmentFile.close(); + } catch (std::ifstream::failure& e) { + spdlog::error("Failed to load shader program {}, {}: {}", vertexPath, fragmentPath, std::string(e.what()).c_str()); + return nullptr; + } + + unsigned int vertex; + unsigned int fragment; + + vertex = glCreateShader(GL_VERTEX_SHADER); + const char* vertex_str = vertexSource.data(); + glShaderSource(vertex, 1, &vertex_str, NULL); + glCompileShader(vertex); + log_shader_compile_errors(vertex, "vertex"); + + fragment = glCreateShader(GL_FRAGMENT_SHADER); + const char* frag_str = fragmentSource.data(); + glShaderSource(fragment, 1, &frag_str, NULL); + glCompileShader(fragment); + log_shader_compile_errors(fragment, "fragment"); + + int shaderId = glCreateProgram(); + + glAttachShader(shaderId, vertex); + glAttachShader(shaderId, fragment); + glLinkProgram(shaderId); + log_program_compile_errors(shaderId); + + glDeleteShader(vertex); + glDeleteShader(fragment); + + return std::make_shared(ShaderProgram(shaderId)); +} + +void log_shader_compile_errors(GLuint shader, std::string_view shaderType) +{ + GLint success; + GLchar infoLog[1024]; + glGetShaderiv(shader, GL_COMPILE_STATUS, &success); + if (!success) + { + glGetShaderInfoLog(shader, 1024, NULL, infoLog); + spdlog::error("Failed to compile {} shader: {}", shaderType, infoLog); + } +} + +void log_program_compile_errors(GLuint program) +{ + GLint success; + GLchar infoLog[1024]; + glGetProgramiv(program, GL_COMPILE_STATUS, &success); + if (!success) + { + glGetShaderInfoLog(program, 1024, NULL, infoLog); + spdlog::error("Failed to compile program: {}", infoLog); + } +} \ No newline at end of file diff --git a/src/ShaderLoader.h b/src/ShaderLoader.h new file mode 100644 index 0000000..1169568 --- /dev/null +++ b/src/ShaderLoader.h @@ -0,0 +1,19 @@ +// +// Created by slinky on 5/1/26. +// + +#ifndef B_ENGINE_SHADERLOADER_H +#define B_ENGINE_SHADERLOADER_H + +#include + +#include "ShaderProgram.h" + +class ShaderLoader { +public: + static std::unordered_map> shaders; + + static std::shared_ptr load(std::string_view vertexPath, std::string_view fragmentPath); +}; + +#endif //B_ENGINE_SHADERLOADER_H \ No newline at end of file diff --git a/src/ShaderProgram.cpp b/src/ShaderProgram.cpp index 31b1863..a96c0a6 100644 --- a/src/ShaderProgram.cpp +++ b/src/ShaderProgram.cpp @@ -5,68 +5,8 @@ #include "ShaderProgram.h" #include -#include -#include -#include "glad/gl.h" -#include "spdlog/spdlog.h" - -void log_shader_compile_errors(GLuint shader, std::string_view shaderType); -void log_program_compile_errors(GLuint program); - -std::shared_ptr ShaderProgram::load(std::string_view vertexPath, std::string_view fragmentPath) -{ - std::string vertexSource; - std::string fragmentSource; - - std::ifstream vertexFile {}; - std::ifstream fragmentFile {}; - - try - { - std::stringstream ss; - vertexFile.open(vertexPath.data()); - fragmentFile.open(fragmentPath.data()); - - ss << vertexFile.rdbuf(); - vertexSource = ss.str(); - ss.clear(); - ss << fragmentFile.rdbuf(); - fragmentSource = ss.str(); - - vertexFile.close(); - fragmentFile.close(); - } catch (std::ifstream::failure& e) { - spdlog::error("Failed to load shader program {}, {}: {}", vertexPath, fragmentPath, std::string(e.what()).c_str()); - return nullptr; - } - - unsigned int vertex; - unsigned int fragment; - - vertex = glCreateShader(GL_VERTEX_SHADER); - glShaderSource(vertex, 1, reinterpret_cast(vertexSource.data()), NULL); - glCompileShader(vertex); - log_shader_compile_errors(vertex, "vertex"); - - fragment = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(fragment, 1, reinterpret_cast(fragmentSource.data()), NULL); - glCompileShader(fragment); - log_shader_compile_errors(fragment, "fragment"); - - ShaderProgram program; - program.id = glCreateProgram(); - - glAttachShader(program.id, vertex); - glAttachShader(program.id, fragment); - glLinkProgram(program.id); - log_program_compile_errors(program.id); - - glDeleteShader(vertex); - glDeleteShader(fragment); - - return std::make_shared(program); -} +#include void ShaderProgram::bind() { @@ -80,49 +20,26 @@ void ShaderProgram::unbind() void ShaderProgram::setFloat(std::string_view name, float value) const { - + glUniform1f(glGetUniformLocation(id, name.data()), value); } -void ShaderProgram::setVec2(std::string_view name, const glm::vec2& value) const +void ShaderProgram::setInt(std::string_view name, int value) const { - + glUniform1i(glGetUniformLocation(id, name.data()), value); } void ShaderProgram::setVec3(std::string_view name, const glm::vec3& value) const { - + glUniform3fv(glGetUniformLocation(id, name.data()), 1, &value[0]); } void ShaderProgram::setVec4(std::string_view name, const glm::vec4& value) const { - + glUniform4fv(glGetUniformLocation(id, name.data()), 1, &value[0]); } void ShaderProgram::setMat4(std::string_view name, const glm::mat4& value) const { - + glUniformMatrix4fv(glGetUniformLocation(id, name.data()), 1, GL_FALSE, &value[0][0]); } -void log_shader_compile_errors(GLuint shader, std::string_view shaderType) -{ - GLint success; - GLchar infoLog[1024]; - glGetShaderiv(shader, GL_COMPILE_STATUS, &success); - if (!success) - { - glGetShaderInfoLog(shader, 1024, NULL, infoLog); - spdlog::error("Failed to compile {} shader: {}", shaderType, infoLog); - } -} - -void log_program_compile_errors(GLuint program) -{ - GLint success; - GLchar infoLog[1024]; - glGetProgramiv(program, GL_COMPILE_STATUS, &success); - if (!success) - { - glGetShaderInfoLog(program, 1024, NULL, infoLog); - spdlog::error("Failed to compile program: {}", infoLog); - } -} \ No newline at end of file diff --git a/src/ShaderProgram.h b/src/ShaderProgram.h index f1b2359..ec3e337 100644 --- a/src/ShaderProgram.h +++ b/src/ShaderProgram.h @@ -15,13 +15,13 @@ class ShaderProgram { public: - static std::shared_ptr load(std::string_view vertexPath, std::string_view fragmentPath); + explicit ShaderProgram(GLuint id) : id(id) {} void bind(); - void unbind(); + static void unbind(); void setFloat(std::string_view name, float value) const; - void setVec2(std::string_view name, const glm::vec2 &value) const; + void setInt(std::string_view name, int value) const; void setVec3(std::string_view name, const glm::vec3 &value) const; void setMat4(std::string_view name, const glm::mat4 &mat) const; void setVec4(std::string_view name, const glm::vec4 &value) const; diff --git a/src/Texture.h b/src/Texture.h index 93bc80d..5aee1f6 100644 --- a/src/Texture.h +++ b/src/Texture.h @@ -5,21 +5,21 @@ #ifndef B_ENGINE_TEXTURE_H #define B_ENGINE_TEXTURE_H -#include #include #include +#include + class Texture { public: - static std::shared_ptr load_from_file(std::string_view filePath); - static std::shared_ptr load_from_data(unsigned char* data, int width, int height, int channels); + Texture(unsigned int id, std::string_view filePath, int width, int height, int channels) + : id(id), filePath(filePath), width(width), height(height), channels(channels) {} - Texture() = default; - ~Texture(); + ~Texture() { glDeleteTextures(1, &id); } - void bind(unsigned int slot); - void unbind(); + void bind() const {glBindTexture(GL_TEXTURE_2D, id);} + static void unbind() {glBindTexture(GL_TEXTURE_2D, 0);} [[nodiscard]] int get_width() const { return width; } [[nodiscard]] int get_height() const { return height; } diff --git a/src/Texture.cpp b/src/TextureLoader.cpp similarity index 58% rename from src/Texture.cpp rename to src/TextureLoader.cpp index a569690..a3233eb 100644 --- a/src/Texture.cpp +++ b/src/TextureLoader.cpp @@ -1,8 +1,8 @@ // -// Created by lbmas on 4/29/2026. +// Created by slinky on 5/1/26. // -#include "Texture.h" +#include "TextureLoader.h" #include "stb_image.h" @@ -10,7 +10,9 @@ #include "glad/gl.h" -std::shared_ptr Texture::load_from_file(std::string_view filePath) +std::unordered_map> TextureLoader::textures; + +std::shared_ptr TextureLoader::load_from_file(std::string_view filePath) { int width, height, channels; unsigned char *data = stbi_load(filePath.data(), &width, &height, &channels, 0); @@ -20,9 +22,9 @@ std::shared_ptr Texture::load_from_file(std::string_view filePath) return nullptr; } - Texture texture = {}; - glGenTextures(1, &texture.id); - glBindTexture(GL_TEXTURE_2D, texture.id); + unsigned int textureID = 0; + glGenTextures(1, &textureID); + glBindTexture(GL_TEXTURE_2D, textureID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -36,18 +38,14 @@ std::shared_ptr Texture::load_from_file(std::string_view filePath) stbi_image_free(data); - texture.filePath = filePath; - texture.width = width; - texture.height = height; - texture.channels = channels; - return std::make_shared(texture); + return std::make_shared(textureID, filePath, width, height, channels); } -std::shared_ptr Texture::load_from_data(unsigned char* data, int width, int height, int channels) +std::shared_ptr TextureLoader::load_from_data(unsigned char* data, int width, int height, int channels) { - Texture texture = {}; - glGenTextures(1, &texture.id); - glBindTexture(GL_TEXTURE_2D, texture.id); + unsigned int textureID = 0; + glGenTextures(1, &textureID); + glBindTexture(GL_TEXTURE_2D, textureID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -59,24 +57,5 @@ std::shared_ptr Texture::load_from_data(unsigned char* data, int width, glTexImage2D(GL_TEXTURE_2D, 0, (GLint)format, width, height, 0, format, GL_UNSIGNED_BYTE, data); glGenerateMipmap(GL_TEXTURE_2D); - texture.filePath = ""; - texture.width = width; - texture.height = height; - texture.channels = channels; - return std::make_shared(texture); -} - -Texture::~Texture() -{ - glDeleteTextures(1, &id); -} - -void Texture::bind(unsigned int slot) -{ - -} - -void Texture::unbind() -{ - -} + return std::make_shared(textureID, "memory", width, height, channels); +} \ No newline at end of file diff --git a/src/TextureLoader.h b/src/TextureLoader.h new file mode 100644 index 0000000..0737e30 --- /dev/null +++ b/src/TextureLoader.h @@ -0,0 +1,21 @@ +// +// Created by slinky on 5/1/26. +// + +#ifndef B_ENGINE_TEXTURELOADER_H +#define B_ENGINE_TEXTURELOADER_H + +#include +#include + +#include "Texture.h" + +class TextureLoader { +public: + static std::unordered_map> textures; + + static std::shared_ptr load_from_file(std::string_view filePath); + static std::shared_ptr load_from_data(unsigned char* data, int width, int height, int channels); +}; + +#endif //B_ENGINE_TEXTURELOADER_H \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index d13ad30..74e557b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -11,8 +11,11 @@ #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; @@ -25,10 +28,6 @@ auto cameraPosition = glm::vec3{0, 0, 0}; auto view = glm::mat4{0}; auto projection = glm::mat4{0}; -std::unordered_map> gModels = {}; -std::unordered_map> gTextures = {}; -std::unordered_map> gShaders = {}; - 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); @@ -37,6 +36,7 @@ void init_glfw(); void create_main_window(); void load_gl(); void init_camera(); +void loop(); std::shared_ptr load_model(std::string_view _path); @@ -55,26 +55,21 @@ int main() { // create a default texture unsigned char defaultDiffuseData[4] = {static_cast(255), 255, 255, 255}; - gTextures["default_diffuse"] = Texture::load_from_data(reinterpret_cast(&defaultDiffuseData), 1, 1, 4); + 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}; - gTextures["default_specular"] = Texture::load_from_data(reinterpret_cast(&defaultSpecularData), 1, 1, 4); + TextureLoader::textures["default_specular"] = TextureLoader::load_from_data(reinterpret_cast(&defaultSpecularData), 1, 1, 4); - gShaders["phong_shader"] = ShaderProgram::load("./resources/standard.frag", "./resources/standard.vert"); - if (gShaders["phong_shader"] == nullptr) + ShaderLoader::shaders["phong_shader"] = ShaderLoader::load("./resources/standard.vert", "./resources/standard.frag"); + if (ShaderLoader::shaders["phong_shader"] == nullptr) { std::exit(1); } - while (!glfwWindowShouldClose(gWindow)) { - glfwPollEvents(); + ModelLoader::models["cube"] = ModelLoader::load_from_file("./resources/cube.obj"); - glClearColor(0.2f, 0.3f, 0.3f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT); - - glfwSwapBuffers(gWindow); - } + loop(); glfwDestroyWindow(gWindow); glfwTerminate(); @@ -153,7 +148,56 @@ void init_camera() projection = glm::perspective(glm::radians(75.f), aspectRatio, 0.1f, 100.0f); } -std::shared_ptr load_model(std::string_view _path) -{ - return std::make_shared(); +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); + } } \ No newline at end of file