diff --git a/CMakeLists.txt b/CMakeLists.txt index f60d446..41edbd5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -73,7 +73,4 @@ file(GLOB_RECURSE ShaderSources CONFIGURE_DEPENDS add_shaders(VulkanEngineShaders ${ShaderSources}) add_dependencies(VulkanEngine VulkanEngineShaders) -file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/assets/paving-stones.jpg" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/assets") -file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/assets/copying-stones.jpg" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/assets") -file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/assets/player.fbx" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/assets") -file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/assets/wall.fbx" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/assets") \ No newline at end of file +file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/assets/" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/assets") \ No newline at end of file diff --git a/assets/copying-stones.jpg b/assets/background.fbx similarity index 96% rename from assets/copying-stones.jpg rename to assets/background.fbx index fd19784..2901c65 100644 Binary files a/assets/copying-stones.jpg and b/assets/background.fbx differ diff --git a/assets/bullet.fbx b/assets/bullet.fbx new file mode 100644 index 0000000..03877b7 Binary files /dev/null and b/assets/bullet.fbx differ diff --git a/assets/paving-stones.jpg b/assets/paving-stones.jpg deleted file mode 100644 index cbf66da..0000000 Binary files a/assets/paving-stones.jpg and /dev/null differ diff --git a/assets/player.fbx b/assets/player.fbx index b14433a..e02cff7 100644 Binary files a/assets/player.fbx and b/assets/player.fbx differ diff --git a/assets/player_flame.fbx b/assets/player_flame.fbx new file mode 100644 index 0000000..c368a9a Binary files /dev/null and b/assets/player_flame.fbx differ diff --git a/assets/wall.fbx b/assets/wall.fbx deleted file mode 100644 index 4717fea..0000000 Binary files a/assets/wall.fbx and /dev/null differ diff --git a/include/asset/loader.h b/include/asset/loader.h new file mode 100644 index 0000000..1c8d579 --- /dev/null +++ b/include/asset/loader.h @@ -0,0 +1,22 @@ +#pragma once + +#include "asset/object/model.h" +#include "assimp/Importer.hpp" +#include "assimp/postprocess.h" +#include "assimp/scene.h" + +namespace veng { + +typedef Model& inModel; + +class Loader { +public: + void setPath(std::string path); + void loadModel(inModel model); + std::vector readTexture(); + +private: + Assimp::Importer importer_; + const struct aiScene* scene_; +}; +} // namespace veng diff --git a/include/asset/object/model.h b/include/asset/object/model.h index 206e6b0..97181ec 100644 --- a/include/asset/object/model.h +++ b/include/asset/object/model.h @@ -1,15 +1,15 @@ #pragma once +#include +#include #include #include "material.h" -#include "vulkan/graphics.h" +#include "vulkan/buffer_handle.h" #include "vulkan/vertex.h" -#include - namespace veng { struct Model { - Model(std::shared_ptr graphics); + Model(class Graphics* graphics) : graphics_(graphics) {} ~Model(); std::vector vertices; @@ -17,11 +17,26 @@ struct Model { std::vector indices; veng::BufferHandle index_buffer; - glm::mat4 transform; + glm::mat4 transform = glm::rotate(glm::mat4(1.0f), glm::radians(180.f), + glm::vec3(0.f, 0.f, 1.f)); + + glm::vec3 position = glm::vec3(0.f); + glm::vec3 linear_velocity = glm::vec3(0.f); + glm::vec3 linear_acceleration = glm::vec3(0.f); + + glm::quat rotation = glm::quat(1.0f, 0.0f, 0.0f, 0.0f); + glm::vec3 angular_velocity = glm::vec3(0.f); // 축 * 각속도(rad/s) + glm::vec3 angular_acceleration = glm::vec3(0.f); + + glm::vec3 scale = glm::vec3(1.f); Material material; -private: - std::weak_ptr graphics_; + glm::mat4 UpdateTransform(float dt); + + glm::vec3 original_offset = glm::vec3(0.f); + + private: + class Graphics* graphics_; }; } // namespace veng diff --git a/include/vulkan/coordinate.h b/include/vulkan/coordinate.h new file mode 100644 index 0000000..2b9ef5f --- /dev/null +++ b/include/vulkan/coordinate.h @@ -0,0 +1,39 @@ +#pragma once + +#include + +#include "asset/object/model.h" + +namespace std { +template <> +struct hash { + std::size_t operator()(const glm::i64vec3& v) const noexcept { + std::size_t h1 = std::hash()(v.x); + std::size_t h2 = std::hash()(v.y); + std::size_t h3 = std::hash()(v.z); + return h1 ^ (h2 << 1) ^ (h3 << 2); + } +}; +} // namespace std + +namespace veng { + +class Coord { + public: + Coord() : seg(glm::i64vec3(0)), pos(glm::vec3(0.f)) {} + Coord(glm::vec3 _pos) : seg(glm::i64vec3(0)), pos(_pos) {} + Coord(glm::i64vec3 _seg, glm::vec3 _pos) : seg(_seg), pos(_pos) {} + + glm::i64vec3 seg; + glm::vec3 pos; + + Coord operator+(const Coord& other) const; + Coord operator-(const Coord& other) const; + + std::unordered_map coord_system; + + private: + const std::float_t border = 1000.f; +}; + +} // namespace veng diff --git a/include/vulkan/graphics.h b/include/vulkan/graphics.h index d6856f6..b8fbdde 100644 --- a/include/vulkan/graphics.h +++ b/include/vulkan/graphics.h @@ -40,6 +40,7 @@ class Graphics final { BufferHandle CreateIndexBuffer(gsl::span indices); void DestroyBuffer(BufferHandle handle); TextureHandle CreateTexture(gsl::czstring path); + TextureHandle CreateTexture(std::vector image_file_data); TextureHandle CreateTexture(gsl::span image_file_data); void DestroyTexture(TextureHandle handle); diff --git a/src/asset/loader.cpp b/src/asset/loader.cpp new file mode 100644 index 0000000..5b40fb5 --- /dev/null +++ b/src/asset/loader.cpp @@ -0,0 +1,62 @@ +#include "asset/loader.h" + +#include "stb/stb_image.h" + +namespace veng { + +void Loader::setPath(std::string path) { + scene_ = importer_.ReadFile( + path.c_str(), aiProcess_CalcTangentSpace | aiProcess_Triangulate | + aiProcess_JoinIdenticalVertices | + aiProcess_SortByPType | aiProcess_FlipUVs); + if (scene_ == nullptr || !scene_->HasMeshes()) + throw std::runtime_error(importer_.GetErrorString()); +} +void Loader::loadModel(inModel model) { + aiMesh* mesh = scene_->mMeshes[0]; + + for (std::uint32_t i = 0; i < mesh->mNumVertices; i++) { + glm::vec2 uv = {mesh->mTextureCoords[0][i].x, mesh->mTextureCoords[0][i].y}; + model.vertices.emplace_back( + glm::vec3{mesh->mVertices[i].x, mesh->mVertices[i].y, + mesh->mVertices[i].z}, + uv); + } + + for (auto& const it : model.vertices) { + model.original_offset.x += it.position.x / model.vertices.size(); + model.original_offset.y += it.position.y / model.vertices.size(); + model.original_offset.z += it.position.z / model.vertices.size(); + } + + for (auto& vertex : model.vertices) { + vertex.position -= model.original_offset; + } + + for (std::uint32_t i = 0; i < mesh->mNumFaces; i++) { + aiFace face = mesh->mFaces[i]; + for (unsigned int j = 0; j < face.mNumIndices; ++j) { + model.indices.push_back(face.mIndices[j]); + } + } +} + +std::vector Loader::readTexture() { + aiString texture_path; + if (scene_->mMaterials[scene_->mMeshes[0]->mMaterialIndex]->GetTexture( + aiTextureType_DIFFUSE, 0, &texture_path) != AI_SUCCESS) { + spdlog::warn("No texture"); + } + + if (scene_->mNumTextures > 0 || texture_path.C_Str()[0] == '*') { + const aiTexture* texture = scene_->GetEmbeddedTexture(texture_path.C_Str()); + + return std::vector( + (std::uint8_t*)texture->pcData, + (std::uint8_t*)texture->pcData + texture->mWidth); + } + + return ReadFile(texture_path.C_Str()); +} + +} // namespace veng diff --git a/src/asset/object/model.cpp b/src/asset/object/model.cpp index 7d5be8a..3b2b428 100644 --- a/src/asset/object/model.cpp +++ b/src/asset/object/model.cpp @@ -1,17 +1,32 @@ #include "asset/object/model.h" +#include "vulkan/graphics.h" + namespace veng { -Model::Model(std::shared_ptr graphics) { graphics_ = graphics; } - Model::~Model() { - auto graphics = graphics_.lock(); + if (graphics_ == nullptr) return; - if (!graphics) return; + graphics_->DestroyTexture(material.texture); + graphics_->DestroyBuffer(vertex_buffer); + graphics_->DestroyBuffer(index_buffer); +} - graphics->DestroyTexture(material.texture); - graphics->DestroyBuffer(vertex_buffer); - graphics->DestroyBuffer(index_buffer); +glm::mat4 Model::UpdateTransform(float dt) { + linear_velocity += linear_acceleration * dt; + position += linear_velocity * dt; + + angular_velocity += angular_acceleration * dt; + if (glm::length(angular_velocity) > 1e-6f) { + rotation = + glm::normalize(glm::rotate(rotation, glm::length(angular_velocity * dt), + glm::normalize(angular_velocity))); + } + + transform = glm::translate(glm::mat4(1.0f), position) * + glm::mat4_cast(rotation) * glm::scale(glm::mat4(1.0f), scale); + + return transform; } } // namespace veng diff --git a/src/main.cpp b/src/main.cpp index 49240ec..51f1d72 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,16 +1,13 @@ #include #include -#include -#include "asset/object/model.h" -#include "assimp/Importer.hpp" -#include "assimp/postprocess.h" -#include "assimp/scene.h" +#include "asset/loader.h" #include "glfw/glfw_initialization.h" #include "glfw/glfw_monitor.h" #include "glfw/glfw_window.h" #include "precomp.h" +#include "vulkan/coordinate.h" #include "vulkan/graphics.h" std::int32_t main(std::int32_t argc, gsl::zstring* argv) { @@ -19,83 +16,63 @@ std::int32_t main(std::int32_t argc, gsl::zstring* argv) { veng::Window window("Vulkan Engine", {800, 600}); window.TryMoveToMonitor(0); - std::shared_ptr graphics = - std::make_shared(&window); + veng::Graphics graphics(&window); - Assimp::Importer assetImporter; + veng::Coord cord; - const struct aiScene* scene = assetImporter.ReadFile( - "assets/wall.fbx", aiProcess_CalcTangentSpace | aiProcess_Triangulate | - aiProcess_JoinIdenticalVertices | - aiProcess_SortByPType | aiProcess_FlipUVs); + veng::Loader loader; - if (scene == nullptr || !scene->HasMeshes()) { - spdlog::error(assetImporter.GetErrorString()); - return false; - } + veng::Model player(&graphics); + loader.setPath("assets/player.fbx"); + loader.loadModel(player); + player.vertex_buffer = graphics.CreateVertexBuffer(player.vertices); + player.index_buffer = graphics.CreateIndexBuffer(player.indices); + player.material.texture = graphics.CreateTexture(loader.readTexture()); + player.scale = glm::vec3(.02f); + player.position.x = 100000.f; + player.position.y = 100000.f; - veng::Model player(graphics); + veng::Model player_flame(&graphics); + loader.setPath("assets/player_flame.fbx"); + loader.loadModel(player_flame); + player_flame.vertex_buffer = + graphics.CreateVertexBuffer(player_flame.vertices); + player_flame.index_buffer = graphics.CreateIndexBuffer(player_flame.indices); + player_flame.material.texture = graphics.CreateTexture(loader.readTexture()); - aiMesh* mesh = scene->mMeshes[0]; - for (std::uint32_t i = 0; i < mesh->mNumVertices; i++) { - glm::vec2 uv = {mesh->mTextureCoords[0][i].x, mesh->mTextureCoords[0][i].y}; - player.vertices.emplace_back( - glm::vec3{mesh->mVertices[i].x, mesh->mVertices[i].y, - mesh->mVertices[i].z}, - uv); - } - player.vertex_buffer = graphics->CreateVertexBuffer(player.vertices); + veng::Model bullet(&graphics); + loader.setPath("assets/bullet.fbx"); + loader.loadModel(bullet); + bullet.vertex_buffer = graphics.CreateVertexBuffer(bullet.vertices); + bullet.index_buffer = graphics.CreateIndexBuffer(bullet.indices); + bullet.material.texture = graphics.CreateTexture(loader.readTexture()); + bullet.scale = glm::vec3(.1f); - for (std::uint32_t i = 0; i < mesh->mNumFaces; i++) { - aiFace face = mesh->mFaces[i]; - for (unsigned int j = 0; j < face.mNumIndices; ++j) { - player.indices.push_back(face.mIndices[j]); - } - } - player.index_buffer = graphics->CreateIndexBuffer(player.indices); + veng::Model background(&graphics); + loader.setPath("assets/background.fbx"); + loader.loadModel(background); + background.vertex_buffer = graphics.CreateVertexBuffer(background.vertices); + background.index_buffer = graphics.CreateIndexBuffer(background.indices); + background.material.texture = graphics.CreateTexture(loader.readTexture()); + background.position = {background.position.x, background.position.y, 30.f}; + background.scale *= 100; - aiString string; - if (scene->mMaterials[scene->mMeshes[0]->mMaterialIndex]->GetTexture( - aiTextureType_DIFFUSE, 0, &string) != AI_SUCCESS) { - std::cout << "No texture" << std::endl; - } - - veng::Model wall(graphics); - - wall.vertices = {veng::Vertex{{-1.f, -1.f, 0.f}, {0.f, 1.f}}, - veng::Vertex{{1.f, -1.f, 0.f}, {1.f, 1.f}}, - veng::Vertex{{-1.f, 1.f, 0.f}, {0.f, 0.f}}, - veng::Vertex{{1.f, 1.f, 0.f}, {1.f, 0.f}}}; - wall.vertex_buffer = graphics->CreateVertexBuffer(wall.vertices); - - wall.indices = {0, 3, 2, 0, 1, 3}; - wall.index_buffer = graphics->CreateIndexBuffer(wall.indices); - - player.transform = - glm::rotate(glm::mat4(1.0f), glm::radians(0.f), glm::vec3(0.f, 1.f, 0.f)); - // player.transform = glm::scale(player.transform, - // glm::vec3(50.f, 50.f, 50.f)); - - wall.transform = glm::rotate(glm::mat4(1.0f), glm::radians(180.f), - glm::vec3(0.f, 0.f, 1.f)); - // plane.transform = glm::scale(plane.transform, glm::vec3(100.f, 100.f, - // 100.f)); + veng::Model camera_lag(nullptr); + camera_lag.position = player.position; + camera_lag.position.z = -5; glm::mat4 view = - glm::lookAt(glm::vec3(0.f, 0.f, 10.f), glm::vec3(0.f, 0.f, 0.f), - glm::vec3(0.f, 1.f, 0.f)); - /*glm::mat4 projection = - glm::perspective(glm::radians(150.f), 800.f / 600.f, 0.1f, 100.f);*/ - glm::mat4 projection = glm::ortho(-10.f, 10.f, -10.f, 10.f, -10.f, 10.f); - graphics->SetViewProjection(view, projection); + glm::lookAt(glm::vec3(0.f, 0.f, -5.f), glm::vec3(0.f, 0.f, 0.f), + glm::vec3(0.f, -1.f, 0.f)); + glm::mat4 projection = + glm::perspective(glm::radians(150.f), 800.f / 600.f, 0.1f, 100.f); + // glm::mat4 projection = glm::ortho(-10.f, 10.f, -10.f, 10.f, -10.f, 10.f); + graphics.SetViewProjection(view, projection); - // player.material.texture = - // graphics->CreateTexture("assets/paving-stones.jpg"); - - auto texture = scene->GetEmbeddedTexture(string.C_Str()); - player.material.texture = graphics->CreateTexture( - gsl::span{(std::uint8_t*)texture->pcData, texture->mWidth}); - wall.material.texture = graphics->CreateTexture("assets/copying-stones.jpg"); + /*auto raw_texture = loader.readTexture(); + player.material.texture = + graphics.CreateTexture({raw_texture.data(), raw_texture.size()}); + wall.material.texture = graphics.CreateTexture("assets/copying-stones.jpg");*/ double last_time = glfwGetTime(); @@ -110,36 +87,114 @@ std::int32_t main(std::int32_t argc, gsl::zstring* argv) { auto grater = (current_window_size.x > current_window_size.y) ? current_window_size.x : current_window_size.y; - projection = glm::ortho(0.01f * (float)current_window_size.x / 2, + /*projection = glm::ortho(0.01f * (float)current_window_size.x / 2, -0.01f * (float)current_window_size.x / 2, -0.01f * (float)current_window_size.y / 2, 0.01f * (float)current_window_size.y / 2, - -1 * (float)grater, (float)grater); - /*projection = glm::perspective( + -1 * (float)grater, (float)grater);*/ + projection = glm::perspective( glm::radians(90.f), (float)current_window_size.x / (float)current_window_size.y, 0.1f, - 100.f);*/ - graphics->SetViewProjection(view, projection); + 100.f); + graphics.SetViewProjection(view, projection); } - // std::cout << glfwGetKey(window.GetHandle(), GLFW_KEY_W) << std::endl; + glm::vec3 forward = player.rotation * glm::vec3(0, 1, 0); + glm::vec3 right = player.rotation * glm::vec3(1, 0, 0); - if (graphics->BeginFrame()) { + if (glfwGetKey(window.GetHandle(), GLFW_KEY_A) == GLFW_PRESS) { + right = player.rotation * glm::vec3(0, 0, 1); + player.angular_velocity = right * 6.f; + } else if (glfwGetKey(window.GetHandle(), GLFW_KEY_D) == GLFW_PRESS) { + right = player.rotation * glm::vec3(0, 0, 1); + player.angular_velocity = right * -6.f; + } else { + right = player.rotation * glm::vec3(0, 0, 1); + player.angular_velocity = right * 0.f; + } + + background.linear_velocity = player.linear_velocity * -1.f; + + if (graphics.BeginFrame()) { double current_time = glfwGetTime(); float delta_time = static_cast(current_time - last_time); last_time = current_time; - player.transform = - glm::rotate(player.transform, delta_time * glm::radians(60.f), - glm::vec3(0.f, 0.f, 1.f)); - graphics->RenderModel(player); + float stiffness = 500.0f * ((glm::length(player.linear_velocity) > 1.f) + ? glm::length(player.linear_velocity) + : 1.f); // 더 크면 빠르게 따라감 + float damping = 10.f * glm::sqrt(stiffness); // 임계 감쇠 - wall.transform = - glm::rotate(wall.transform, delta_time * glm::radians(-60.f), - glm::vec3(0.f, 1.f, 0.f)); - graphics->RenderModel(wall); + // 감쇠 스프링 업데이트 + glm::vec3 displacement = camera_lag.position - player.position; - graphics->EndFrame(); + camera_lag.linear_velocity += + (-stiffness * displacement - damping * camera_lag.linear_velocity) * + delta_time; + + glm::mat4 view = glm::lookAt( + glm::vec3(camera_lag.position.x, camera_lag.position.y, -5.f), + camera_lag.position, glm::vec3(0.f, -1.f, 0.f)); + graphics.SetViewProjection(view, projection); + + player.UpdateTransform(delta_time); + player_flame.transform = + glm::translate(player.transform, player_flame.original_offset * 0.5f); + background.UpdateTransform(delta_time); + camera_lag.UpdateTransform(delta_time); + + graphics.RenderModel(player); + + if (glfwGetKey(window.GetHandle(), GLFW_KEY_W) == GLFW_PRESS) { + player.linear_acceleration = glm::normalize(forward) * 10.f; + + graphics.RenderModel(player_flame); + } else + player.linear_acceleration = forward * .0f; + + spdlog::info("player cord: x:{}, y:{}", player.position.x, + player.position.y); + + if (player.position.x - background.position.x >= background.scale.x) { + background.position += glm::vec3(2.f, 0.f, 0.f) * background.scale; + } + if (player.position.x - background.position.x < -background.scale.x) { + background.position -= glm::vec3(2.f, 0.f, 0.f) * background.scale; + } + if (player.position.y - background.position.y >= background.scale.y) { + background.position += glm::vec3(0.f, 2.f, 0.f) * background.scale; + } + if (player.position.y - background.position.y < -background.scale.y) { + background.position -= glm::vec3(0.f, 2.f, 0.f) * background.scale; + } + + glm::vec3 sparse; + + sparse = glm::vec3(1.f, 1.f, 0.f); + background.position += sparse * background.scale; + background.UpdateTransform(delta_time); + graphics.RenderModel(background); + background.position -= sparse * background.scale; + + sparse = glm::vec3(-1.f, 1.f, 0.f); + background.position += sparse * background.scale; + background.UpdateTransform(delta_time); + graphics.RenderModel(background); + background.position -= sparse * background.scale; + + sparse = glm::vec3(1.f, -1.f, 0.f); + background.position += sparse * background.scale; + background.UpdateTransform(delta_time); + graphics.RenderModel(background); + background.position -= sparse * background.scale; + + sparse = glm::vec3(-1.f, -1.f, 0.f); + background.position += sparse * background.scale; + background.UpdateTransform(delta_time); + graphics.RenderModel(background); + background.position -= sparse * background.scale; + + graphics.EndFrame(); } } diff --git a/src/vulkan/coordinate.cpp b/src/vulkan/coordinate.cpp new file mode 100644 index 0000000..f7e969d --- /dev/null +++ b/src/vulkan/coordinate.cpp @@ -0,0 +1,62 @@ +#include "vulkan/coordinate.h" + +namespace veng { +Coord Coord::operator+(const Coord& other) const { + Coord result; + result.seg.x = this->seg.x + other.seg.x; + result.seg.y = this->seg.y + other.seg.y; + result.seg.z = this->seg.z + other.seg.z; + + if (this->pos.x + other.pos.x > border) { + result.seg.x += 1; + result.pos.x += glm::mod(this->pos.x, border); + result.pos.x += glm::mod(other.pos.x, border); + } else { + result.pos.x = this->pos.x + other.pos.x; + } + if (this->pos.y + other.pos.y > border) { + result.seg.y += 1; + result.pos.y += glm::mod(this->pos.y, border); + result.pos.y += glm::mod(other.pos.y, border); + } else { + result.pos.y = this->pos.y + other.pos.y; + } + if (this->pos.z + other.pos.z > border) { + result.seg.z += 1; + result.pos.z += glm::mod(this->pos.z, border); + result.pos.z += glm::mod(other.pos.z, border); + } else { + result.pos.z = this->pos.z + other.pos.z; + } + return result; +} +Coord Coord::operator-(const Coord& other) const { + Coord result; + result.seg.x = this->seg.x - other.seg.x; + result.seg.y = this->seg.y - other.seg.y; + result.seg.z = this->seg.z - other.seg.z; + + if (this->pos.x - other.pos.x < -border) { + result.seg.x -= 1; + result.pos.x -= glm::mod(this->pos.x, border); + result.pos.x -= glm::mod(other.pos.x, border); + } else { + result.pos.x = this->pos.x - other.pos.x; + } + if (this->pos.y - other.pos.y < -border) { + result.seg.y -= 1; + result.pos.y -= glm::mod(this->pos.y, border); + result.pos.y -= glm::mod(other.pos.y, border); + } else { + result.pos.y = this->pos.y - other.pos.y; + } + if (this->pos.z - other.pos.z < -border) { + result.seg.z -= 1; + result.pos.z -= glm::mod(this->pos.z, border); + result.pos.z -= glm::mod(other.pos.z, border); + } else { + result.pos.z = this->pos.z - other.pos.z; + } + return result; +} +} // namespace veng diff --git a/src/vulkan/texture.cpp b/src/vulkan/texture.cpp index 0fe3fab..e20616b 100644 --- a/src/vulkan/texture.cpp +++ b/src/vulkan/texture.cpp @@ -35,6 +35,11 @@ TextureHandle Graphics::CreateTexture(gsl::czstring path) { return CreateTexture({data.data(), data.size()}); } +TextureHandle Graphics::CreateTexture( + std::vector image_file_data) { + return CreateTexture({image_file_data.data(), image_file_data.size()}); +} + TextureHandle Graphics::CreateTexture(gsl::span image_file_data) { glm::ivec2 image_extents; std::int32_t channels;