Compare commits

..

2 Commits

Author SHA1 Message Date
0ea46b288d 모델 로더 완성 2025-05-19 03:28:51 +09:00
3a9dbcb470 FBX파일 읽기 로직 완성 2025-05-18 19:23:30 +09:00
13 changed files with 172 additions and 48 deletions

View File

@@ -74,4 +74,6 @@ 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/player.fbx" 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")

BIN
assets/copying-stones.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 557 KiB

Binary file not shown.

BIN
assets/wall.fbx Normal file

Binary file not shown.

View File

@@ -0,0 +1,9 @@
#pragma once
#include "vulkan/texture_handle.h"
namespace veng {
struct Material {
TextureHandle texture;
};
} // namespace veng

View File

@@ -0,0 +1,27 @@
#pragma once
#include <vector>
#include "material.h"
#include "vulkan/graphics.h"
#include "vulkan/vertex.h"
#include <memory>
namespace veng {
struct Model {
Model(std::shared_ptr<class Graphics> graphics);
~Model();
std::vector<veng::Vertex> vertices;
veng::BufferHandle vertex_buffer;
std::vector<std::uint32_t> indices;
veng::BufferHandle index_buffer;
glm::mat4 transform;
Material material;
private:
std::weak_ptr<class Graphics> graphics_;
};
} // namespace veng

View File

@@ -1,7 +1,6 @@
#pragma once
struct GLFWmonitor;
struct GLFWwindow;
#include <GLFW/glfw3.h>
namespace veng {
class Window {
@@ -14,6 +13,8 @@ class Window {
bool ShouldClose() const;
GLFWwindow* GetHandle() const;
GLFWkeyfun SetKeyCallback(GLFWkeyfun key_callback);
bool TryMoveToMonitor(std::uint16_t monitor_number);
private:

View File

@@ -33,12 +33,14 @@ class Graphics final {
void RenderBuffer(BufferHandle handle, std::uint32_t vertex_count);
void RenderIndexedBuffer(BufferHandle vertex_buffer,
BufferHandle index_buffer, std::uint32_t count);
void RenderModel(struct Model& model);
void EndFrame();
BufferHandle CreateVertexBuffer(gsl::span<Vertex> vertices);
BufferHandle CreateIndexBuffer(gsl::span<std::uint32_t> indices);
void DestroyBuffer(BufferHandle handle);
TextureHandle CreateTexture(gsl::czstring path);
TextureHandle CreateTexture(gsl::span<std::uint8_t> image_file_data);
void DestroyTexture(TextureHandle handle);
private:

View File

@@ -0,0 +1,17 @@
#include "asset/object/model.h"
namespace veng {
Model::Model(std::shared_ptr<Graphics> graphics) { graphics_ = graphics; }
Model::~Model() {
auto graphics = graphics_.lock();
if (!graphics) return;
graphics->DestroyTexture(material.texture);
graphics->DestroyBuffer(vertex_buffer);
graphics->DestroyBuffer(index_buffer);
}
} // namespace veng

View File

@@ -1,7 +1,8 @@
#include "glfw/glfw_window.h"
#include <GLFW/glfw3.h>
#include "glfw/glfw_monitor.h"
#include "glfw/glfw_window.h"
#include "precomp.h"
namespace veng {
@@ -32,6 +33,10 @@ bool Window::ShouldClose() const { return glfwWindowShouldClose(window_); }
GLFWwindow* Window::GetHandle() const { return window_; }
GLFWkeyfun Window::SetKeyCallback(GLFWkeyfun key_callback) {
return glfwSetKeyCallback(window_, key_callback);
}
bool Window::TryMoveToMonitor(std::uint16_t monitor_number) {
gsl::span<GLFWmonitor*> monitors = veng::GetMonitors();

View File

@@ -3,8 +3,10 @@
#include <glm/gtc/matrix_transform.hpp>
#include <iostream>
#include "asset/object/model.h"
#include "assimp/Importer.hpp"
#include "assimp/postprocess.h"
#include "assimp/scene.h"
#include "glfw/glfw_initialization.h"
#include "glfw/glfw_monitor.h"
#include "glfw/glfw_window.h"
@@ -17,42 +19,83 @@ std::int32_t main(std::int32_t argc, gsl::zstring* argv) {
veng::Window window("Vulkan Engine", {800, 600});
window.TryMoveToMonitor(0);
veng::Graphics graphics(&window);
std::shared_ptr<veng::Graphics> graphics =
std::make_shared<veng::Graphics>(&window);
Assimp::Importer assetImporter;
const struct aiScene* scene = assetImporter.ReadFile(
"assets/player.fbx", aiProcess_CalcTangentSpace | aiProcess_Triangulate |
aiProcess_JoinIdenticalVertices | aiProcess_SortByPType);
"assets/wall.fbx", aiProcess_CalcTangentSpace | aiProcess_Triangulate |
aiProcess_JoinIdenticalVertices |
aiProcess_SortByPType | aiProcess_FlipUVs);
if (nullptr == scene) {
if (scene == nullptr || !scene->HasMeshes()) {
spdlog::error(assetImporter.GetErrorString());
return false;
}
std::array<veng::Vertex, 4> vertices = {
veng::Vertex{{-.5f, -.5f, 0.f}, {0.f, 1.f}},
veng::Vertex{{.5f, -.5f, 0.f}, {1.f, 1.f}},
veng::Vertex{{-.5f, .5f, 0.f}, {0.f, 0.f}},
veng::Vertex{{.5f, .5f, 0.f}, {1.f, 0.f}}};
veng::BufferHandle buffer = graphics.CreateVertexBuffer(vertices);
veng::Model player(graphics);
std::array<std::uint32_t, 6> indices = {0, 3, 2, 0, 1, 3};
veng::BufferHandle index_buffer = graphics.CreateIndexBuffer(indices);
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);
glm::mat4 rotation = glm::rotate(glm::mat4(1.0f), glm::radians(45.f),
glm::vec3(0.f, 1.f, 0.f));
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);
glm::mat4 rotation2 =
glm::rotate(glm::mat4(1.0f), glm::radians(0.f), glm::vec3(0.f, 0.f, 1.f));
aiString string;
if (scene->mMaterials[scene->mMeshes[0]->mMaterialIndex]->GetTexture(
aiTextureType_DIFFUSE, 0, &string) != AI_SUCCESS) {
std::cout << "No texture" << std::endl;
}
glm::mat4 view = glm::translate(glm::mat4(1.f), glm::vec3(0.f, 0.f, -2.f));
glm::mat4 projection =
glm::perspective(glm::radians(150.f), 800.f / 600.f, 0.1f, 100.f);
graphics.SetViewProjection(view, projection);
veng::Model wall(graphics);
veng::TextureHandle texture =
graphics.CreateTexture("assets/paving-stones.jpg");
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));
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);
// 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");
double last_time = glfwGetTime();
@@ -61,37 +104,44 @@ std::int32_t main(std::int32_t argc, gsl::zstring* argv) {
glfwPollEvents();
glm::ivec2 current_window_size = window.GetFramebufferSize();
if (current_window_size != window_size && current_window_size.x != 0 && current_window_size.y != 0) {
if (current_window_size != window_size && current_window_size.x != 0 &&
current_window_size.y != 0) {
window_size = current_window_size;
projection = glm::perspective(
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,
-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(
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);
}
if (graphics.BeginFrame()) {
// std::cout << glfwGetKey(window.GetHandle(), GLFW_KEY_W) << std::endl;
if (graphics->BeginFrame()) {
double current_time = glfwGetTime();
float delta_time = static_cast<float>(current_time - last_time);
last_time = current_time;
graphics.SetTexture(texture);
rotation2 = glm::rotate(rotation2, delta_time * glm::radians(-360.f),
glm::vec3(0.f, 0.f, 1.f));
graphics.SetModelMatrix(rotation2);
graphics.RenderIndexedBuffer(buffer, index_buffer, indices.size());
rotation = glm::rotate(rotation, delta_time * glm::radians(360.f),
glm::vec3(0.f, 0.f, 1.f));
graphics.SetModelMatrix(rotation);
graphics.RenderIndexedBuffer(buffer, index_buffer, indices.size());
player.transform =
glm::rotate(player.transform, delta_time * glm::radians(60.f),
glm::vec3(0.f, 0.f, 1.f));
graphics->RenderModel(player);
graphics.EndFrame();
wall.transform =
glm::rotate(wall.transform, delta_time * glm::radians(-60.f),
glm::vec3(0.f, 1.f, 0.f));
graphics->RenderModel(wall);
graphics->EndFrame();
}
}
graphics.DestroyTexture(texture);
graphics.DestroyBuffer(buffer);
graphics.DestroyBuffer(index_buffer);
return EXIT_SUCCESS;
}

View File

@@ -1,5 +1,6 @@
#include <vulkan/vulkan.h>
#include "asset/object/model.h"
#include "precomp.h"
#include "vulkan/graphics.h"
#include "vulkan/uniform_transformations.h"
@@ -142,8 +143,8 @@ void Graphics::SetModelMatrix(glm::mat4 model) {
void Graphics::SetViewProjection(glm::mat4 view, glm::mat4 projection) {
UniformTransformations transformations{view, projection};
for (Frame& frame : frames_)
std::memcpy(frame.uniform_buffer_location,
&transformations, sizeof(UniformTransformations));
std::memcpy(frame.uniform_buffer_location, &transformations,
sizeof(UniformTransformations));
}
void Graphics::RenderBuffer(BufferHandle handle, std::uint32_t vertex_count) {
@@ -170,6 +171,12 @@ void Graphics::RenderIndexedBuffer(BufferHandle vertex_buffer,
vkCmdDrawIndexed(frames_[current_frame_].command_buffer, count, 1, 0, 0, 0);
SetModelMatrix(glm::mat4(1.f));
}
void Graphics::RenderModel(Model& model) {
SetTexture(model.material.texture);
SetModelMatrix(model.transform);
RenderIndexedBuffer(model.vertex_buffer, model.index_buffer,
model.indices.size());
}
VkCommandBuffer Graphics::BeginTransientCommandBuffer() {
VkCommandBufferAllocateInfo allocation_info = {};

View File

@@ -31,9 +31,13 @@ void Graphics::CreateTextureSampler() {
}
TextureHandle Graphics::CreateTexture(gsl::czstring path) {
std::vector<std::uint8_t> data = ReadFile(path);
return CreateTexture({data.data(), data.size()});
}
TextureHandle Graphics::CreateTexture(gsl::span<std::uint8_t> image_file_data) {
glm::ivec2 image_extents;
std::int32_t channels;
std::vector<std::uint8_t> image_file_data = ReadFile(path);
stbi_uc* pixel_data = stbi_load_from_memory(
image_file_data.data(), image_file_data.size(), &image_extents.x,
&image_extents.y, &channels, STBI_rgb_alpha);