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