添加多模型渲染,添加贴图渲染,添加平行光, 暂时不上传assets

This commit is contained in:
2026-09-21 14:07:20 +08:00
parent 381b7c0aa6
commit 7d628f8d8a
37 changed files with 9817 additions and 189 deletions
+157
View File
@@ -0,0 +1,157 @@
//
// Created by atdunbg on 2026/9/21.
//
#include <Engine/Renderer/Model.h>
#include <Engine/Renderer/Material.h>
#include <Engine/Vulkan/Device.h>
#include <Engine/Vulkan/MemoryAllocator.h>
#include <Engine/Vulkan/DescriptorManager.h>
#include <Engine/Vulkan/Texture.h>
#include <Engine/Core/Log.h>
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/postprocess.h>
#include <filesystem>
namespace Engine {
Model::Model(Device& device, MemoryAllocator& allocator,
DescriptorManager& descriptorManager,
vk::DescriptorSetLayout textureLayout,
const std::string& path)
: m_Device(device)
, m_Allocator(allocator)
, m_DescriptorManager(descriptorManager)
, m_TextureLayout(textureLayout)
{
// 兜底纹理
m_DefaultTexture = CreateScope<Texture>(
m_Device, m_Allocator, "assets/textures/default.tga");
LoadModel(path);
}
Model::~Model() = default;
void Model::LoadModel(const std::string& path)
{
m_ModelPath = path;
Assimp::Importer importer;
const aiScene* scene = importer.ReadFile(path,
aiProcess_Triangulate |
aiProcess_FlipUVs |
aiProcess_GenSmoothNormals |
aiProcess_JoinIdenticalVertices);
if (!scene || (scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE) || !scene->mRootNode) {
ENGINE_ERROR("Assimp error: {}", importer.GetErrorString());
return;
}
ProcessNode(scene->mRootNode, scene);
ENGINE_INFO("Model loaded: {} ({} meshes, {} textures)",
path, m_Meshes.size(), m_TextureCache.size());
}
void Model::ProcessNode(aiNode* node, const aiScene* scene)
{
for (u32 i = 0; i < node->mNumMeshes; ++i) {
aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
m_Meshes.push_back(ProcessMesh(mesh, scene));
}
for (u32 i = 0; i < node->mNumChildren; ++i) {
ProcessNode(node->mChildren[i], scene);
}
}
Texture* Model::GetOrLoadTexture(const std::string& path)
{
auto it = m_TextureCache.find(path);
if (it != m_TextureCache.end()) {
return it->second.get();
}
// 文件不存在则用兜底纹理
if (!std::filesystem::exists(path)) {
ENGINE_WARN("Texture not found, using default: {}", path);
return m_DefaultTexture.get();
}
auto tex = CreateScope<Texture>(m_Device, m_Allocator, path);
Texture* ptr = tex.get();
m_TextureCache.emplace(path, std::move(tex));
return ptr;
}
Scope<Mesh> Model::ProcessMesh(aiMesh* mesh, const aiScene* scene)
{
std::vector<Vertex> vertices;
std::vector<u32> indices;
vertices.reserve(mesh->mNumVertices);
for (u32 i = 0; i < mesh->mNumVertices; ++i) {
Vertex vertex{};
vertex.position = {
mesh->mVertices[i].x,
mesh->mVertices[i].y,
mesh->mVertices[i].z
};
if (mesh->HasNormals()) {
vertex.normal = {
mesh->mNormals[i].x,
mesh->mNormals[i].y,
mesh->mNormals[i].z
};
}
if (mesh->mTextureCoords[0]) {
vertex.uv = {
mesh->mTextureCoords[0][i].x,
mesh->mTextureCoords[0][i].y
};
}
vertices.push_back(vertex);
}
for (u32 i = 0; i < mesh->mNumFaces; ++i) {
aiFace face = mesh->mFaces[i];
for (u32 j = 0; j < face.mNumIndices; ++j) {
indices.push_back(face.mIndices[j]);
}
}
// 读取材质纹理路径
std::string texturePath;
if (mesh->mMaterialIndex >= 0) {
aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];
aiString path;
if (material->GetTexture(aiTextureType_DIFFUSE, 0, &path) == AI_SUCCESS) {
std::filesystem::path modelDir =
std::filesystem::path(m_ModelPath).parent_path();
texturePath = (modelDir / path.C_Str()).string();
}
}
// 从缓存拿,没有才加载
Texture* tex = texturePath.empty()
? m_DefaultTexture.get()
: GetOrLoadTexture(texturePath);
auto mat = CreateScope<Material>(
m_Device, m_DescriptorManager, m_TextureLayout, tex);
return CreateScope<Mesh>(
m_Device, m_Allocator, vertices, indices, std::move(mat));
}
} // namespace Engine