添加多模型渲染,添加贴图渲染,添加平行光, 暂时不上传assets
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
//
|
||||
// Created by atdunbg on 2026/9/21.
|
||||
//
|
||||
|
||||
#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>
|
||||
|
||||
namespace Engine
|
||||
{
|
||||
Material::Material(Device& device,
|
||||
DescriptorManager& descriptorManager,
|
||||
vk::DescriptorSetLayout layout,
|
||||
Texture* texture)
|
||||
: m_Texture(texture)
|
||||
{
|
||||
m_DescriptorSet = descriptorManager.AllocateDescriptorSet(layout);
|
||||
|
||||
descriptorManager.UpdateTexture(
|
||||
m_DescriptorSet, 0,
|
||||
m_Texture->GetSampler(),
|
||||
m_Texture->GetView());
|
||||
}
|
||||
|
||||
|
||||
Material::~Material() = default;
|
||||
} // namespace Engine
|
||||
@@ -0,0 +1,64 @@
|
||||
//
|
||||
// Created by atdunbg on 2026/9/21.
|
||||
//
|
||||
|
||||
#include <Engine/Renderer/Mesh.h>
|
||||
#include <Engine/Renderer/Material.h>
|
||||
#include <Engine/Vulkan/Device.h>
|
||||
#include <Engine/Vulkan/MemoryAllocator.h>
|
||||
#include <Engine/Vulkan/Buffer.h>
|
||||
#include <Engine/Core/Log.h>
|
||||
|
||||
#include "Engine/Core/Stats.h"
|
||||
|
||||
namespace Engine
|
||||
{
|
||||
Mesh::Mesh(Device& device, MemoryAllocator& allocator,
|
||||
const std::vector<Vertex>& vertices,
|
||||
const std::vector<u32>& indices,
|
||||
Scope<Material> material)
|
||||
: m_Material(std::move(material))
|
||||
{
|
||||
if (vertices.empty() || indices.empty())
|
||||
{
|
||||
ENGINE_ERROR("Mesh: empty vertices or indices");
|
||||
return;
|
||||
}
|
||||
|
||||
u64 vbSize = sizeof(Vertex) * vertices.size();
|
||||
m_VertexBuffer = CreateScope<Buffer>(
|
||||
device, allocator, vbSize,
|
||||
vk::BufferUsageFlagBits::eVertexBuffer,
|
||||
vk::MemoryPropertyFlagBits::eHostVisible |
|
||||
vk::MemoryPropertyFlagBits::eHostCoherent);
|
||||
m_VertexBuffer->Upload(vertices.data(), vbSize);
|
||||
|
||||
u64 ibSize = sizeof(u32) * indices.size();
|
||||
m_IndexBuffer = CreateScope<Buffer>(
|
||||
device, allocator, ibSize,
|
||||
vk::BufferUsageFlagBits::eIndexBuffer,
|
||||
vk::MemoryPropertyFlagBits::eHostVisible |
|
||||
vk::MemoryPropertyFlagBits::eHostCoherent);
|
||||
m_IndexBuffer->Upload(indices.data(), ibSize);
|
||||
|
||||
m_IndexCount = static_cast<u32>(indices.size());
|
||||
|
||||
ENGINE_INFO("Mesh created: {} vertices, {} indices", vertices.size(), indices.size());
|
||||
|
||||
m_VertexBytes = sizeof(Vertex) * vertices.size();
|
||||
m_IndexBytes = sizeof(u32) * indices.size();
|
||||
STATS.AddMesh(m_VertexBytes, m_IndexBytes);
|
||||
}
|
||||
|
||||
Mesh::~Mesh()
|
||||
{
|
||||
STATS.RemoveMesh(m_VertexBytes, m_IndexBytes);
|
||||
}
|
||||
|
||||
void Mesh::Draw(vk::CommandBuffer cmd) const
|
||||
{
|
||||
cmd.bindVertexBuffers(0, m_VertexBuffer->Get(), {0});
|
||||
cmd.bindIndexBuffer(m_IndexBuffer->Get(), 0, vk::IndexType::eUint32);
|
||||
cmd.drawIndexed(m_IndexCount, 1, 0, 0, 0);
|
||||
}
|
||||
} // namespace Engine
|
||||
@@ -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
|
||||
+176
-108
@@ -3,6 +3,7 @@
|
||||
//
|
||||
|
||||
#include <Engine/Renderer/Renderer.h>
|
||||
#include <Engine/Renderer/Material.h>
|
||||
#include <Engine/Vulkan/Device.h>
|
||||
#include <Engine/Vulkan/MemoryAllocator.h>
|
||||
#include <Engine/Vulkan/DescriptorManager.h>
|
||||
@@ -10,7 +11,6 @@
|
||||
#include <Engine/Vulkan/Swapchain.h>
|
||||
#include <Engine/Vulkan/CommandManager.h>
|
||||
#include <Engine/Vulkan/SyncManager.h>
|
||||
#include <Engine/Vulkan/Buffer.h>
|
||||
#include <Engine/Vulkan/UniformBuffer.h>
|
||||
#include <Engine/Core/Window.h>
|
||||
#include <Engine/Core/Log.h>
|
||||
@@ -22,21 +22,25 @@
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
|
||||
#include "Engine/Core/Stats.h"
|
||||
#include "GLFW/glfw3.h"
|
||||
|
||||
namespace Engine
|
||||
{
|
||||
// 顶点结构:位置 + 颜色
|
||||
struct Vertex
|
||||
{
|
||||
float position[3];
|
||||
float color[3];
|
||||
|
||||
struct Light {
|
||||
glm::vec4 direction;
|
||||
glm::vec4 color; // rgb = 颜色,a = 强度
|
||||
};
|
||||
|
||||
// Uniform Buffer 结构
|
||||
struct UniformBufferObject
|
||||
{
|
||||
glm::mat4 mvp;
|
||||
struct UniformBufferObject {
|
||||
glm::mat4 view;
|
||||
glm::mat4 proj;
|
||||
glm::vec4 ambientColor;
|
||||
Light lights[4];
|
||||
};
|
||||
|
||||
|
||||
Renderer::Renderer(Window& window)
|
||||
: m_Window(window)
|
||||
{
|
||||
@@ -49,24 +53,37 @@ namespace Engine
|
||||
// 3. DescriptorManager
|
||||
m_DescriptorManager = CreateScope<DescriptorManager>(*m_Device);
|
||||
|
||||
// 4. DescriptorSetLayout(一个 uniform buffer binding)
|
||||
m_DescriptorSetLayout = m_DescriptorManager->CreateUniformBufferLayout(0);
|
||||
// 4. Set 0: UBO
|
||||
std::vector<DescriptorBinding> uboBindings = {
|
||||
{0, vk::DescriptorType::eUniformBuffer, vk::ShaderStageFlagBits::eVertex | vk::ShaderStageFlagBits::eFragment },
|
||||
};
|
||||
m_UBOSetLayout = m_DescriptorManager->CreateLayout(uboBindings);
|
||||
|
||||
// 5. PipelineLayout(shader 绑定描述符时用)
|
||||
m_PipelineLayout = m_DescriptorManager->CreatePipelineLayout(m_DescriptorSetLayout);
|
||||
// 5. Set 1: texture
|
||||
std::vector<DescriptorBinding> texBindings = {
|
||||
{0, vk::DescriptorType::eCombinedImageSampler, vk::ShaderStageFlagBits::eFragment},
|
||||
};
|
||||
m_TextureSetLayout = m_DescriptorManager->CreateLayout(texBindings);
|
||||
|
||||
// 6. ShaderManager,编译 shader 时传入描述符布局
|
||||
// 6. PipelineLayout:两个 set
|
||||
std::vector<vk::DescriptorSetLayout> layouts = {
|
||||
m_UBOSetLayout, m_TextureSetLayout
|
||||
};
|
||||
m_PipelineLayout = m_DescriptorManager->CreatePipelineLayout(
|
||||
layouts, sizeof(glm::mat4));
|
||||
|
||||
// 7. ShaderManager
|
||||
m_ShaderManager = CreateScope<ShaderManager>(*m_Device);
|
||||
|
||||
std::string shaderDir = "shaders/";
|
||||
auto vert = m_ShaderManager->CreateFromFile(
|
||||
shaderDir + "simple_shader.vert.spv",
|
||||
vk::ShaderStageFlagBits::eVertex,
|
||||
m_DescriptorSetLayout);
|
||||
layouts, sizeof(glm::mat4));
|
||||
auto frag = m_ShaderManager->CreateFromFile(
|
||||
shaderDir + "simple_shader.frag.spv",
|
||||
vk::ShaderStageFlagBits::eFragment,
|
||||
m_DescriptorSetLayout);
|
||||
layouts, sizeof(glm::mat4));
|
||||
|
||||
m_VertShader = vert.Handle;
|
||||
m_FragShader = frag.Handle;
|
||||
@@ -76,96 +93,46 @@ namespace Engine
|
||||
ENGINE_FATAL("Failed to create shader objects");
|
||||
}
|
||||
|
||||
// 7. Swapchain
|
||||
// 8. Swapchain
|
||||
m_Swapchain = CreateScope<Swapchain>(*m_Device, *m_Allocator, window);
|
||||
m_Extent = m_Swapchain->GetExtent();
|
||||
m_Format = m_Swapchain->GetFormat();
|
||||
|
||||
// 8. SyncManager
|
||||
// 9. SyncManager
|
||||
m_SyncManager = CreateScope<SyncManager>(*m_Device, kMaxFramesInFlight, m_Swapchain->GetImageCount());
|
||||
|
||||
// 9. CommandManager
|
||||
// 10. CommandManager
|
||||
m_CommandManager = CreateScope<CommandManager>(*m_Device);
|
||||
|
||||
// 10. 顶点缓冲
|
||||
std::vector<Vertex> vertices = {
|
||||
// 前面 (-Z)
|
||||
{{-0.5f, -0.5f, 0.5f}, {1.0f, 0.0f, 0.0f}},
|
||||
{{ 0.5f, -0.5f, 0.5f}, {1.0f, 0.0f, 0.0f}},
|
||||
{{ 0.5f, 0.5f, 0.5f}, {1.0f, 0.0f, 0.0f}},
|
||||
{{-0.5f, 0.5f, 0.5f}, {1.0f, 0.0f, 0.0f}},
|
||||
// 后面 (+Z)
|
||||
{{-0.5f, -0.5f, -0.5f}, {0.0f, 1.0f, 0.0f}},
|
||||
{{-0.5f, 0.5f, -0.5f}, {0.0f, 1.0f, 0.0f}},
|
||||
{{ 0.5f, 0.5f, -0.5f}, {0.0f, 1.0f, 0.0f}},
|
||||
{{ 0.5f, -0.5f, -0.5f}, {0.0f, 1.0f, 0.0f}},
|
||||
// 左面 (-X)
|
||||
{{-0.5f, -0.5f, -0.5f}, {0.0f, 0.0f, 1.0f}},
|
||||
{{-0.5f, -0.5f, 0.5f}, {0.0f, 0.0f, 1.0f}},
|
||||
{{-0.5f, 0.5f, 0.5f}, {0.0f, 0.0f, 1.0f}},
|
||||
{{-0.5f, 0.5f, -0.5f}, {0.0f, 0.0f, 1.0f}},
|
||||
// 右面 (+X)
|
||||
{{ 0.5f, -0.5f, 0.5f}, {1.0f, 1.0f, 0.0f}},
|
||||
{{ 0.5f, -0.5f, -0.5f}, {1.0f, 1.0f, 0.0f}},
|
||||
{{ 0.5f, 0.5f, -0.5f}, {1.0f, 1.0f, 0.0f}},
|
||||
{{ 0.5f, 0.5f, 0.5f}, {1.0f, 1.0f, 0.0f}},
|
||||
// 上面 (+Y)
|
||||
{{-0.5f, 0.5f, 0.5f}, {1.0f, 0.0f, 1.0f}},
|
||||
{{ 0.5f, 0.5f, 0.5f}, {1.0f, 0.0f, 1.0f}},
|
||||
{{ 0.5f, 0.5f, -0.5f}, {1.0f, 0.0f, 1.0f}},
|
||||
{{-0.5f, 0.5f, -0.5f}, {1.0f, 0.0f, 1.0f}},
|
||||
// 下面 (-Y)
|
||||
{{-0.5f, -0.5f, -0.5f}, {0.0f, 1.0f, 1.0f}},
|
||||
{{ 0.5f, -0.5f, -0.5f}, {0.0f, 1.0f, 1.0f}},
|
||||
{{ 0.5f, -0.5f, 0.5f}, {0.0f, 1.0f, 1.0f}},
|
||||
{{-0.5f, -0.5f, 0.5f}, {0.0f, 1.0f, 1.0f}},
|
||||
};
|
||||
u64 bufferSize = sizeof(Vertex) * vertices.size();
|
||||
|
||||
|
||||
m_VertexBuffer = CreateScope<Buffer>(
|
||||
*m_Device, *m_Allocator,
|
||||
bufferSize,
|
||||
vk::BufferUsageFlagBits::eVertexBuffer,
|
||||
vk::MemoryPropertyFlagBits::eHostVisible |
|
||||
vk::MemoryPropertyFlagBits::eHostCoherent);
|
||||
m_VertexBuffer->Upload(vertices.data(), bufferSize);
|
||||
|
||||
|
||||
// 索引缓冲:两个三角形组成一个四边形
|
||||
std::vector<u32> indices = {
|
||||
0, 1, 2, 2, 3, 0, // 前面
|
||||
4, 5, 6, 6, 7, 4, // 后面
|
||||
8, 9,10,10,11, 8, // 左面
|
||||
12,13,14,14,15,12, // 右面
|
||||
16,17,18,18,19,16, // 上面
|
||||
20,21,22,22,23,20, // 下面
|
||||
};
|
||||
u64 indexBufferSize = sizeof(u32) * indices.size();
|
||||
|
||||
|
||||
m_IndexBuffer = CreateScope<Buffer>(
|
||||
*m_Device, *m_Allocator,
|
||||
indexBufferSize,
|
||||
vk::BufferUsageFlagBits::eIndexBuffer,
|
||||
vk::MemoryPropertyFlagBits::eHostVisible |
|
||||
vk::MemoryPropertyFlagBits::eHostCoherent);
|
||||
m_IndexBuffer->Upload(indices.data(), indexBufferSize);
|
||||
|
||||
|
||||
// 11. Uniform Buffer
|
||||
m_UniformBuffer = CreateScope<UniformBuffer>(
|
||||
*m_Device, *m_Allocator, sizeof(UniformBufferObject));
|
||||
|
||||
// 12. DescriptorSet + 绑定 UniformBuffer
|
||||
m_DescriptorSet = m_DescriptorManager->AllocateDescriptorSet(m_DescriptorSetLayout);
|
||||
// 12. UBO DescriptorSet
|
||||
m_UBODescriptorSet = m_DescriptorManager->AllocateDescriptorSet(m_UBOSetLayout);
|
||||
m_DescriptorManager->UpdateUniformBuffer(
|
||||
m_DescriptorSet, 0, m_UniformBuffer->Get(), m_UniformBuffer->GetSize());
|
||||
m_UBODescriptorSet, 0, m_UniformBuffer->Get(), m_UniformBuffer->GetSize());
|
||||
|
||||
// 13. Model(模型自己加载纹理)
|
||||
m_Model = CreateScope<Model>(
|
||||
*m_Device, *m_Allocator, *m_DescriptorManager,
|
||||
m_TextureSetLayout,
|
||||
"assets/models/backpack/backpack.obj");
|
||||
|
||||
// 14. 创建几个物体,摆一排
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
Object obj;
|
||||
obj.model = m_Model.get();
|
||||
obj.transform = glm::translate(
|
||||
glm::mat4(1.0f),
|
||||
glm::vec3((i - 1) * 1.5f, 0.0f, 0.0f));
|
||||
m_Objects.push_back(obj);
|
||||
}
|
||||
|
||||
// 13. Debug: 记录开始时间,用于旋转
|
||||
m_StartTime = std::chrono::steady_clock::now();
|
||||
|
||||
ENGINE_INFO("Renderer initialized");
|
||||
|
||||
}
|
||||
|
||||
Renderer::~Renderer()
|
||||
@@ -182,36 +149,110 @@ namespace Engine
|
||||
}
|
||||
|
||||
m_Device->GetDevice().destroyPipelineLayout(m_PipelineLayout);
|
||||
m_Device->GetDevice().destroyDescriptorSetLayout(m_DescriptorSetLayout);
|
||||
|
||||
m_Device->GetDevice().destroyDescriptorSetLayout(m_UBOSetLayout);
|
||||
m_Device->GetDevice().destroyDescriptorSetLayout(m_TextureSetLayout);
|
||||
}
|
||||
|
||||
|
||||
void Renderer::Render()
|
||||
{
|
||||
|
||||
if (m_Window.WasResized())
|
||||
{
|
||||
m_Window.ResetResizedFlag();
|
||||
|
||||
m_Device->GetDevice().waitIdle();
|
||||
|
||||
m_Swapchain->Recreate(m_Window);
|
||||
m_Extent = m_Swapchain->GetExtent();
|
||||
m_SyncManager = CreateScope<SyncManager>(
|
||||
*m_Device, kMaxFramesInFlight, m_Swapchain->GetImageCount());
|
||||
}
|
||||
|
||||
u32 frameIndex = m_CurrentFrame;
|
||||
const auto& vkDevice = m_Device->GetDevice();
|
||||
|
||||
// 1. 更新 MVP 矩阵
|
||||
auto currentTime = std::chrono::steady_clock::now();
|
||||
float time = std::chrono::duration<float, std::chrono::seconds::period>(
|
||||
currentTime - m_StartTime).count();
|
||||
auto now = std::chrono::steady_clock::now();
|
||||
float currentTime = std::chrono::duration<float>(now - m_StartTime).count();
|
||||
m_DeltaTime = currentTime - m_LastFrameTime;
|
||||
m_LastFrameTime = currentTime;
|
||||
|
||||
auto model = glm::rotate(glm::mat4(1.0f),
|
||||
time * glm::radians(90.0f),
|
||||
glm::vec3(1.0f, 1.0f, 1.0f));
|
||||
// 更新每个物体的 transform
|
||||
for (size_t i = 0; i < m_Objects.size(); ++i) {
|
||||
float angle = currentTime * glm::radians(60.0f) + i * 0.7f;
|
||||
|
||||
auto view = glm::lookAt(glm::vec3(0.0f, 0.0f, 2.0f),
|
||||
glm::vec3(0.0f, 0.0f, 0.0f),
|
||||
glm::vec3(0.0f, 1.0f, 0.0f));
|
||||
glm::mat4 t = glm::translate(
|
||||
glm::mat4(1.0f),
|
||||
glm::vec3((static_cast<float>(i) - 1.0f) * 1.5f, 0.0f, 0.0f));
|
||||
glm::mat4 r = glm::rotate(glm::mat4(1.0f), angle, glm::vec3(0.0f, 1.0f, 0.0f));
|
||||
|
||||
float aspect = static_cast<float>(m_Extent.width) /
|
||||
static_cast<float>(m_Extent.height);
|
||||
m_Objects[i].transform = t * r;
|
||||
}
|
||||
|
||||
auto proj = glm::perspective(glm::radians(45.0f), aspect, 0.1f, 10.0f);
|
||||
// 鼠标控制方向
|
||||
/*
|
||||
float mouseDX = 0, mouseDY = 0;
|
||||
m_Window.GetMouseDelta(mouseDX, mouseDY);
|
||||
if (mouseDX != 0 || mouseDY != 0)
|
||||
{
|
||||
m_CameraYaw += mouseDX * m_MouseSensitivity;
|
||||
m_CameraPitch -= mouseDY * m_MouseSensitivity;
|
||||
m_CameraPitch = glm::clamp(m_CameraPitch, -89.0f, 89.0f);
|
||||
}
|
||||
*/
|
||||
|
||||
// 相机前方向量
|
||||
glm::vec3 forward;
|
||||
forward.x = cosf(glm::radians(m_CameraYaw)) * cos(glm::radians(m_CameraPitch));
|
||||
forward.y = sinf(glm::radians(m_CameraPitch));
|
||||
forward.z = sinf(glm::radians(m_CameraYaw)) * cos(glm::radians(m_CameraPitch));
|
||||
forward = glm::normalize(forward);
|
||||
|
||||
glm::vec3 right = glm::normalize(glm::cross(forward, glm::vec3(0, 1, 0)));
|
||||
glm::vec3 up = glm::normalize(glm::cross(right, forward));
|
||||
|
||||
// WASD 移动
|
||||
float speed = m_CameraSpeed * m_DeltaTime;
|
||||
if (m_Window.IsKeyPressed(GLFW_KEY_W)) m_CameraPos += forward * speed;
|
||||
if (m_Window.IsKeyPressed(GLFW_KEY_S)) m_CameraPos -= forward * speed;
|
||||
if (m_Window.IsKeyPressed(GLFW_KEY_A)) m_CameraPos -= right * speed;
|
||||
if (m_Window.IsKeyPressed(GLFW_KEY_D)) m_CameraPos += right * speed;
|
||||
if (m_Window.IsKeyPressed(GLFW_KEY_SPACE)) m_CameraPos.y += speed;
|
||||
if (m_Window.IsKeyPressed(GLFW_KEY_LEFT_SHIFT)) m_CameraPos.y -= speed;
|
||||
|
||||
|
||||
auto view = glm::lookAt(m_CameraPos,
|
||||
m_CameraPos + forward,
|
||||
up);
|
||||
|
||||
float aspect = static_cast<f32>(m_Extent.width) /
|
||||
static_cast<f32>(m_Extent.height);
|
||||
|
||||
auto proj = glm::perspective(glm::radians(45.0f), aspect, 0.1f, 100.0f);
|
||||
proj[1][1] *= -1.0f; // Vulkan Y 翻转
|
||||
|
||||
UniformBufferObject ubo{};
|
||||
ubo.mvp = proj * view * model;
|
||||
ubo.view = view;
|
||||
ubo.proj = proj;
|
||||
|
||||
ubo.ambientColor = glm::vec4(0.15f, 0.15f, 0.2f, 0.0f);
|
||||
|
||||
// 主光:暖色,从左上方照下
|
||||
ubo.lights[0].direction = glm::vec4(glm::normalize(glm::vec3(-0.5f, -1.0f, -0.3f)), 0.0f);
|
||||
ubo.lights[0].color = glm::vec4(1.0f, 0.95f, 0.9f, 1.0f);
|
||||
|
||||
// 补光:冷色,从右下方照上
|
||||
ubo.lights[1].direction = glm::vec4(glm::normalize(glm::vec3(0.5f, -0.5f, 0.3f)), 0.0f);
|
||||
ubo.lights[1].color = glm::vec4(0.3f, 0.5f, 1.0f, 0.8f);
|
||||
|
||||
// 未使用:强度 0
|
||||
ubo.lights[2].direction = glm::vec4(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
ubo.lights[2].color = glm::vec4(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
|
||||
ubo.lights[3].direction = glm::vec4(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
ubo.lights[3].color = glm::vec4(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
|
||||
m_UniformBuffer->Update(&ubo, sizeof(ubo));
|
||||
|
||||
@@ -318,6 +359,9 @@ namespace Engine
|
||||
{
|
||||
m_Swapchain->Recreate(m_Window);
|
||||
}
|
||||
|
||||
if (m_Window.IsKeyPressed(GLFW_KEY_F1))
|
||||
STATS.PrintComparison();
|
||||
}
|
||||
|
||||
void Renderer::RecordCommands(vk::CommandBuffer cmd, u32 imageIndex)
|
||||
@@ -359,8 +403,8 @@ namespace Engine
|
||||
|
||||
// 绑定描述符集
|
||||
cmd.bindDescriptorSets(vk::PipelineBindPoint::eGraphics,
|
||||
m_PipelineLayout, 0,
|
||||
m_DescriptorSet, {});
|
||||
m_PipelineLayout, 0,
|
||||
m_UBODescriptorSet, {});
|
||||
|
||||
// ===== 动态状态 =====
|
||||
cmd.setRasterizerDiscardEnable(VK_FALSE);
|
||||
@@ -379,22 +423,30 @@ namespace Engine
|
||||
cmd.setPrimitiveRestartEnable(VK_FALSE);
|
||||
|
||||
// 顶点输入
|
||||
/*
|
||||
vk::VertexInputBindingDescription2EXT binding;
|
||||
binding.setBinding(0)
|
||||
.setStride(sizeof(f32) * 6)
|
||||
.setStride(sizeof(f32) * 5)
|
||||
.setInputRate(vk::VertexInputRate::eVertex)
|
||||
.setDivisor(1);
|
||||
|
||||
std::array<vk::VertexInputAttributeDescription2EXT, 2> attributes;
|
||||
|
||||
// location 0: position
|
||||
attributes[0].setLocation(0)
|
||||
.setBinding(0)
|
||||
.setFormat(vk::Format::eR32G32B32Sfloat)
|
||||
.setOffset(0);
|
||||
|
||||
// location 1: uv
|
||||
attributes[1].setLocation(1)
|
||||
.setBinding(0)
|
||||
.setFormat(vk::Format::eR32G32B32Sfloat)
|
||||
.setFormat(vk::Format::eR32G32Sfloat)
|
||||
.setOffset(sizeof(f32) * 3);
|
||||
*/
|
||||
|
||||
auto binding = Vertex::GetBindingDescription();
|
||||
auto attributes = Vertex::GetAttributeDescriptions();
|
||||
cmd.setVertexInputEXT(binding, attributes);
|
||||
|
||||
cmd.setRasterizationSamplesEXT(vk::SampleCountFlagBits::e1);
|
||||
@@ -431,11 +483,27 @@ namespace Engine
|
||||
vk::ColorComponentFlagBits::eA;
|
||||
cmd.setColorWriteMaskEXT(0, colorWriteMask);
|
||||
|
||||
|
||||
// 绑定顶点缓冲并绘制
|
||||
for (auto& obj : m_Objects) {
|
||||
cmd.pushConstants(m_PipelineLayout,
|
||||
vk::ShaderStageFlagBits::eVertex,
|
||||
0, sizeof(glm::mat4), &obj.transform);
|
||||
|
||||
for (auto& mesh : obj.model->GetMeshes()) {
|
||||
cmd.bindDescriptorSets(vk::PipelineBindPoint::eGraphics,
|
||||
m_PipelineLayout, 1,
|
||||
mesh->GetMaterial()->GetDescriptorSet(), {});
|
||||
mesh->Draw(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
cmd.bindVertexBuffers(0, m_VertexBuffer->Get(), {0});
|
||||
cmd.bindIndexBuffer(m_IndexBuffer->Get(), 0, vk::IndexType::eUint32);
|
||||
// cmd.draw(3, 1, 0, 0);
|
||||
cmd.drawIndexed(36, 1, 0, 0, 0);
|
||||
*/
|
||||
|
||||
cmd.endRendering();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user