diff --git a/src/graphics/arrays.cpp b/src/graphics/arrays.cpp index 9d1bfbb..8da8753 100644 --- a/src/graphics/arrays.cpp +++ b/src/graphics/arrays.cpp @@ -32,5 +32,8 @@ void arrays::vertex_attrib_pointers() glVertexAttribPointer(3, 3, GL_FLOAT, false, sizeof(v), ptr_diff(&v.normal, &v)); glEnableVertexAttribArray(3); + + glVertexAttribPointer(4, 1, GL_FLOAT, false, sizeof(v), ptr_diff(&v.do_tex, &v)); + glEnableVertexAttribArray(4); } diff --git a/src/graphics/arrays.hpp b/src/graphics/arrays.hpp index b158d3c..e9995d6 100644 --- a/src/graphics/arrays.hpp +++ b/src/graphics/arrays.hpp @@ -13,6 +13,7 @@ struct vertex glm::vec2 texpos = {0, 0}; glm::vec3 pos = {0, 0, 0}; glm::vec3 normal = {0, 0, 0}; + float do_tex = 0; vertex() { } vertex(unsigned long texid, glm::vec2 texpos, glm::vec3 pos) : texid(texid), texpos(texpos), pos(pos) { } diff --git a/src/graphics/camera.cpp b/src/graphics/camera.cpp index 9a87165..71c9aef 100644 --- a/src/graphics/camera.cpp +++ b/src/graphics/camera.cpp @@ -5,6 +5,7 @@ #include "camera.hpp" #include "keyboard.hpp" +#include #include #include #include @@ -12,55 +13,80 @@ using namespace sim::graphics; static double yaw = 0, pitch = 0; -static double x = 0, y = 0, z = 0; +static glm::vec<3, double> pos(56, 90, 8); +static glm::vec<3, double> velocity(0); void camera::rotate(double y, double p) { - yaw += y * 0.05; + yaw -= y * 0.05; pitch += p * 0.05; - if(pitch < -90) pitch = -90; - if(pitch > 90) pitch = 90; + if(pitch < 0) pitch = 0; + if(pitch > 180) pitch = 180; } void camera::move(double xoff, double yoff, double zoff) { - x += xoff; - y += yoff; - z += zoff; + pos.x += xoff; + pos.y += yoff; + pos.z += zoff; } void camera::update() { - double xoff = 0, yoff = 0, zoff = 0; - - glm::vec<3, double> off(0, 0, 0); + glm::vec<2, double> off(0, 0); + double m = 0.01; - if(keyboard::is_pressed(GLFW_KEY_SPACE)) - off.y -= 1; - if(keyboard::is_pressed(GLFW_KEY_LEFT_SHIFT)) - off.y += 1; if(keyboard::is_pressed(GLFW_KEY_W)) - off.z += 1; + off.y += 1; if(keyboard::is_pressed(GLFW_KEY_S)) - off.z -= 1; + off.y -= 1; if(keyboard::is_pressed(GLFW_KEY_A)) off.x += 1; if(keyboard::is_pressed(GLFW_KEY_D)) off.x -= 1; + if(keyboard::is_pressed(GLFW_KEY_LEFT_SHIFT)) + m *= 1.5; + if(off.x != 0 || off.y != 0) + off /= std::sqrt(off.x * off.x + off.y * off.y); - double angle = -glm::radians(yaw); + double angle = glm::radians(yaw); glm::mat<2, 2, double> mat = { std::cos(angle), std::sin(angle), -std::sin(angle), std::cos(angle) }; - glm::vec<2, double> rotated = glm::vec<2, double>(off.x, off.z) * mat; + glm::vec<2, double> rotated = glm::vec<2, double>(off.x, off.y) * mat; + bool on_ground = false; - y += off.y * 0.05; - x += rotated.x * 0.05; - z += rotated.y * 0.05; + velocity.z -= 0.00981; + + if(pos.z + velocity.z < 3.5) + { + on_ground = true; + + if(keyboard::is_pressed(GLFW_KEY_SPACE)) + { + velocity.z += 0.4; + } + + else + { + velocity.z = 0; + } + } + + else + { + m = 0; + } + + velocity.x += rotated.x * m; + velocity.y += rotated.y * m; + + pos += velocity; + velocity *= glm::vec<3, double>(on_ground ? 0.9 : 0.9999); } glm::mat4 camera::get_model_matrix() @@ -68,8 +94,8 @@ glm::mat4 camera::get_model_matrix() glm::mat4 mat(1); mat = glm::rotate(mat, (float)glm::radians(pitch), glm::vec3(1, 0, 0)); - mat = glm::rotate(mat, (float)glm::radians(yaw), glm::vec3(0, 1, 0)); - mat = glm::translate(mat, glm::vec3(x, y, z)); + mat = glm::rotate(mat, (float)glm::radians(yaw), glm::vec3(0, 0, 1)); + mat = glm::translate(mat, glm::vec3(pos.x, pos.y, pos.z)); return mat; } diff --git a/src/graphics/font.cpp b/src/graphics/font.cpp index 73d59f9..82a6d2f 100644 --- a/src/graphics/font.cpp +++ b/src/graphics/font.cpp @@ -33,8 +33,9 @@ void font::init() FT_Set_Pixel_Sizes(face, 0, 1024); GLuint texids[128]; - + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glCreateTextures(GL_TEXTURE_2D, 128, texids); for(int i = 0; i < 128; i++) { @@ -54,7 +55,6 @@ void font::init() continue; } - glCreateTextures(GL_TEXTURE_2D, 1, &texids[i]); glTextureStorage2D(texids[i], 1, GL_R8, c.size.x, c.size.y); glTextureSubImage2D(texids[i], 0, 0, 0, c.size.x, c.size.y, GL_RED, GL_UNSIGNED_BYTE, face->glyph->bitmap.buffer); diff --git a/src/graphics/model.cpp b/src/graphics/model.cpp index 6139305..3862792 100644 --- a/src/graphics/model.cpp +++ b/src/graphics/model.cpp @@ -6,23 +6,52 @@ #include #include +#include #include #include "mesh.hpp" #include "model.hpp" #include "arrays.hpp" +#include "texture.hpp" using namespace sim::graphics; -static void proc_mesh(std::vector& meshes, aiMesh* mesh, const aiScene* scene) +struct proc_state { + unsigned int offset = 0; + + std::string base; std::vector vertices; std::vector indices; +}; + +static unsigned int proc_texture(const proc_state& state, aiMaterial* mat, aiTextureType type) +{ + if(mat->GetTextureCount(type) == 0) + { + return 0; + } + + aiString str; + mat->GetTexture(type, 0, &str); + + std::string filename(str.C_Str()); + std::replace(filename.begin(), filename.end(), '\\', '/'); + + return texture::load(state.base + "/" + filename); +} + +static void proc_mesh(proc_state& state, std::vector& meshes, aiMesh* mesh, const aiScene* scene) +{ + aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex]; + unsigned int texid = proc_texture(state, material, aiTextureType_DIFFUSE); + unsigned int offset = state.offset; for(unsigned int i = 0; i < mesh->mNumVertices; i++) { arrays::vertex vertex; + vertex.texid = texid; vertex.pos = {mesh->mVertices[i].x, mesh->mVertices[i].y, mesh->mVertices[i].z}; if(mesh->HasNormals()) @@ -30,7 +59,13 @@ static void proc_mesh(std::vector& meshes, aiMesh* mesh, const aiScene* sc vertex.normal = {mesh->mNormals[i].x, mesh->mNormals[i].y, mesh->mNormals[i].z}; } - vertices.push_back(vertex); + if(mesh->mTextureCoords[0]) + { + vertex.texpos = {mesh->mTextureCoords[0][i].x, mesh->mTextureCoords[0][i].y}; + vertex.do_tex = 1; + } + + state.vertices.push_back(vertex); } for(unsigned int i = 0; i < mesh->mNumFaces; i++) @@ -39,35 +74,40 @@ static void proc_mesh(std::vector& meshes, aiMesh* mesh, const aiScene* sc for(unsigned int j = 0; j < face.mNumIndices; j++) { - indices.push_back(face.mIndices[j]); + state.indices.push_back(face.mIndices[j] + offset); } } - sim::graphics::mesh m; - m.set_vertices(&vertices[0], vertices.size(), GL_STATIC_DRAW); - m.set_indices(&indices[0], indices.size(), GL_STATIC_DRAW); - meshes.push_back(std::move(m)); + state.offset += mesh->mNumVertices; } -static void proc_node(std::vector& meshes, aiNode* node, const aiScene* scene) +static void proc_node(proc_state& state, std::vector& meshes, aiNode* node, const aiScene* scene) { for(size_t i = 0; i < node->mNumMeshes; i++) { aiMesh* mesh = scene->mMeshes[node->mMeshes[i]]; - proc_mesh(meshes, mesh, scene); + proc_mesh(state, meshes, mesh, scene); } for(size_t i = 0; i < node->mNumChildren; i++) { - proc_node(meshes, node->mChildren[i], scene); + proc_node(state, meshes, node->mChildren[i], scene); } } -void model::load(const char* path) +void model::load(std::string base, std::string filename) { + proc_state state {.base = base}; + std::string path = base + "/" + filename; Assimp::Importer importer; - const aiScene *scene = importer.ReadFile(path, aiProcess_Triangulate | aiProcess_FlipUVs); - proc_node(meshes, scene->mRootNode, scene); + + const aiScene *scene = importer.ReadFile(path.c_str(), aiProcess_Triangulate | aiProcess_FlipUVs); + proc_node(state, meshes, scene->mRootNode, scene); + + sim::graphics::mesh m; + m.set_vertices(&state.vertices[0], state.vertices.size(), GL_STATIC_DRAW); + m.set_indices(&state.indices[0], state.indices.size(), GL_STATIC_DRAW); + meshes.push_back(std::move(m)); } void model::render() const diff --git a/src/graphics/model.hpp b/src/graphics/model.hpp index 8a15c52..86aa60e 100644 --- a/src/graphics/model.hpp +++ b/src/graphics/model.hpp @@ -4,6 +4,7 @@ #include "mesh.hpp" #include +#include namespace sim::graphics { @@ -12,7 +13,7 @@ struct model { std::vector meshes; - void load(const char* path); + void load(std::string base, std::string path); void render() const; }; diff --git a/src/graphics/shader.cpp b/src/graphics/shader.cpp index f0bba1f..444607b 100644 --- a/src/graphics/shader.cpp +++ b/src/graphics/shader.cpp @@ -17,23 +17,23 @@ layout (location = 0) in sampler2D aTex; layout (location = 1) in vec2 aTexPos; layout (location = 2) in vec3 aPos; layout (location = 3) in vec3 aNormal; +layout (location = 4) in float aDoTex; uniform mat4 model; uniform mat4 projection; +out float do_tex; +out float brightness; out flat sampler2D tex; out vec2 texPos; -out float zVal; void main() { vec4 pos = model * vec4(aPos, 1.0); + vec3 cNormal = vec3(0.f, 0.f, 1.f) * mat3(model); - mat3 model_norm = mat3(model); - vec3 normal = aNormal; - vec3 cNormal = vec3(0.f, 0.f, 1.f) * model_norm; - - zVal = dot(normal, cNormal);// / (length(aNormal) * length(cNormal)); + brightness = dot(normalize(aNormal), normalize(cNormal)) * 0.25f + 0.75f; + do_tex = aDoTex; gl_Position = projection * pos; texPos = aTexPos; @@ -46,19 +46,19 @@ static const char* FRAGMENT_SHADER = R"( #version 460 core #extension GL_ARB_bindless_texture : require +in float do_tex; +in float brightness; in flat sampler2D tex; in vec2 texPos; -in float zVal; out vec4 FragColour; -uniform bool do_tex; uniform mat4 tex_mat; void main() { - vec4 texdata = do_tex ? texture2D(tex, texPos) : vec4(1); - FragColour = tex_mat * texdata * vec4(zVal, zVal, zVal, 1); + vec4 texdata = (do_tex > 0.5f) ? texture2D(tex, texPos) : vec4(1); + FragColour = tex_mat * texdata * vec4(vec3(brightness), 1); } )"; diff --git a/src/graphics/texture.cpp b/src/graphics/texture.cpp new file mode 100644 index 0000000..e7ca227 --- /dev/null +++ b/src/graphics/texture.cpp @@ -0,0 +1,76 @@ + +#include +#include +#include + +#include +#include + +#include "texture.hpp" + +using namespace sim::graphics; + +static std::unordered_map loaded; + +unsigned int texture::load(std::string path) +{ + const auto it = loaded.find(path); + + if(it != loaded.end()) + { + return it->second; + } + + int width, height, channels; + unsigned char* data = stbi_load(path.c_str(), &width, &height, &channels, 0); + + if(!data) + { + stbi_image_free(data); + throw std::runtime_error("Failed to load path: " + path); + } + + GLenum format, format_in; + switch(channels) + { + case 1: + format = GL_RED; + format_in = GL_R8; + break; + case 2: + format = GL_RG; + format_in = GL_RG8; + break; + case 3: + format = GL_RGB; + format_in = GL_RGB8; + break; + case 4: + format = GL_RGBA; + format_in = GL_RGBA8; + break; + } + + unsigned int texid; + + glCreateTextures(GL_TEXTURE_2D, 1, &texid); + glTextureStorage2D(texid, 1, format_in, width, height); + glTextureSubImage2D(texid, 0, 0, 0, width, height, format, GL_UNSIGNED_BYTE, data); + + stbi_image_free(data); + + glTextureParameteri(texid, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTextureParameteri(texid, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTextureParameteri(texid, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTextureParameteri(texid, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glGenerateTextureMipmap(texid); + + unsigned int handle = glGetTextureHandleARB(texid); + glMakeTextureHandleResidentARB(handle); + + std::cout << "Loaded Image: " << path << "\n"; + + loaded[path] = handle; + return handle; +} + diff --git a/src/graphics/texture.hpp b/src/graphics/texture.hpp new file mode 100644 index 0000000..a29d157 --- /dev/null +++ b/src/graphics/texture.hpp @@ -0,0 +1,12 @@ + +#pragma once + +#include + +namespace sim::graphics::texture +{ + +unsigned int load(std::string path); + +}; + diff --git a/src/graphics/window.cpp b/src/graphics/window.cpp index 01d267c..431c73a 100644 --- a/src/graphics/window.cpp +++ b/src/graphics/window.cpp @@ -35,8 +35,11 @@ void window::create() glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, true); glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, true); + +#ifdef __APPLE__ + glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, true); +#endif win = glfwCreateWindow(800, 600, "FastNuclearSim", nullptr, nullptr); @@ -53,6 +56,7 @@ void window::create() glEnable(GL_DEBUG_OUTPUT); glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); + glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); glEnable(GL_BLEND); @@ -66,7 +70,7 @@ void window::create() shader::init_program(); - Model.load("teapot.obj"); + Model.load("Minimalistic Modern Office", "Minimalistic Modern Office.fbx"); glViewport(0, 0, 800, 600); } @@ -77,10 +81,10 @@ void window::loop() glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glm::mat4 mat_colour = { - 1, 1, 1, 1, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0 + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 }; camera::update(); @@ -90,11 +94,12 @@ void window::loop() double mouse_x, mouse_y; mouse::get(mouse_x, mouse_y); - mat_model = glm::translate(mat_model, glm::vec3(0.0f, 0.0f, -5.0f)); - mat_model = glm::rotate(mat_model, float(M_PI * 0.125), glm::vec3(1, 1, 1)); - mat_model = glm::scale(mat_model, glm::vec3(1, 1, 1) * 0.2f); + mat_model = glm::translate(mat_model, glm::vec3(0, -90, 0)); +// mat_model = glm::rotate(mat_model, float(M_PI * 0.125), glm::vec3(1, 1, 1)); + mat_model = glm::scale(mat_model, glm::vec3(15, 60, 15)); + mat_model = glm::rotate(mat_model, -float(M_PI) / 2, glm::vec3(0, 1, 0)); - glm::mat4 mat_projection = glm::perspective(float(M_PI * 0.25), (float)resize::get_aspect(), 0.1f, 100.f); + glm::mat4 mat_projection = glm::perspective(glm::radians(90.0f), (float)resize::get_aspect(), 0.1f, 200.f); glUniformMatrix4fv(shader::gl_tex_mat, 1, false, &mat_colour[0][0]); glUniformMatrix4fv(shader::gl_projection, 1, false, &mat_projection[0][0]); diff --git a/src/stb/stb_image.cpp b/src/stb/stb_image.cpp new file mode 100644 index 0000000..36a258d --- /dev/null +++ b/src/stb/stb_image.cpp @@ -0,0 +1,4 @@ + +#define STB_IMAGE_IMPLEMENTATION +#include +