revamped resource system

This commit is contained in:
2026-05-02 21:24:21 -04:00
parent f9010eea81
commit 782bbcbadc
16 changed files with 374 additions and 177 deletions

View File

@@ -5,7 +5,6 @@ set(CMAKE_CXX_STANDARD 20)
set (GLAD_SOURCE_DIR _ThirdParty/glad/src) set (GLAD_SOURCE_DIR _ThirdParty/glad/src)
set (GLAD_INCLUDE_DIR _ThirdParty/glad/include) set (GLAD_INCLUDE_DIR _ThirdParty/glad/include)
include_directories(${GLAD_INCLUDE_DIR}) include_directories(${GLAD_INCLUDE_DIR})
set (GLFW_BUILD_EXAMPLES OFF) set (GLFW_BUILD_EXAMPLES OFF)
@@ -20,7 +19,9 @@ add_subdirectory(_ThirdParty/assimp)
add_subdirectory(glm) 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.cpp
src/Mesh.h src/Mesh.h
src/Model.cpp src/Model.cpp
@@ -31,8 +32,11 @@ add_executable(${PROJECT_NAME} src/main.cpp ${GLAD_SOURCE_DIR}/gl.c
src/ModelLoader.h src/ModelLoader.h
src/ShaderProgram.cpp src/ShaderProgram.cpp
src/ShaderProgram.h 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_link_libraries(${PROJECT_NAME} glfw spdlog assimp glm)
target_include_directories(${PROJECT_NAME} PRIVATE ${ASSIMP_INCLUDE_INSTALL_DIR}) target_include_directories(${PROJECT_NAME} PRIVATE ${ASSIMP_INCLUDE_INSTALL_DIR})

46
resources/cube.obj Normal file
View File

@@ -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

View File

@@ -5,23 +5,27 @@
#ifndef B_ENGINE_MATERIAL_H #ifndef B_ENGINE_MATERIAL_H
#define B_ENGINE_MATERIAL_H #define B_ENGINE_MATERIAL_H
#include <memory>
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include "Texture.h" #include "Texture.h"
typedef struct typedef struct
{ {
alignas(16) glm::vec3 ambient; glm::vec3 ambient;
alignas(16) glm::vec3 diffuse; glm::vec3 diffuse;
alignas(16) glm::vec3 specular; glm::vec3 specular;
float shininess; float shininess;
} PhongProperties; } PhongProperties;
typedef struct typedef struct
{ {
Texture* diffuse; std::shared_ptr<Texture> diffuse;
Texture* specular; std::shared_ptr<Texture> specular;
Texture* normal; std::shared_ptr<Texture> normal;
std::string name;
PhongProperties phong; PhongProperties phong;
} Material; } Material;

View File

@@ -6,6 +6,7 @@
Mesh::Mesh(const std::vector<float> &positions, const std::vector<float> &uvs, const std::vector<float> &normals, const std::vector<unsigned int> &indices) { Mesh::Mesh(const std::vector<float> &positions, const std::vector<float> &uvs, const std::vector<float> &normals, const std::vector<unsigned int> &indices) {
vao = 0; vao = 0;
ebo = 0; ebo = 0;
numIndices = indices.size();
glGenVertexArrays(1, &vao); glGenVertexArrays(1, &vao);
glBindVertexArray(vao); glBindVertexArray(vao);
@@ -27,6 +28,7 @@ Mesh::Mesh(const std::vector<float> &positions, const std::vector<float> &uvs, c
glBindBuffer(GL_ARRAY_BUFFER, normalVbo); glBindBuffer(GL_ARRAY_BUFFER, normalVbo);
glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(float), normals.data(), GL_STATIC_DRAW); glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(float), normals.data(), GL_STATIC_DRAW);
glGenBuffers(1, &ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), indices.data(), GL_STATIC_DRAW); glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), indices.data(), GL_STATIC_DRAW);

View File

@@ -20,6 +20,7 @@ public:
GLuint vao; GLuint vao;
GLuint ebo; GLuint ebo;
unsigned int numIndices;
}; };
#endif //B_ENGINE_MESH_H #endif //B_ENGINE_MESH_H

View File

@@ -5,7 +5,7 @@
#ifndef B_ENGINE_MODEL_H #ifndef B_ENGINE_MODEL_H
#define B_ENGINE_MODEL_H #define B_ENGINE_MODEL_H
#include <string> #include <string_view>
#include <vector> #include <vector>
#include "Mesh.h" #include "Mesh.h"
@@ -14,9 +14,10 @@
class Model class Model
{ {
public: public:
int numMeshes; static std::shared_ptr<Model> load_from_file(std::string_view filename);
std::vector<Mesh> meshes;
std::vector<Material> materials; std::vector<std::shared_ptr<Mesh>> meshes;
std::vector<std::shared_ptr<Material>> materials;
}; };
#endif //B_ENGINE_MODEL_H #endif //B_ENGINE_MODEL_H

View File

@@ -10,16 +10,23 @@
#include <assimp/postprocess.h> #include <assimp/postprocess.h>
#include <assimp/scene.h> #include <assimp/scene.h>
#include <cstring>
std::unordered_map<std::string, std::shared_ptr<Model>> ModelLoader::models;
void process_ai_node(aiNode* node, const aiScene* scene, Model* model); 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<Model> ModelLoader::load_from_file(std::string_view _path) std::shared_ptr<Model> ModelLoader::load_from_file(std::string_view _path)
{ {
Assimp::Importer importer; Assimp::Importer importer;
const aiScene* scene = importer.ReadFile(_path.data(), const aiScene* scene = importer.ReadFile(_path.data(),
/*aiProcess_CalcTangentSpace |*/ aiProcess_Triangulate |
aiProcess_Triangulate | aiProcess_GenSmoothNormals | aiProcess_FlipUVs | aiProcess_GenSmoothNormals |
aiProcess_FlipUVs |
aiProcess_CalcTangentSpace); aiProcess_CalcTangentSpace);
if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode)
@@ -30,21 +37,29 @@ std::shared_ptr<Model> ModelLoader::load_from_file(std::string_view _path)
auto model = std::make_shared<Model>(); auto model = std::make_shared<Model>();
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<Material>(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<Mesh>(process_ai_mesh(mesh));
}
return model; return model;
} }
void process_ai_node(aiNode* node, const aiScene* scene, Model* model) void process_ai_node(aiNode* node, const aiScene* scene, Model* model)
{ {
for (unsigned int i = 0; i < node->mNumMeshes; i++) for (unsigned int i = 0; i < node->mNumChildren; i++) {
{
aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
model->meshes.push_back(process_ai_mesh(mesh, scene, model));
} }
} }
Mesh process_ai_mesh(aiMesh* aiMesh, const aiScene* scene, Model* model) Mesh process_ai_mesh(const aiMesh* aiMesh)
{ {
auto positions = std::vector<float>(aiMesh->mNumVertices * 3); auto positions = std::vector<float>(aiMesh->mNumVertices * 3);
auto uvs = std::vector<float>(aiMesh->mNumVertices * 2); auto uvs = std::vector<float>(aiMesh->mNumVertices * 2);
@@ -92,3 +107,48 @@ Mesh process_ai_mesh(aiMesh* aiMesh, const aiScene* scene, Model* model)
return {positions, uvs, normals, indices}; 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;
}

View File

@@ -13,6 +13,8 @@
class ModelLoader class ModelLoader
{ {
public: public:
static std::unordered_map<std::string, std::shared_ptr<Model>> models;
static std::shared_ptr<Model> load_from_file(std::string_view _path); static std::shared_ptr<Model> load_from_file(std::string_view _path);
}; };

97
src/ShaderLoader.cpp Normal file
View File

@@ -0,0 +1,97 @@
//
// Created by slinky on 5/1/26.
//
#include "ShaderLoader.h"
#include "glad/gl.h"
#include <fstream>
#include <sstream>
#include <spdlog/spdlog.h>
void log_shader_compile_errors(GLuint shader, std::string_view shaderType);
void log_program_compile_errors(GLuint program);
std::unordered_map<std::string, std::shared_ptr<ShaderProgram>> ShaderLoader::shaders;
std::shared_ptr<ShaderProgram> 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>(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);
}
}

19
src/ShaderLoader.h Normal file
View File

@@ -0,0 +1,19 @@
//
// Created by slinky on 5/1/26.
//
#ifndef B_ENGINE_SHADERLOADER_H
#define B_ENGINE_SHADERLOADER_H
#include <memory>
#include "ShaderProgram.h"
class ShaderLoader {
public:
static std::unordered_map<std::string, std::shared_ptr<ShaderProgram>> shaders;
static std::shared_ptr<ShaderProgram> load(std::string_view vertexPath, std::string_view fragmentPath);
};
#endif //B_ENGINE_SHADERLOADER_H

View File

@@ -5,68 +5,8 @@
#include "ShaderProgram.h" #include "ShaderProgram.h"
#include <fstream> #include <fstream>
#include <string>
#include <sstream>
#include "glad/gl.h" #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> 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<const GLchar* const*>(vertexSource.data()), NULL);
glCompileShader(vertex);
log_shader_compile_errors(vertex, "vertex");
fragment = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment, 1, reinterpret_cast<const GLchar* const*>(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<ShaderProgram>(program);
}
void ShaderProgram::bind() void ShaderProgram::bind()
{ {
@@ -80,49 +20,26 @@ void ShaderProgram::unbind()
void ShaderProgram::setFloat(std::string_view name, float value) const 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 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 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 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);
}
}

View File

@@ -15,13 +15,13 @@
class ShaderProgram class ShaderProgram
{ {
public: public:
static std::shared_ptr<ShaderProgram> load(std::string_view vertexPath, std::string_view fragmentPath); explicit ShaderProgram(GLuint id) : id(id) {}
void bind(); void bind();
void unbind(); static void unbind();
void setFloat(std::string_view name, float value) const; 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 setVec3(std::string_view name, const glm::vec3 &value) const;
void setMat4(std::string_view name, const glm::mat4 &mat) const; void setMat4(std::string_view name, const glm::mat4 &mat) const;
void setVec4(std::string_view name, const glm::vec4 &value) const; void setVec4(std::string_view name, const glm::vec4 &value) const;

View File

@@ -5,21 +5,21 @@
#ifndef B_ENGINE_TEXTURE_H #ifndef B_ENGINE_TEXTURE_H
#define B_ENGINE_TEXTURE_H #define B_ENGINE_TEXTURE_H
#include <memory>
#include <string_view> #include <string_view>
#include <string> #include <string>
#include <glad/gl.h>
class Texture class Texture
{ {
public: public:
static std::shared_ptr<Texture> load_from_file(std::string_view filePath); Texture(unsigned int id, std::string_view filePath, int width, int height, int channels)
static std::shared_ptr<Texture> load_from_data(unsigned char* data, int width, int height, int channels); : id(id), filePath(filePath), width(width), height(height), channels(channels) {}
Texture() = default; ~Texture() { glDeleteTextures(1, &id); }
~Texture();
void bind(unsigned int slot); void bind() const {glBindTexture(GL_TEXTURE_2D, id);}
void unbind(); static void unbind() {glBindTexture(GL_TEXTURE_2D, 0);}
[[nodiscard]] int get_width() const { return width; } [[nodiscard]] int get_width() const { return width; }
[[nodiscard]] int get_height() const { return height; } [[nodiscard]] int get_height() const { return height; }

View File

@@ -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" #include "stb_image.h"
@@ -10,7 +10,9 @@
#include "glad/gl.h" #include "glad/gl.h"
std::shared_ptr<Texture> Texture::load_from_file(std::string_view filePath) std::unordered_map<std::string, std::shared_ptr<Texture>> TextureLoader::textures;
std::shared_ptr<Texture> TextureLoader::load_from_file(std::string_view filePath)
{ {
int width, height, channels; int width, height, channels;
unsigned char *data = stbi_load(filePath.data(), &width, &height, &channels, 0); unsigned char *data = stbi_load(filePath.data(), &width, &height, &channels, 0);
@@ -20,9 +22,9 @@ std::shared_ptr<Texture> Texture::load_from_file(std::string_view filePath)
return nullptr; return nullptr;
} }
Texture texture = {}; unsigned int textureID = 0;
glGenTextures(1, &texture.id); glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_2D, texture.id); glBindTexture(GL_TEXTURE_2D, textureID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@@ -36,18 +38,14 @@ std::shared_ptr<Texture> Texture::load_from_file(std::string_view filePath)
stbi_image_free(data); stbi_image_free(data);
texture.filePath = filePath; return std::make_shared<Texture>(textureID, filePath, width, height, channels);
texture.width = width;
texture.height = height;
texture.channels = channels;
return std::make_shared<Texture>(texture);
} }
std::shared_ptr<Texture> Texture::load_from_data(unsigned char* data, int width, int height, int channels) std::shared_ptr<Texture> TextureLoader::load_from_data(unsigned char* data, int width, int height, int channels)
{ {
Texture texture = {}; unsigned int textureID = 0;
glGenTextures(1, &texture.id); glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_2D, texture.id); glBindTexture(GL_TEXTURE_2D, textureID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@@ -59,24 +57,5 @@ std::shared_ptr<Texture> Texture::load_from_data(unsigned char* data, int width,
glTexImage2D(GL_TEXTURE_2D, 0, (GLint)format, width, height, 0, format, GL_UNSIGNED_BYTE, data); glTexImage2D(GL_TEXTURE_2D, 0, (GLint)format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D); glGenerateMipmap(GL_TEXTURE_2D);
texture.filePath = ""; return std::make_shared<Texture>(textureID, "memory", width, height, channels);
texture.width = width;
texture.height = height;
texture.channels = channels;
return std::make_shared<Texture>(texture);
}
Texture::~Texture()
{
glDeleteTextures(1, &id);
}
void Texture::bind(unsigned int slot)
{
}
void Texture::unbind()
{
} }

21
src/TextureLoader.h Normal file
View File

@@ -0,0 +1,21 @@
//
// Created by slinky on 5/1/26.
//
#ifndef B_ENGINE_TEXTURELOADER_H
#define B_ENGINE_TEXTURELOADER_H
#include <memory>
#include <unordered_map>
#include "Texture.h"
class TextureLoader {
public:
static std::unordered_map<std::string, std::shared_ptr<Texture>> textures;
static std::shared_ptr<Texture> load_from_file(std::string_view filePath);
static std::shared_ptr<Texture> load_from_data(unsigned char* data, int width, int height, int channels);
};
#endif //B_ENGINE_TEXTURELOADER_H

View File

@@ -11,8 +11,11 @@
#include "stb_image.h" #include "stb_image.h"
#include "Model.h" #include "Model.h"
#include "ModelLoader.h"
#include "ShaderLoader.h"
#include "ShaderProgram.h" #include "ShaderProgram.h"
#include "Texture.h" #include "Texture.h"
#include "TextureLoader.h"
GLFWwindow* gWindow = nullptr; GLFWwindow* gWindow = nullptr;
int gWindowWidth = 800; int gWindowWidth = 800;
@@ -25,10 +28,6 @@ auto cameraPosition = glm::vec3{0, 0, 0};
auto view = glm::mat4{0}; auto view = glm::mat4{0};
auto projection = glm::mat4{0}; auto projection = glm::mat4{0};
std::unordered_map<std::string, std::shared_ptr<Model>> gModels = {};
std::unordered_map<std::string, std::shared_ptr<Texture>> gTextures = {};
std::unordered_map<std::string, std::shared_ptr<ShaderProgram>> gShaders = {};
void glfw_error_callback(int error, const char* description); 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_key_callback(GLFWwindow* window, int key, int scancode, int action, int mods);
void glfw_framebuffer_size_callback(GLFWwindow* window, int width, int height); void glfw_framebuffer_size_callback(GLFWwindow* window, int width, int height);
@@ -37,6 +36,7 @@ void init_glfw();
void create_main_window(); void create_main_window();
void load_gl(); void load_gl();
void init_camera(); void init_camera();
void loop();
std::shared_ptr<Model> load_model(std::string_view _path); std::shared_ptr<Model> load_model(std::string_view _path);
@@ -55,26 +55,21 @@ int main() {
// create a default texture // create a default texture
unsigned char defaultDiffuseData[4] = {static_cast<unsigned char>(255), 255, 255, 255}; unsigned char defaultDiffuseData[4] = {static_cast<unsigned char>(255), 255, 255, 255};
gTextures["default_diffuse"] = Texture::load_from_data(reinterpret_cast<unsigned char*>(&defaultDiffuseData), 1, 1, 4); TextureLoader::textures["default_diffuse"] = TextureLoader::load_from_data(reinterpret_cast<unsigned char*>(&defaultDiffuseData), 1, 1, 4);
// create a default specular map // create a default specular map
unsigned char defaultSpecularData[4] = {static_cast<unsigned char>(128), 128, 128, 255}; unsigned char defaultSpecularData[4] = {static_cast<unsigned char>(128), 128, 128, 255};
gTextures["default_specular"] = Texture::load_from_data(reinterpret_cast<unsigned char*>(&defaultSpecularData), 1, 1, 4); TextureLoader::textures["default_specular"] = TextureLoader::load_from_data(reinterpret_cast<unsigned char*>(&defaultSpecularData), 1, 1, 4);
gShaders["phong_shader"] = ShaderProgram::load("./resources/standard.frag", "./resources/standard.vert"); ShaderLoader::shaders["phong_shader"] = ShaderLoader::load("./resources/standard.vert", "./resources/standard.frag");
if (gShaders["phong_shader"] == nullptr) if (ShaderLoader::shaders["phong_shader"] == nullptr)
{ {
std::exit(1); std::exit(1);
} }
while (!glfwWindowShouldClose(gWindow)) { ModelLoader::models["cube"] = ModelLoader::load_from_file("./resources/cube.obj");
glfwPollEvents();
glClearColor(0.2f, 0.3f, 0.3f, 1.0f); loop();
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(gWindow);
}
glfwDestroyWindow(gWindow); glfwDestroyWindow(gWindow);
glfwTerminate(); glfwTerminate();
@@ -153,7 +148,56 @@ void init_camera()
projection = glm::perspective(glm::radians(75.f), aspectRatio, 0.1f, 100.0f); projection = glm::perspective(glm::radians(75.f), aspectRatio, 0.1f, 100.0f);
} }
std::shared_ptr<Model> load_model(std::string_view _path) void loop() {
{ Texture* defaultDiffuse = TextureLoader::textures["default_diffuse"].get();
return std::make_shared<Model>(); Texture* defaultSpecular = TextureLoader::textures["default_specular"].get();
while (!glfwWindowShouldClose(gWindow)) {
auto modelMatrix = glm::identity<glm::mat4>();
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);
}
} }