9 VulkanSkeletalMeshRenderer::VulkanSkeletalMeshRenderer(VulkanRenderer* renderer, VulkanLogicalDevice* device, VulkanDescriptorPool* descriptorPool)
11 this->renderer_ = renderer;
12 this->device_ = device;
13 this->descriptorPool_ = descriptorPool;
14 this->commandPool_ = renderer->GetGraphicsCommandPool();
15 this->allocator_ = renderer->GetVmaAllocator();
17 skeletalMeshPipeline_ = eastl::unique_ptr<VulkanPipeline>(
new VulkanPipeline(device, renderer));
19 skeletalMeshPipeline_->LoadShader(VulkanPipeline::SHADER_TYPE::VERTEX_SHADER,
"SkeletonMesh.vert.spv");
21 skeletalMeshPipeline_->LoadShader(VulkanPipeline::SHADER_TYPE::FRAGMENT_SHADER,
"Mesh.frag.spv");
23 skeletalMeshPipeline_->AddVertexInputBindingDescription(0, static_cast<uint32_t>(
sizeof(
Vertex)), VK_VERTEX_INPUT_RATE_VERTEX);
24 skeletalMeshPipeline_->AddVertexInputAttributeDescription(0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(
Vertex, position));
25 skeletalMeshPipeline_->AddVertexInputAttributeDescription(1, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(
Vertex, normal));
26 skeletalMeshPipeline_->AddVertexInputAttributeDescription(2, 0, VK_FORMAT_R32G32_SFLOAT, offsetof(
Vertex, texCoords));
27 skeletalMeshPipeline_->AddVertexInputAttributeDescription(3, 0, VK_FORMAT_R32G32B32A32_SFLOAT, offsetof(
Vertex, boneWeights));
28 skeletalMeshPipeline_->AddVertexInputAttributeDescription(4, 0, VK_FORMAT_R32G32B32A32_SINT, offsetof(
Vertex, boneIds));
31 skeletalMeshPipeline_->CreateDescriptorSet();
32 skeletalMeshPipeline_->AddDescriptorSetLayout(VulkanMaterial::CreateMaterialDescriptorSetLayout(device));
33 skeletalMeshPipeline_->AddDescriptorSetLayout(renderer_->CreateLightDescriptorSetLayout());
34 skeletalMeshPipeline_->CreateDescriptorSet();
35 skeletalMeshPipeline_->CreateDescriptorSet();
37 skeletalMeshPipeline_->AddDescriptorSetBinding(0, 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_GEOMETRY_BIT,
nullptr);
38 skeletalMeshPipeline_->AddDescriptorSetBinding(3, 0, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_VERTEX_BIT,
nullptr);
39 skeletalMeshPipeline_->AddDescriptorSetBinding(4, 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT,
nullptr);
41 skeletalMeshPipeline_->AddPushConstantRange(VK_SHADER_STAGE_VERTEX_BIT, 0, static_cast<uint32_t>(
sizeof(PushConstants_t)));
43 skeletalMeshPipeline_->SetRenderPassInfo(renderer->GetGBufferRenderPass(),
static_cast<int>(VulkanRenderer::GBufferSubPasses::G_BUFFER_PASS));
45 skeletalMeshPipeline_->CreateColorBlendAttachment(VK_FALSE);
46 skeletalMeshPipeline_->CreateColorBlendAttachment(VK_FALSE);
47 skeletalMeshPipeline_->CreateColorBlendAttachment(VK_FALSE);
49 skeletalMeshPipeline_->SetInputAssemblyState(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
false);
51 skeletalMeshPipeline_->SetRasterizerSettings();
53 skeletalMeshPipeline_->Compile();
55 shadowPipeline_ = eastl::unique_ptr<VulkanPipeline>(
new VulkanPipeline(device_, renderer_));
57 shadowPipeline_->LoadShader(VulkanPipeline::SHADER_TYPE::VERTEX_SHADER,
"SkeletonShadow.vert.spv");
58 shadowPipeline_->LoadShader(VulkanPipeline::SHADER_TYPE::GEOMETRY_SHADER,
"ShadowVolume.geom.spv");
59 shadowPipeline_->LoadShader(VulkanPipeline::SHADER_TYPE::FRAGMENT_SHADER,
"ShadowVolume.frag.spv");
61 shadowPipeline_->AddVertexInputBindingDescription(0,
62 static_cast<uint32_t>(
sizeof(
Vertex)), VK_VERTEX_INPUT_RATE_VERTEX);
64 shadowPipeline_->AddVertexInputAttributeDescription(0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(
Vertex, position));
65 shadowPipeline_->AddVertexInputAttributeDescription(1, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(
Vertex, normal));
66 shadowPipeline_->AddVertexInputAttributeDescription(2, 0, VK_FORMAT_R32G32_SFLOAT, offsetof(
Vertex, texCoords));
67 shadowPipeline_->AddVertexInputAttributeDescription(3, 0, VK_FORMAT_R32G32B32A32_SFLOAT, offsetof(
Vertex, boneWeights));
68 shadowPipeline_->AddVertexInputAttributeDescription(4, 0, VK_FORMAT_R32G32B32A32_SINT, offsetof(
Vertex, boneIds));
70 shadowPipeline_->CreateDescriptorSet();
71 shadowPipeline_->AddDescriptorSetLayout(renderer_->CreateLightDescriptorSetLayout());
72 shadowPipeline_->CreateDescriptorSet();
73 shadowPipeline_->CreateDescriptorSet();
74 shadowPipeline_->CreateDescriptorSet();
76 shadowPipeline_->AddDescriptorSetBinding(0, 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_GEOMETRY_BIT,
nullptr);
77 shadowPipeline_->AddDescriptorSetBinding(3, 0, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_VERTEX_BIT,
nullptr);
78 shadowPipeline_->AddDescriptorSetBinding(4, 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT,
nullptr);
80 shadowPipeline_->AddPushConstantRange(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_GEOMETRY_BIT,
81 0, static_cast<uint32_t>(
sizeof(PushConstants_t)));
83 shadowPipeline_->SetRenderPassInfo(renderer->GetRenderPass(),
static_cast<int>(VulkanRenderer::RenderSubPasses::RENDER_PASS));
85 shadowPipeline_->SetInputAssemblyState(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY,
false);
87 shadowPipeline_->SetRasterizerSettings(VK_TRUE, VK_FALSE,
88 VK_POLYGON_MODE_FILL, 1.f, VK_CULL_MODE_NONE, VK_FRONT_FACE_COUNTER_CLOCKWISE, VK_FALSE, 0.0, 0.f, 0.f);
90 VkStencilOpState front = {};
91 front.failOp = VK_STENCIL_OP_KEEP;
92 front.passOp = VK_STENCIL_OP_KEEP;
93 front.depthFailOp = VK_STENCIL_OP_DECREMENT_AND_WRAP;
94 front.compareOp = VK_COMPARE_OP_ALWAYS;
96 front.writeMask = 0xff;
97 front.compareMask = 0xff;
99 VkStencilOpState back = {};
100 back.failOp = VK_STENCIL_OP_KEEP;
101 back.passOp = VK_STENCIL_OP_KEEP;
102 back.depthFailOp = VK_STENCIL_OP_INCREMENT_AND_WRAP;
103 back.compareOp = VK_COMPARE_OP_ALWAYS;
105 back.writeMask = 0xff;
106 back.compareMask = 0xff;
108 shadowPipeline_->SetDepthStencilState(VK_TRUE, VK_FALSE, VK_COMPARE_OP_LESS, VK_TRUE, 0.f, 1.f, VK_TRUE, front, back);
110 shadowPipeline_->CreateColorBlendAttachment(VK_TRUE, 0U);
112 shadowPipeline_->Compile();
114 ubo_ = { glm::mat4(), glm::mat4() };
116 uniformBuffer_ = eastl::unique_ptr<VulkanBuffer>(
new VulkanBuffer(device, renderer->GetVmaAllocator(),
117 static_cast<uint32_t
>(
sizeof(ubo_)), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
false, renderer->GetGraphicsCommandPool()));
119 uniformBuffer_->UpdateBuffer(&ubo_, 0, static_cast<uint32_t>(
sizeof(ubo_)));
121 uboDescriptors_.resize(renderer_->GetThreadCount());
123 for (
size_t i = 0, size = uboDescriptors_.size(); i < size; ++i) {
125 VkDescriptorSetLayout layouts[] = { skeletalMeshPipeline_->GetDescriptorSetLayout(0) };
126 renderer_->GetDescriptorPool(i)->AllocateDescriptorSet(1, layouts, &uboDescriptors_[i]);
128 renderer_->GetDescriptorPool(i)->DescriptorSetBindToBuffer(uboDescriptors_[i], uniformBuffer_->GetBuffer(),
129 0,
static_cast<VkDeviceSize
>(
sizeof(ubo_)), 0, 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1);
132 Engine::GetEngine().lock()->GetResourceManager().lock()->CreateTexture(
"default.png");
133 defaultTexture_ = eastl::dynamic_pointer_cast<VulkanTexture, Texture>(
134 Engine::GetEngine().lock()->GetResourceManager().lock()->GetTexture(
"default.png").lock());
138 VulkanSkeletalMeshRenderer::~VulkanSkeletalMeshRenderer()
140 uniformBuffer_.reset();
142 skeletalMeshPipeline_.reset();
145 void VulkanSkeletalMeshRenderer::StartRender(glm::mat4 view, glm::mat4 projection) {
146 if (ubo_.view != view || ubo_.proj != projection) {
148 ubo_.proj = projection;
150 uniformBuffer_->UpdateBuffer(&ubo_, 0, static_cast<uint32_t>(
sizeof(ubo_)));
156 void VulkanSkeletalMeshRenderer::RenderMesh(
const glm::mat4x4& modelMatrix, VulkanMesh* mesh,
157 VulkanMaterial* material, Skeleton* skeleton,
size_t animation,
158 float time,
float ticksPerSecond,
float duration,
bool looping,
const glm::vec4 & mainColor)
161 data.animation = animation;
162 data.skeleton = skeleton;
163 data.transform = modelMatrix;
164 data.material = material;
165 data.color = mainColor;
168 data.ticksPerSecond = ticksPerSecond;
169 data.duration = duration;
170 data.looping = looping;
171 data.boneData =
static_cast<VulkanTexture*
>(skeleton->GetAnimationData(animation));
173 meshes.push_back(data);
176 void VulkanSkeletalMeshRenderer::FinishRender(
size_t threadID, VkCommandPool commandPool, VkCommandBuffer buffer)
184 VkCommandBuffer commandBuffer = buffer;
188 renderer_->StartSecondaryCommandBufferRecording(commandBuffer,
189 VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT | VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT,
190 renderer_->GetGBufferRenderPass(),
static_cast<int>(VulkanRenderer::GBufferSubPasses::G_BUFFER_PASS), VK_NULL_HANDLE);
193 VkRect2D scissor = { 0,0,renderer_->GetSwapChainExtent() };
195 vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
197 vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, skeletalMeshPipeline_->GetPipeline());
199 vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
200 skeletalMeshPipeline_->GetPipelineLayout(), 0, 1, &uboDescriptors_[threadID], 0,
nullptr);
202 for (
size_t i = 0, size = meshes.size(); i<size; ++i) {
204 VulkanMesh* mesh = meshes[i].mesh;
206 PushConstants_t constants = {};
207 constants.model = meshes[i].transform;
208 constants.color = meshes[i].color;
209 constants.duration = meshes[i].duration;
210 constants.looping = meshes[i].looping;
211 constants.ticksPerSecond = meshes[i].ticksPerSecond;
212 constants.time = meshes[i].time;
215 vkCmdPushConstants(commandBuffer, skeletalMeshPipeline_->GetPipelineLayout(), VK_SHADER_STAGE_VERTEX_BIT, 0,
216 static_cast<uint32_t
>(
sizeof(PushConstants_t)), &constants);
218 VkBuffer buffers[] = { mesh->GetVertexBuffer() };
219 VkDeviceSize offsets[] = { 0 };
220 vkCmdBindVertexBuffers(commandBuffer, 0, 1, buffers, offsets);
222 vkCmdBindIndexBuffer(commandBuffer, mesh->GetIndexBuffer(), 0, VK_INDEX_TYPE_UINT32);
224 VkDescriptorSet materialDescriptor;
226 materialDescriptor = meshes[i].material->GetMaterialDescriptorSet(threadID, skeletalMeshPipeline_->GetPipelineId(), 1);
227 if (materialDescriptor == VK_NULL_HANDLE)
228 materialDescriptor = meshes[i].material->CreateMaterialDescriptorSet(
229 threadID, skeletalMeshPipeline_->GetPipelineId(),
230 1, skeletalMeshPipeline_->GetDescriptorSetLayout(1));
232 vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, skeletalMeshPipeline_->GetPipelineLayout(),
233 1, 1, &(materialDescriptor), 0,
nullptr);
235 VkDescriptorSet boneOffsets = mesh->GetBoneOffsetDescriptorSet(threadID, skeletalMeshPipeline_->GetPipelineId(), 4);
237 if (boneOffsets == VK_NULL_HANDLE)
238 boneOffsets = mesh->CreateBoneOffsetDescriptorSet(
239 threadID, skeletalMeshPipeline_->GetPipelineId(),
240 4, skeletalMeshPipeline_->GetDescriptorSetLayout(4));
242 VkDescriptorSet boneDescriptor = meshes[i].boneData->GetDescriptorSet(threadID, skeletalMeshPipeline_->GetPipelineId(), 3);
243 if (boneDescriptor == VK_NULL_HANDLE)
244 boneDescriptor = meshes[i].boneData->CreateDescriptorSet(threadID, skeletalMeshPipeline_->GetPipelineId(),
245 3, skeletalMeshPipeline_->GetDescriptorSetLayout(3));
247 vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, skeletalMeshPipeline_->GetPipelineLayout(),
248 3, 1, &(boneDescriptor), 0,
nullptr);
250 vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, skeletalMeshPipeline_->GetPipelineLayout(), 4, 1, &boneOffsets, 0,
nullptr);
252 vkCmdDrawIndexed(commandBuffer, mesh->GetIndexCount(), 1, 0, 0, 0);
255 renderer_->EndSecondaryCommandBufferRecording(commandBuffer);
259 void VulkanSkeletalMeshRenderer::RenderShadows(
size_t threadID, VkCommandPool commandPool, VkCommandBuffer buffer, uint32_t lightOffset)
267 VkCommandBuffer commandBuffer = buffer;
271 renderer_->StartSecondaryCommandBufferRecording(commandBuffer,
272 VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT,
273 renderer_->GetRenderPass(),
static_cast<int>(VulkanRenderer::RenderSubPasses::RENDER_PASS), renderer_->GetFrameBuffer());
275 VkRect2D scissor = { 0,0,renderer_->GetSwapChainExtent() };
277 vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
279 vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, shadowPipeline_->GetPipeline());
281 vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
282 shadowPipeline_->GetPipelineLayout(), 0, 1, &uboDescriptors_[threadID], 0,
nullptr);
284 VkDescriptorSet lightDescriptor = renderer_->GetLightDescriptorSet(threadID, shadowPipeline_->GetPipelineId(), 1);
285 if (lightDescriptor == VK_NULL_HANDLE)
286 lightDescriptor = renderer_->CreateLightDescriptorSet(threadID, shadowPipeline_->GetPipelineId(), 1, shadowPipeline_->GetDescriptorSetLayout(1));
288 vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
289 shadowPipeline_->GetPipelineLayout(), 1, 1, &lightDescriptor, 1, &lightOffset);
291 for (
size_t i = 0, size = meshes.size(); i < size; ++i) {
293 VulkanMesh* mesh = meshes[i].mesh;
295 PushConstants_t constants = {};
296 constants.model = meshes[i].transform;
297 constants.color = meshes[i].color;
298 constants.duration = meshes[i].duration;
299 constants.looping = meshes[i].looping;
300 constants.ticksPerSecond = meshes[i].ticksPerSecond;
301 constants.time = meshes[i].time;
304 vkCmdPushConstants(commandBuffer, shadowPipeline_->GetPipelineLayout(),
305 VK_SHADER_STAGE_VERTEX_BIT |VK_SHADER_STAGE_GEOMETRY_BIT, 0,
306 static_cast<uint32_t
>(
sizeof(PushConstants_t)), &constants);
308 VkBuffer buffers[] = { mesh->GetVertexBuffer() };
309 VkDeviceSize offsets[] = { 0 };
310 vkCmdBindVertexBuffers(commandBuffer, 0, 1, buffers, offsets);
312 vkCmdBindIndexBuffer(commandBuffer, mesh->GetShadowIndexBuffer(), 0, VK_INDEX_TYPE_UINT32);
314 VkDescriptorSet boneOffsets = mesh->GetBoneOffsetDescriptorSet(threadID, shadowPipeline_->GetPipelineId(), 4);
316 if (boneOffsets == VK_NULL_HANDLE)
317 boneOffsets = mesh->CreateBoneOffsetDescriptorSet(
318 threadID, shadowPipeline_->GetPipelineId(),
319 4, shadowPipeline_->GetDescriptorSetLayout(4));
321 VkDescriptorSet boneDescriptor = meshes[i].boneData->GetDescriptorSet(threadID, shadowPipeline_->GetPipelineId(), 3);
322 if (boneDescriptor == VK_NULL_HANDLE)
323 boneDescriptor = meshes[i].boneData->CreateDescriptorSet(threadID, shadowPipeline_->GetPipelineId(),
324 3, shadowPipeline_->GetDescriptorSetLayout(3));
326 vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, shadowPipeline_->GetPipelineLayout(),
327 3, 1, &(boneDescriptor), 0,
nullptr);
329 vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, shadowPipeline_->GetPipelineLayout(), 4, 1, &boneOffsets, 0,
nullptr);
331 vkCmdDrawIndexed(commandBuffer, mesh->GetShadowIndexCount(), 1, 0, 0, 0);
334 renderer_->EndSecondaryCommandBufferRecording(commandBuffer);
338 void VulkanSkeletalMeshRenderer::Clean()
const 340 skeletalMeshPipeline_->Clean();
341 shadowPipeline_->Clean();
344 void VulkanSkeletalMeshRenderer::Recreate() {
345 skeletalMeshPipeline_->SetRenderPassInfo(renderer_->GetGBufferRenderPass(),
static_cast<int>(VulkanRenderer::GBufferSubPasses::G_BUFFER_PASS));
346 skeletalMeshPipeline_->Recreate();
348 shadowPipeline_->SetRenderPassInfo(renderer_->GetRenderPass(),
static_cast<int>(VulkanRenderer::RenderSubPasses::RENDER_PASS));
349 shadowPipeline_->Recreate();
353 #endif // USING_VULKAN
This object is used to store general data for a vertex.