添加多模型渲染,添加贴图渲染,添加平行光, 暂时不上传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
+176 -108
View File
@@ -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();
}