scop
a small 3D object loader
Loading...
Searching...
No Matches
VulkanPipeline.cpp
Go to the documentation of this file.
1/* ************************************************************************** */
2/* */
3/* ::: :::::::: */
4/* VulkanPipeline.cpp :+: :+: :+: */
5/* +:+ +:+ +:+ */
6/* By: rbourgea <rbourgea@student.42.fr> +#+ +:+ +#+ */
7/* +#+#+#+#+#+ +#+ */
8/* Created: 2024/01/11 07:14:04 by rbourgea #+# #+# */
9/* Updated: 2024/04/02 22:43:57 by rbourgea ### ########.fr */
10/* */
11/* ************************************************************************** */
12
13#include "VulkanApp.hpp"
14
16 VkAttachmentDescription colorAttachment{};
17 colorAttachment.format = swapChainImageFormat;
18 colorAttachment.samples = msaaSamples;
19 colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
20 colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
21 colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
22 colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
23 colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
24 colorAttachment.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
25
26 VkAttachmentDescription depthAttachment{};
27 depthAttachment.format = findDepthFormat();
28 depthAttachment.samples = msaaSamples;
29 depthAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
30 depthAttachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
31 depthAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
32 depthAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
33 depthAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
34 depthAttachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
35
36 VkAttachmentDescription colorAttachmentResolve{};
37 colorAttachmentResolve.format = swapChainImageFormat;
38 colorAttachmentResolve.samples = VK_SAMPLE_COUNT_1_BIT;
39 colorAttachmentResolve.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
40 colorAttachmentResolve.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
41 colorAttachmentResolve.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
42 colorAttachmentResolve.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
43 colorAttachmentResolve.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
44 colorAttachmentResolve.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
45
46 VkAttachmentReference colorAttachmentRef{};
47 colorAttachmentRef.attachment = 0;
48 colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
49
50 VkAttachmentReference depthAttachmentRef{};
51 depthAttachmentRef.attachment = 1;
52 depthAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
53
54 VkAttachmentReference colorAttachmentResolveRef{};
55 colorAttachmentResolveRef.attachment = 2;
56 colorAttachmentResolveRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
57
58 VkSubpassDescription subpass{};
59 subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
60 subpass.colorAttachmentCount = 1;
61 subpass.pColorAttachments = &colorAttachmentRef;
62 subpass.pDepthStencilAttachment = &depthAttachmentRef;
63 subpass.pResolveAttachments = &colorAttachmentResolveRef;
64
65 VkSubpassDependency dependency{};
66 dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
67 dependency.dstSubpass = 0;
68 dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
69 dependency.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
70 dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
71 dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
72
73 std::array<VkAttachmentDescription, 3> attachments = {colorAttachment, depthAttachment, colorAttachmentResolve };
74 VkRenderPassCreateInfo renderPassInfo{};
75 renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
76 renderPassInfo.attachmentCount = static_cast<uint32_t>(attachments.size());
77 renderPassInfo.pAttachments = attachments.data();
78 renderPassInfo.subpassCount = 1;
79 renderPassInfo.pSubpasses = &subpass;
80 renderPassInfo.dependencyCount = 1;
81 renderPassInfo.pDependencies = &dependency;
82
83 if (vkCreateRenderPass(device, &renderPassInfo, nullptr, &renderPass) != VK_SUCCESS) {
84 throw std::runtime_error("Failed to create render pass !");
85 }
86}
87
88VkShaderModule VulkanApp::createShaderModule(const std::vector<char>& code) {
89 VkShaderModuleCreateInfo createInfo{};
90 createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
91 createInfo.codeSize = code.size();
92 createInfo.pCode = reinterpret_cast<const uint32_t*>(code.data());
93
94 VkShaderModule shaderModule;
95 if (vkCreateShaderModule(device, &createInfo, nullptr, &shaderModule) != VK_SUCCESS) {
96 throw std::runtime_error("Failed to create shader module !");
97 }
98
99 return shaderModule;
100}
101
103#ifdef __APPLE__
104 auto vertShaderCode = readFile("../shaders/vert.spv");
105 auto fragShaderCode = readFile("../shaders/frag.spv");
106#else
107 auto vertShaderCode = readFile("shaders/vert.spv");
108 auto fragShaderCode = readFile("shaders/frag.spv");
109#endif
110
111 VkShaderModule vertShaderModule = createShaderModule(vertShaderCode);
112 VkShaderModule fragShaderModule = createShaderModule(fragShaderCode);
113
114 VkPipelineShaderStageCreateInfo vertShaderStageInfo{};
115 vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
116 vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
117 vertShaderStageInfo.module = vertShaderModule;
118 vertShaderStageInfo.pName = "main";
119
120 VkPipelineShaderStageCreateInfo fragShaderStageInfo{};
121 fragShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
122 fragShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
123 fragShaderStageInfo.module = fragShaderModule;
124 fragShaderStageInfo.pName = "main";
125
126 VkPipelineShaderStageCreateInfo shaderStages[] = {vertShaderStageInfo, fragShaderStageInfo};
127
128 VkPipelineVertexInputStateCreateInfo vertexInputInfo{};
129 vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
130
131 auto bindingDescription = Vertex::getBindingDescription();
132 auto attributeDescriptions = Vertex::getAttributeDescriptions();
133
134 VkPipelineInputAssemblyStateCreateInfo inputAssembly{};
135 inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
136 inputAssembly.topology = topology;
137 inputAssembly.primitiveRestartEnable = VK_FALSE;
138
139 VkPipelineViewportStateCreateInfo viewportState{};
140 viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
141 viewportState.viewportCount = 1;
142 viewportState.scissorCount = 1;
143
144 vertexInputInfo.vertexBindingDescriptionCount = 1;
145 vertexInputInfo.vertexAttributeDescriptionCount = static_cast<uint32_t>(attributeDescriptions.size());
146 vertexInputInfo.pVertexBindingDescriptions = &bindingDescription;
147 vertexInputInfo.pVertexAttributeDescriptions = attributeDescriptions.data();
148
149 VkPipelineRasterizationStateCreateInfo rasterizer{};
150 rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
151 rasterizer.depthClampEnable = VK_FALSE;
152 rasterizer.rasterizerDiscardEnable = VK_FALSE;
153 rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
154 rasterizer.lineWidth = 1.0f;
155 rasterizer.cullMode = VK_CULL_MODE_BACK_BIT;
156 rasterizer.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
157 rasterizer.depthBiasEnable = VK_FALSE;
158
159 VkPipelineMultisampleStateCreateInfo multisampling{};
160 multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
161 multisampling.sampleShadingEnable = VK_FALSE;
162 multisampling.minSampleShading = 0.2f;
163 multisampling.rasterizationSamples = msaaSamples;
164
165 VkPipelineDepthStencilStateCreateInfo depthStencil{};
166 depthStencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
167 depthStencil.depthTestEnable = VK_TRUE;
168 depthStencil.depthWriteEnable = VK_TRUE;
169 depthStencil.depthCompareOp = VK_COMPARE_OP_LESS;
170 depthStencil.depthBoundsTestEnable = VK_FALSE;
171 depthStencil.stencilTestEnable = VK_FALSE;
172
173 VkPipelineColorBlendAttachmentState colorBlendAttachment{};
174 colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
175 colorBlendAttachment.blendEnable = VK_TRUE;
176 colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
177 colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
178 colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD;
179 colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
180 colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
181 colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD;
182
183 VkPipelineColorBlendStateCreateInfo colorBlending{};
184 colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
185 colorBlending.logicOpEnable = VK_FALSE;
186 colorBlending.logicOp = VK_LOGIC_OP_COPY;
187 colorBlending.attachmentCount = 1;
188 colorBlending.pAttachments = &colorBlendAttachment;
189 colorBlending.blendConstants[0] = 0.0f;
190 colorBlending.blendConstants[1] = 0.0f;
191 colorBlending.blendConstants[2] = 0.0f;
192 colorBlending.blendConstants[3] = 0.0f;
193
194 std::vector<VkDynamicState> dynamicStates = {
195 VK_DYNAMIC_STATE_VIEWPORT,
196 VK_DYNAMIC_STATE_SCISSOR
197 };
198 VkPipelineDynamicStateCreateInfo dynamicState{};
199 dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
200 dynamicState.dynamicStateCount = static_cast<uint32_t>(dynamicStates.size());
201 dynamicState.pDynamicStates = dynamicStates.data();
202
203 VkPipelineLayoutCreateInfo pipelineLayoutInfo{};
204 pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
205 pipelineLayoutInfo.setLayoutCount = 1;
206 pipelineLayoutInfo.pSetLayouts = &descriptorSetLayout;
207
208 if (vkCreatePipelineLayout(device, &pipelineLayoutInfo, nullptr, &pipelineLayout) != VK_SUCCESS) {
209 throw std::runtime_error("Failed to create pipeline layout !");
210 }
211
212 VkGraphicsPipelineCreateInfo pipelineInfo{};
213 pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
214 pipelineInfo.stageCount = 2;
215 pipelineInfo.pStages = shaderStages;
216 pipelineInfo.pVertexInputState = &vertexInputInfo;
217 pipelineInfo.pInputAssemblyState = &inputAssembly;
218 pipelineInfo.pViewportState = &viewportState;
219 pipelineInfo.pRasterizationState = &rasterizer;
220 pipelineInfo.pMultisampleState = &multisampling;
221 pipelineInfo.pDepthStencilState = &depthStencil;
222 pipelineInfo.pColorBlendState = &colorBlending;
223 pipelineInfo.pDynamicState = &dynamicState;
224 pipelineInfo.layout = pipelineLayout;
225 pipelineInfo.renderPass = renderPass;
226 pipelineInfo.subpass = 0;
227 pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
228
229 if (vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &graphicsPipeline) != VK_SUCCESS) {
230 throw std::runtime_error("Failed to create graphics pipeline !");
231 }
232
233 vkDestroyShaderModule(device, fragShaderModule, nullptr);
234 vkDestroyShaderModule(device, vertShaderModule, nullptr);
235}
236
238 VkDescriptorSetLayoutBinding uboLayoutBinding{};
239 uboLayoutBinding.binding = 0;
240 uboLayoutBinding.descriptorCount = 1;
241 uboLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
242 uboLayoutBinding.pImmutableSamplers = nullptr;
243 uboLayoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
244
245 VkDescriptorSetLayoutBinding samplerLayoutBinding{};
246 samplerLayoutBinding.binding = 1;
247 samplerLayoutBinding.descriptorCount = 1;
248 samplerLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
249 samplerLayoutBinding.pImmutableSamplers = nullptr;
250 samplerLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
251
252 std::array<VkDescriptorSetLayoutBinding, 2> bindings = {uboLayoutBinding, samplerLayoutBinding};
253 VkDescriptorSetLayoutCreateInfo layoutInfo{};
254 layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
255 layoutInfo.bindingCount = static_cast<uint32_t>(bindings.size());
256 layoutInfo.pBindings = bindings.data();
257
258 if (vkCreateDescriptorSetLayout(device, &layoutInfo, nullptr, &descriptorSetLayout) != VK_SUCCESS) {
259 throw std::runtime_error("Failed to create descriptor set layout !");
260 }
261}
262
264 VkDeviceSize bufferSize = sizeof(UniformBufferObject);
265
269
270 for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
271 createBuffer(bufferSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, uniformBuffers[i], uniformBuffersMemory[i]);
272
273 vkMapMemory(device, uniformBuffersMemory[i], 0, bufferSize, 0, &uniformBuffersMapped[i]);
274 }
275}
276
277void VulkanApp::updateUniformBuffer(uint32_t currentImage) {
279
281 float rotationAngle = math::length(rotationAxis);
282 // Normalize
283 if (rotationAngle > 0.0f) {
284 rotationAxis /= rotationAngle;
285 }
286
287 quat totalRotationQuat = math::angleAxis(math::radians(rotationAngle), rotationAxis);
288
290 modelMatrix = math::translate(mat4(), -modelCentroid) * totalRotationQuat.toMat4() * modelMatrix;
291 ubo.model = modelMatrix;
292
294 ubo.view = viewMatrix;
295
296 mat4 projMatrix = math::perspective(math::radians(45.0f), swapChainExtent.width / static_cast<float>(swapChainExtent.height), 0.1f, 10.0f);
297 projMatrix(1, 1) *= -1;
298 ubo.proj = projMatrix;
299
300 memcpy(uniformBuffersMapped[currentImage], &ubo, sizeof(ubo));
301}
302
304 std::array<VkDescriptorPoolSize, 2> poolSizes{};
305 poolSizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
306 poolSizes[0].descriptorCount = static_cast<uint32_t>(MAX_FRAMES_IN_FLIGHT);
307 poolSizes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
308 poolSizes[1].descriptorCount = static_cast<uint32_t>(MAX_FRAMES_IN_FLIGHT);
309
310 VkDescriptorPoolCreateInfo poolInfo{};
311 poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
312 poolInfo.poolSizeCount = static_cast<uint32_t>(poolSizes.size());
313 poolInfo.pPoolSizes = poolSizes.data();
314 poolInfo.maxSets = static_cast<uint32_t>(MAX_FRAMES_IN_FLIGHT);
315
316 if (vkCreateDescriptorPool(device, &poolInfo, nullptr, &descriptorPool) != VK_SUCCESS) {
317 throw std::runtime_error("Failed to create descriptor pool !");
318 }
319}
320
322 std::vector<VkDescriptorSetLayout> layouts(MAX_FRAMES_IN_FLIGHT, descriptorSetLayout);
323 VkDescriptorSetAllocateInfo allocInfo{};
324 allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
325 allocInfo.descriptorPool = descriptorPool;
326 allocInfo.descriptorSetCount = static_cast<uint32_t>(MAX_FRAMES_IN_FLIGHT);
327 allocInfo.pSetLayouts = layouts.data();
328
330 if (vkAllocateDescriptorSets(device, &allocInfo, descriptorSets.data()) != VK_SUCCESS) {
331 throw std::runtime_error("Failed to allocate descriptor sets !");
332 }
333
334 for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
335 VkDescriptorBufferInfo bufferInfo{};
336 bufferInfo.buffer = uniformBuffers[i];
337 bufferInfo.offset = 0;
338 bufferInfo.range = sizeof(UniformBufferObject);
339
340 VkDescriptorImageInfo imageInfo{};
341 imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
342 imageInfo.imageView = textureImageView;
343 imageInfo.sampler = textureSampler;
344
345 std::array<VkWriteDescriptorSet, 2> descriptorWrites{};
346
347 descriptorWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
348 descriptorWrites[0].dstSet = descriptorSets[i];
349 descriptorWrites[0].dstBinding = 0;
350 descriptorWrites[0].dstArrayElement = 0;
351 descriptorWrites[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
352 descriptorWrites[0].descriptorCount = 1;
353 descriptorWrites[0].pBufferInfo = &bufferInfo;
354
355 descriptorWrites[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
356 descriptorWrites[1].dstSet = descriptorSets[i];
357 descriptorWrites[1].dstBinding = 1;
358 descriptorWrites[1].dstArrayElement = 0;
359 descriptorWrites[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
360 descriptorWrites[1].descriptorCount = 1;
361 descriptorWrites[1].pImageInfo = &imageInfo;
362
363 vkUpdateDescriptorSets(device, static_cast<uint32_t>(descriptorWrites.size()), descriptorWrites.data(), 0, nullptr);
364 }
365}
const int MAX_FRAMES_IN_FLIGHT
Definition VulkanApp.hpp:45
static std::vector< char > readFile(const std::string &filename)
Definition Parsing.cpp:258
void createDescriptorSets()
Camera cameraView
VkSampleCountFlagBits msaaSamples
VkDevice device
void createGraphicsPipeline()
VkImageView textureImageView
std::vector< VkDeviceMemory > uniformBuffersMemory
VkRenderPass renderPass
VkSampler textureSampler
VkShaderModule createShaderModule(const std::vector< char > &code)
vec3 modelCentroid
VkPipelineLayout pipelineLayout
void createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer &buffer, VkDeviceMemory &bufferMemory)
void createDescriptorSetLayout()
VkExtent2D swapChainExtent
VkPipeline graphicsPipeline
VkDescriptorPool descriptorPool
vec3 rotationModel
std::vector< VkBuffer > uniformBuffers
VkFormat findDepthFormat()
VkPrimitiveTopology topology
void createUniformBuffers()
std::vector< VkDescriptorSet > descriptorSets
std::vector< void * > uniformBuffersMapped
void createDescriptorPool()
void updateUniformBuffer(uint32_t currentImage)
void createRenderPass()
vec3 positionModel
VkDescriptorSetLayout descriptorSetLayout
VkFormat swapChainImageFormat
Definition Math.hpp:172
static float length(vec3 v)
Definition Math.hpp:332
static mat4 translate(const mat4 &matrix, const vec3 &translation)
Definition Math.hpp:368
static mat4 lookAt(const vec3 &eye, const vec3 &center, const vec3 &up)
Definition Math.hpp:404
static float radians(float degrees)
Definition Math.hpp:350
static quat angleAxis(float angle, const vec3 &axis)
Definition Math.hpp:453
static mat4 perspective(float fov, float aspectRatio, float near, float far)
Definition Math.hpp:429
Definition Math.hpp:261
mat4 toMat4() const
Definition Math.hpp:289
Definition Math.hpp:65
float x
Definition Math.hpp:67
float y
Definition Math.hpp:67
float z
Definition Math.hpp:67
vec3 center
Definition VulkanApp.hpp:84
vec3 eye
Definition VulkanApp.hpp:83
vec3 up
Definition VulkanApp.hpp:85
static VkVertexInputBindingDescription getBindingDescription()
static std::array< VkVertexInputAttributeDescription, 7 > getAttributeDescriptions()