reconstruct gltf model loader (no complete yet)
							parent
							
								
									293e5a6d28
								
							
						
					
					
						commit
						e7d9f78252
					
				| 
						 | 
					@ -1,8 +1,16 @@
 | 
				
			||||||
#pragma once
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define TINYGLTF_IMPLEMENTATION
 | 
				
			||||||
 | 
					#define STB_IMAGE_IMPLEMENTATION
 | 
				
			||||||
 | 
					#define TINYGLTF_NO_STB_IMAGE_WRITE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "glTFModel.h"
 | 
					#include "glTFModel.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VkDescriptorSetLayout glTFModel::descriptorSetLayoutImage = VK_NULL_HANDLE;
 | 
				
			||||||
 | 
					VkDescriptorSetLayout glTFModel::descriptorSetLayoutUbo = VK_NULL_HANDLE;
 | 
				
			||||||
 | 
					VkMemoryPropertyFlags glTFModel::memoryPropertyFlags = 0;
 | 
				
			||||||
 | 
					uint32_t glTFModel::descriptorBindingFlags = glTFModel::DescriptorBindingFlags::ImageBaseColor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
	glTF loading functions
 | 
						glTF loading functions
 | 
				
			||||||
| 
						 | 
					@ -10,24 +18,81 @@
 | 
				
			||||||
	The following functions take a glTF input model loaded via tinyglTF and convert all required data into our own structure
 | 
						The following functions take a glTF input model loaded via tinyglTF and convert all required data into our own structure
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void VulkanglTFModel::loadImages(tinygltf::Model& input)
 | 
					// custom image loading function with tinyglTF
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ktx image as texture
 | 
				
			||||||
 | 
					bool loadImageDataFunc(tinygltf::Image* image, const int imageIndex, std::string* error, std::string* warning, int req_width, int req_height, const unsigned char* bytes, int size, void* userData)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						// KTX files will be handled by our own code
 | 
				
			||||||
 | 
						if (image->uri.find_last_of(".") != std::string::npos) {
 | 
				
			||||||
 | 
							if (image->uri.substr(image->uri.find_last_of(".") + 1) == "ktx") {
 | 
				
			||||||
 | 
								return true;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return tinygltf::LoadImageData(image, imageIndex, error, warning, req_width, req_height, bytes, size, userData);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//will be used for samples that don't require images to be loaded
 | 
				
			||||||
 | 
					bool loadImageDataFuncEmpty(tinygltf::Image* image, const int imageIndex, std::string* error, std::string* warning, int req_width, int req_height, const unsigned char* bytes, int size, void* userData)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						// This function will be used for samples that don't require images to be loaded
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					   glTF texture loader
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void glTFModel::Texture::updateDescriptor()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						descriptor.sampler = sampler;
 | 
				
			||||||
 | 
						descriptor.imageView = view;
 | 
				
			||||||
 | 
						descriptor.imageLayout = imageLayout;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void glTFModel::Texture::destroy()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (device)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							vkDestroyImageView(device->logicalDevice, view, nullptr);
 | 
				
			||||||
 | 
							vkDestroyImage(device->logicalDevice, image, nullptr);
 | 
				
			||||||
 | 
							vkFreeMemory(device->logicalDevice, deviceMemory, nullptr);
 | 
				
			||||||
 | 
							vkDestroySampler(device->logicalDevice, sampler, nullptr);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void glTFModel::Texture::fromglTfImage(tinygltf::Image& gltfImage, std::string path, vks::VulkanDevice* device, VkQueue copyQueue)
 | 
				
			||||||
 | 
					{	
 | 
				
			||||||
 | 
						this->device = device;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool isKtx = false;
 | 
				
			||||||
 | 
						// Image points to an external ktx file
 | 
				
			||||||
 | 
						if (gltfImage.uri.find_last_of(".") != std::string::npos) {
 | 
				
			||||||
 | 
							if (gltfImage.uri.substr(gltfImage.uri.find_last_of(".") + 1) == "ktx") {
 | 
				
			||||||
 | 
								isKtx = true;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						VkFormat format;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						if (!isKtx) 
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							// loaded using STB_Image
 | 
				
			||||||
		// Images can be stored inside the glTF (which is the case for the sample model), so instead of directly
 | 
							// Images can be stored inside the glTF (which is the case for the sample model), so instead of directly
 | 
				
			||||||
		// loading them from disk, we fetch them from the glTF loader and upload the buffers
 | 
							// loading them from disk, we fetch them from the glTF loader and upload the buffers
 | 
				
			||||||
	images.resize(input.images.size());
 | 
					
 | 
				
			||||||
	for (size_t i = 0; i < input.images.size(); i++) {
 | 
					 | 
				
			||||||
		tinygltf::Image& glTFImage = input.images[i];
 | 
					 | 
				
			||||||
		// Get the image data from the glTF loader
 | 
					 | 
				
			||||||
		unsigned char* buffer = nullptr;
 | 
							unsigned char* buffer = nullptr;
 | 
				
			||||||
		VkDeviceSize bufferSize = 0;
 | 
							VkDeviceSize bufferSize = 0;
 | 
				
			||||||
		bool deleteBuffer = false;
 | 
							bool deleteBuffer = false;
 | 
				
			||||||
		// We convert RGB-only images to RGBA, as most devices don't support RGB-formats in Vulkan
 | 
							// We convert RGB-only images to RGBA, as most devices don't support RGB-formats in Vulkan
 | 
				
			||||||
		if (glTFImage.component == 3) {
 | 
							if (gltfImage.component == 3) {
 | 
				
			||||||
			bufferSize = glTFImage.width * glTFImage.height * 4;
 | 
								bufferSize = gltfImage.width * gltfImage.height * 4;
 | 
				
			||||||
			buffer = new unsigned char[bufferSize];
 | 
								buffer = new unsigned char[bufferSize];
 | 
				
			||||||
			unsigned char* rgba = buffer;
 | 
								unsigned char* rgba = buffer;
 | 
				
			||||||
			unsigned char* rgb = &glTFImage.image[0];
 | 
								unsigned char* rgb = &gltfImage.image[0];
 | 
				
			||||||
			for (size_t i = 0; i < glTFImage.width * glTFImage.height; ++i) {
 | 
								for (size_t i = 0; i < gltfImage.width * gltfImage.height; ++i) {
 | 
				
			||||||
				memcpy(rgba, rgb, sizeof(unsigned char) * 3);
 | 
									memcpy(rgba, rgb, sizeof(unsigned char) * 3);
 | 
				
			||||||
				rgba += 4;
 | 
									rgba += 4;
 | 
				
			||||||
				rgb += 3;
 | 
									rgb += 3;
 | 
				
			||||||
| 
						 | 
					@ -35,16 +100,339 @@ void VulkanglTFModel::loadImages(tinygltf::Model& input)
 | 
				
			||||||
			deleteBuffer = true;
 | 
								deleteBuffer = true;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		else {
 | 
							else {
 | 
				
			||||||
			buffer = &glTFImage.image[0];
 | 
								buffer = &gltfImage.image[0];
 | 
				
			||||||
			bufferSize = glTFImage.image.size();
 | 
								bufferSize = gltfImage.image.size();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		// Load texture from image buffer
 | 
					
 | 
				
			||||||
		images[i].texture.fromBuffer(buffer, bufferSize, VK_FORMAT_R8G8B8A8_UNORM, glTFImage.width, glTFImage.height, vulkanDevice, copyQueue);
 | 
							format = VK_FORMAT_R8G8B8A8_UNORM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							VkFormatProperties formatProperties;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							width = gltfImage.width;
 | 
				
			||||||
 | 
							height = gltfImage.height;
 | 
				
			||||||
 | 
							mipLevels = static_cast<uint32_t>(floor(log2(std::max(width, height))) + 1.0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							vkGetPhysicalDeviceFormatProperties(device->physicalDevice, format, &formatProperties);
 | 
				
			||||||
 | 
							assert(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_BLIT_SRC_BIT);
 | 
				
			||||||
 | 
							assert(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_BLIT_DST_BIT);
 | 
				
			||||||
 | 
							// allocate memry for texture
 | 
				
			||||||
 | 
							VkMemoryAllocateInfo memAllocInfo{};
 | 
				
			||||||
 | 
							memAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
 | 
				
			||||||
 | 
							VkMemoryRequirements memReqs{};
 | 
				
			||||||
 | 
							VkBuffer stagingBuffer;
 | 
				
			||||||
 | 
							VkDeviceMemory stagingMemory;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							VkBufferCreateInfo bufferCreateInfo{};
 | 
				
			||||||
 | 
							bufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
 | 
				
			||||||
 | 
							bufferCreateInfo.size = bufferSize;
 | 
				
			||||||
 | 
							bufferCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
 | 
				
			||||||
 | 
							bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
 | 
				
			||||||
 | 
							VK_CHECK_RESULT(vkCreateBuffer(device->logicalDevice, &bufferCreateInfo, nullptr, &stagingBuffer));
 | 
				
			||||||
 | 
							vkGetBufferMemoryRequirements(device->logicalDevice, stagingBuffer, &memReqs);
 | 
				
			||||||
 | 
							memAllocInfo.allocationSize = memReqs.size;
 | 
				
			||||||
 | 
							memAllocInfo.memoryTypeIndex = device->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
 | 
				
			||||||
 | 
							VK_CHECK_RESULT(vkAllocateMemory(device->logicalDevice, &memAllocInfo, nullptr, &stagingMemory));
 | 
				
			||||||
 | 
							VK_CHECK_RESULT(vkBindBufferMemory(device->logicalDevice, stagingBuffer, stagingMemory, 0));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							uint8_t* data;
 | 
				
			||||||
 | 
							VK_CHECK_RESULT(vkMapMemory(device->logicalDevice, stagingMemory, 0, memReqs.size, 0, (void**)&data));
 | 
				
			||||||
 | 
							memcpy(data, buffer, bufferSize);
 | 
				
			||||||
 | 
							vkUnmapMemory(device->logicalDevice, stagingMemory);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							VkImageCreateInfo imageCreateInfo{};
 | 
				
			||||||
 | 
							imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
 | 
				
			||||||
 | 
							imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
 | 
				
			||||||
 | 
							imageCreateInfo.format = format;
 | 
				
			||||||
 | 
							imageCreateInfo.mipLevels = mipLevels;
 | 
				
			||||||
 | 
							imageCreateInfo.arrayLayers = 1;
 | 
				
			||||||
 | 
							imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
 | 
				
			||||||
 | 
							imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
 | 
				
			||||||
 | 
							imageCreateInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
 | 
				
			||||||
 | 
							imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
 | 
				
			||||||
 | 
							imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
 | 
				
			||||||
 | 
							imageCreateInfo.extent = { width, height, 1 };
 | 
				
			||||||
 | 
							imageCreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
 | 
				
			||||||
 | 
							VK_CHECK_RESULT(vkCreateImage(device->logicalDevice, &imageCreateInfo, nullptr, &image));
 | 
				
			||||||
 | 
							vkGetImageMemoryRequirements(device->logicalDevice, image, &memReqs);
 | 
				
			||||||
 | 
							memAllocInfo.allocationSize = memReqs.size;
 | 
				
			||||||
 | 
							memAllocInfo.memoryTypeIndex = device->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
 | 
				
			||||||
 | 
							VK_CHECK_RESULT(vkAllocateMemory(device->logicalDevice, &memAllocInfo, nullptr, &deviceMemory));
 | 
				
			||||||
 | 
							VK_CHECK_RESULT(vkBindImageMemory(device->logicalDevice, image, deviceMemory, 0));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							VkCommandBuffer copyCmd = device->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							VkImageSubresourceRange subresourceRange = {};
 | 
				
			||||||
 | 
							subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
 | 
				
			||||||
 | 
							subresourceRange.levelCount = 1;
 | 
				
			||||||
 | 
							subresourceRange.layerCount = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								VkImageMemoryBarrier imageMemoryBarrier{};
 | 
				
			||||||
 | 
								imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
 | 
				
			||||||
 | 
								imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
 | 
				
			||||||
 | 
								imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
 | 
				
			||||||
 | 
								imageMemoryBarrier.srcAccessMask = 0;
 | 
				
			||||||
 | 
								imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
 | 
				
			||||||
 | 
								imageMemoryBarrier.image = image;
 | 
				
			||||||
 | 
								imageMemoryBarrier.subresourceRange = subresourceRange;
 | 
				
			||||||
 | 
								vkCmdPipelineBarrier(copyCmd, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 0, nullptr, 1, &imageMemoryBarrier);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							VkBufferImageCopy bufferCopyRegion = {};
 | 
				
			||||||
 | 
							bufferCopyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
 | 
				
			||||||
 | 
							bufferCopyRegion.imageSubresource.mipLevel = 0;
 | 
				
			||||||
 | 
							bufferCopyRegion.imageSubresource.baseArrayLayer = 0;
 | 
				
			||||||
 | 
							bufferCopyRegion.imageSubresource.layerCount = 1;
 | 
				
			||||||
 | 
							bufferCopyRegion.imageExtent.width = width;
 | 
				
			||||||
 | 
							bufferCopyRegion.imageExtent.height = height;
 | 
				
			||||||
 | 
							bufferCopyRegion.imageExtent.depth = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							vkCmdCopyBufferToImage(copyCmd, stagingBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &bufferCopyRegion);
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								VkImageMemoryBarrier imageMemoryBarrier{};
 | 
				
			||||||
 | 
								imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
 | 
				
			||||||
 | 
								imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
 | 
				
			||||||
 | 
								imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
 | 
				
			||||||
 | 
								imageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
 | 
				
			||||||
 | 
								imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
 | 
				
			||||||
 | 
								imageMemoryBarrier.image = image;
 | 
				
			||||||
 | 
								imageMemoryBarrier.subresourceRange = subresourceRange;
 | 
				
			||||||
 | 
								vkCmdPipelineBarrier(copyCmd, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 0, nullptr, 1, &imageMemoryBarrier);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							device->flushCommandBuffer(copyCmd, copyQueue, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							vkFreeMemory(device->logicalDevice, stagingMemory, nullptr);
 | 
				
			||||||
 | 
							vkDestroyBuffer(device->logicalDevice, stagingBuffer, nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Generate the mip chain (glTF uses jpg and png, so we need to create this manually)
 | 
				
			||||||
 | 
							VkCommandBuffer blitCmd = device->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);
 | 
				
			||||||
 | 
							for (uint32_t i = 1; i < mipLevels; i++) {
 | 
				
			||||||
 | 
								VkImageBlit imageBlit{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								imageBlit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
 | 
				
			||||||
 | 
								imageBlit.srcSubresource.layerCount = 1;
 | 
				
			||||||
 | 
								imageBlit.srcSubresource.mipLevel = i - 1;
 | 
				
			||||||
 | 
								imageBlit.srcOffsets[1].x = int32_t(width >> (i - 1));
 | 
				
			||||||
 | 
								imageBlit.srcOffsets[1].y = int32_t(height >> (i - 1));
 | 
				
			||||||
 | 
								imageBlit.srcOffsets[1].z = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								imageBlit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
 | 
				
			||||||
 | 
								imageBlit.dstSubresource.layerCount = 1;
 | 
				
			||||||
 | 
								imageBlit.dstSubresource.mipLevel = i;
 | 
				
			||||||
 | 
								imageBlit.dstOffsets[1].x = int32_t(width >> i);
 | 
				
			||||||
 | 
								imageBlit.dstOffsets[1].y = int32_t(height >> i);
 | 
				
			||||||
 | 
								imageBlit.dstOffsets[1].z = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								VkImageSubresourceRange mipSubRange = {};
 | 
				
			||||||
 | 
								mipSubRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
 | 
				
			||||||
 | 
								mipSubRange.baseMipLevel = i;
 | 
				
			||||||
 | 
								mipSubRange.levelCount = 1;
 | 
				
			||||||
 | 
								mipSubRange.layerCount = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									VkImageMemoryBarrier imageMemoryBarrier{};
 | 
				
			||||||
 | 
									imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
 | 
				
			||||||
 | 
									imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
 | 
				
			||||||
 | 
									imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
 | 
				
			||||||
 | 
									imageMemoryBarrier.srcAccessMask = 0;
 | 
				
			||||||
 | 
									imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
 | 
				
			||||||
 | 
									imageMemoryBarrier.image = image;
 | 
				
			||||||
 | 
									imageMemoryBarrier.subresourceRange = mipSubRange;
 | 
				
			||||||
 | 
									vkCmdPipelineBarrier(blitCmd, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &imageMemoryBarrier);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								vkCmdBlitImage(blitCmd, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &imageBlit, VK_FILTER_LINEAR);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									VkImageMemoryBarrier imageMemoryBarrier{};
 | 
				
			||||||
 | 
									imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
 | 
				
			||||||
 | 
									imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
 | 
				
			||||||
 | 
									imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
 | 
				
			||||||
 | 
									imageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
 | 
				
			||||||
 | 
									imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
 | 
				
			||||||
 | 
									imageMemoryBarrier.image = image;
 | 
				
			||||||
 | 
									imageMemoryBarrier.subresourceRange = mipSubRange;
 | 
				
			||||||
 | 
									vkCmdPipelineBarrier(blitCmd, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &imageMemoryBarrier);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							subresourceRange.levelCount = mipLevels;
 | 
				
			||||||
 | 
							imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								VkImageMemoryBarrier imageMemoryBarrier{};
 | 
				
			||||||
 | 
								imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
 | 
				
			||||||
 | 
								imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
 | 
				
			||||||
 | 
								imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
 | 
				
			||||||
 | 
								imageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
 | 
				
			||||||
 | 
								imageMemoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
 | 
				
			||||||
 | 
								imageMemoryBarrier.image = image;
 | 
				
			||||||
 | 
								imageMemoryBarrier.subresourceRange = subresourceRange;
 | 
				
			||||||
 | 
								vkCmdPipelineBarrier(blitCmd, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 0, nullptr, 1, &imageMemoryBarrier);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (deleteBuffer) {
 | 
							if (deleteBuffer) {
 | 
				
			||||||
			delete[] buffer;
 | 
								delete[] buffer;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							device->flushCommandBuffer(blitCmd, copyQueue, true);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
							// Texture is stored in an external ktx file
 | 
				
			||||||
 | 
							std::string filename = path + "/" + gltfImage.uri;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ktxTexture* ktxTexture;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ktxResult result = KTX_SUCCESS;
 | 
				
			||||||
 | 
					#if defined(__ANDROID__)
 | 
				
			||||||
 | 
							AAsset* asset = AAssetManager_open(androidApp->activity->assetManager, filename.c_str(), AASSET_MODE_STREAMING);
 | 
				
			||||||
 | 
							if (!asset) {
 | 
				
			||||||
 | 
								vks::tools::exitFatal("Could not load texture from " + filename + "\n\nThe file may be part of the additional asset pack.\n\nRun \"download_assets.py\" in the repository root to download the latest version.", -1);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							size_t size = AAsset_getLength(asset);
 | 
				
			||||||
 | 
							assert(size > 0);
 | 
				
			||||||
 | 
							ktx_uint8_t* textureData = new ktx_uint8_t[size];
 | 
				
			||||||
 | 
							AAsset_read(asset, textureData, size);
 | 
				
			||||||
 | 
							AAsset_close(asset);
 | 
				
			||||||
 | 
							result = ktxTexture_CreateFromMemory(textureData, size, KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, &ktxTexture);
 | 
				
			||||||
 | 
							delete[] textureData;
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
							if (!vks::tools::fileExists(filename)) {
 | 
				
			||||||
 | 
								vks::tools::exitFatal("Could not load texture from " + filename + "\n\nThe file may be part of the additional asset pack.\n\nRun \"download_assets.py\" in the repository root to download the latest version.", -1);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							result = ktxTexture_CreateFromNamedFile(filename.c_str(), KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, &ktxTexture);
 | 
				
			||||||
 | 
					#endif		
 | 
				
			||||||
 | 
							assert(result == KTX_SUCCESS);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this->device = device;
 | 
				
			||||||
 | 
							width = ktxTexture->baseWidth;
 | 
				
			||||||
 | 
							height = ktxTexture->baseHeight;
 | 
				
			||||||
 | 
							mipLevels = ktxTexture->numLevels;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ktx_uint8_t* ktxTextureData = ktxTexture_GetData(ktxTexture);
 | 
				
			||||||
 | 
							ktx_size_t ktxTextureSize = ktxTexture_GetSize(ktxTexture);
 | 
				
			||||||
 | 
							// @todo: Use ktxTexture_GetVkFormat(ktxTexture)
 | 
				
			||||||
 | 
							format = VK_FORMAT_R8G8B8A8_UNORM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Get device properties for the requested texture format
 | 
				
			||||||
 | 
							VkFormatProperties formatProperties;
 | 
				
			||||||
 | 
							vkGetPhysicalDeviceFormatProperties(device->physicalDevice, format, &formatProperties);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							VkCommandBuffer copyCmd = device->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);
 | 
				
			||||||
 | 
							VkBuffer stagingBuffer;
 | 
				
			||||||
 | 
							VkDeviceMemory stagingMemory;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							VkBufferCreateInfo bufferCreateInfo = vks::initializers::bufferCreateInfo();
 | 
				
			||||||
 | 
							bufferCreateInfo.size = ktxTextureSize;
 | 
				
			||||||
 | 
							// This buffer is used as a transfer source for the buffer copy
 | 
				
			||||||
 | 
							bufferCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
 | 
				
			||||||
 | 
							bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
 | 
				
			||||||
 | 
							VK_CHECK_RESULT(vkCreateBuffer(device->logicalDevice, &bufferCreateInfo, nullptr, &stagingBuffer));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							VkMemoryAllocateInfo memAllocInfo = vks::initializers::memoryAllocateInfo();
 | 
				
			||||||
 | 
							VkMemoryRequirements memReqs;
 | 
				
			||||||
 | 
							vkGetBufferMemoryRequirements(device->logicalDevice, stagingBuffer, &memReqs);
 | 
				
			||||||
 | 
							memAllocInfo.allocationSize = memReqs.size;
 | 
				
			||||||
 | 
							memAllocInfo.memoryTypeIndex = device->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
 | 
				
			||||||
 | 
							VK_CHECK_RESULT(vkAllocateMemory(device->logicalDevice, &memAllocInfo, nullptr, &stagingMemory));
 | 
				
			||||||
 | 
							VK_CHECK_RESULT(vkBindBufferMemory(device->logicalDevice, stagingBuffer, stagingMemory, 0));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							uint8_t* data;
 | 
				
			||||||
 | 
							VK_CHECK_RESULT(vkMapMemory(device->logicalDevice, stagingMemory, 0, memReqs.size, 0, (void**)&data));
 | 
				
			||||||
 | 
							memcpy(data, ktxTextureData, ktxTextureSize);
 | 
				
			||||||
 | 
							vkUnmapMemory(device->logicalDevice, stagingMemory);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							std::vector<VkBufferImageCopy> bufferCopyRegions;
 | 
				
			||||||
 | 
							for (uint32_t i = 0; i < mipLevels; i++)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								ktx_size_t offset;
 | 
				
			||||||
 | 
								KTX_error_code result = ktxTexture_GetImageOffset(ktxTexture, i, 0, 0, &offset);
 | 
				
			||||||
 | 
								assert(result == KTX_SUCCESS);
 | 
				
			||||||
 | 
								VkBufferImageCopy bufferCopyRegion = {};
 | 
				
			||||||
 | 
								bufferCopyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
 | 
				
			||||||
 | 
								bufferCopyRegion.imageSubresource.mipLevel = i;
 | 
				
			||||||
 | 
								bufferCopyRegion.imageSubresource.baseArrayLayer = 0;
 | 
				
			||||||
 | 
								bufferCopyRegion.imageSubresource.layerCount = 1;
 | 
				
			||||||
 | 
								bufferCopyRegion.imageExtent.width = std::max(1u, ktxTexture->baseWidth >> i);
 | 
				
			||||||
 | 
								bufferCopyRegion.imageExtent.height = std::max(1u, ktxTexture->baseHeight >> i);
 | 
				
			||||||
 | 
								bufferCopyRegion.imageExtent.depth = 1;
 | 
				
			||||||
 | 
								bufferCopyRegion.bufferOffset = offset;
 | 
				
			||||||
 | 
								bufferCopyRegions.push_back(bufferCopyRegion);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Create optimal tiled target image
 | 
				
			||||||
 | 
							VkImageCreateInfo imageCreateInfo = vks::initializers::imageCreateInfo();
 | 
				
			||||||
 | 
							imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
 | 
				
			||||||
 | 
							imageCreateInfo.format = format;
 | 
				
			||||||
 | 
							imageCreateInfo.mipLevels = mipLevels;
 | 
				
			||||||
 | 
							imageCreateInfo.arrayLayers = 1;
 | 
				
			||||||
 | 
							imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
 | 
				
			||||||
 | 
							imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
 | 
				
			||||||
 | 
							imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
 | 
				
			||||||
 | 
							imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
 | 
				
			||||||
 | 
							imageCreateInfo.extent = { width, height, 1 };
 | 
				
			||||||
 | 
							imageCreateInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
 | 
				
			||||||
 | 
							VK_CHECK_RESULT(vkCreateImage(device->logicalDevice, &imageCreateInfo, nullptr, &image));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							vkGetImageMemoryRequirements(device->logicalDevice, image, &memReqs);
 | 
				
			||||||
 | 
							memAllocInfo.allocationSize = memReqs.size;
 | 
				
			||||||
 | 
							memAllocInfo.memoryTypeIndex = device->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
 | 
				
			||||||
 | 
							VK_CHECK_RESULT(vkAllocateMemory(device->logicalDevice, &memAllocInfo, nullptr, &deviceMemory));
 | 
				
			||||||
 | 
							VK_CHECK_RESULT(vkBindImageMemory(device->logicalDevice, image, deviceMemory, 0));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							VkImageSubresourceRange subresourceRange = {};
 | 
				
			||||||
 | 
							subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
 | 
				
			||||||
 | 
							subresourceRange.baseMipLevel = 0;
 | 
				
			||||||
 | 
							subresourceRange.levelCount = mipLevels;
 | 
				
			||||||
 | 
							subresourceRange.layerCount = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							vks::tools::setImageLayout(copyCmd, image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, subresourceRange);
 | 
				
			||||||
 | 
							vkCmdCopyBufferToImage(copyCmd, stagingBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, static_cast<uint32_t>(bufferCopyRegions.size()), bufferCopyRegions.data());
 | 
				
			||||||
 | 
							vks::tools::setImageLayout(copyCmd, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, subresourceRange);
 | 
				
			||||||
 | 
							device->flushCommandBuffer(copyCmd, copyQueue);
 | 
				
			||||||
 | 
							this->imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							vkFreeMemory(device->logicalDevice, stagingMemory, nullptr);
 | 
				
			||||||
 | 
							vkDestroyBuffer(device->logicalDevice, stagingBuffer, nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ktxTexture_Destroy(ktxTexture);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						VkSamplerCreateInfo samplerInfo{};
 | 
				
			||||||
 | 
						samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
 | 
				
			||||||
 | 
						samplerInfo.magFilter = VK_FILTER_LINEAR;
 | 
				
			||||||
 | 
						samplerInfo.minFilter = VK_FILTER_LINEAR;
 | 
				
			||||||
 | 
						samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
 | 
				
			||||||
 | 
						samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT;
 | 
				
			||||||
 | 
						samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT;
 | 
				
			||||||
 | 
						samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT;
 | 
				
			||||||
 | 
						samplerInfo.compareOp = VK_COMPARE_OP_NEVER;
 | 
				
			||||||
 | 
						samplerInfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE;
 | 
				
			||||||
 | 
						samplerInfo.maxAnisotropy = 1.0;
 | 
				
			||||||
 | 
						samplerInfo.anisotropyEnable = VK_FALSE;
 | 
				
			||||||
 | 
						samplerInfo.maxLod = (float)mipLevels;
 | 
				
			||||||
 | 
						samplerInfo.maxAnisotropy = 8.0f;
 | 
				
			||||||
 | 
						samplerInfo.anisotropyEnable = VK_TRUE;
 | 
				
			||||||
 | 
						VK_CHECK_RESULT(vkCreateSampler(device->logicalDevice, &samplerInfo, nullptr, &sampler));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						VkImageViewCreateInfo viewInfo{};
 | 
				
			||||||
 | 
						viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
 | 
				
			||||||
 | 
						viewInfo.image = image;
 | 
				
			||||||
 | 
						viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
 | 
				
			||||||
 | 
						viewInfo.format = format;
 | 
				
			||||||
 | 
						viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
 | 
				
			||||||
 | 
						viewInfo.subresourceRange.layerCount = 1;
 | 
				
			||||||
 | 
						viewInfo.subresourceRange.levelCount = mipLevels;
 | 
				
			||||||
 | 
						VK_CHECK_RESULT(vkCreateImageView(device->logicalDevice, &viewInfo, nullptr, &view));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						descriptor.sampler = sampler;
 | 
				
			||||||
 | 
						descriptor.imageView = view;
 | 
				
			||||||
 | 
						descriptor.imageLayout = imageLayout;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void VulkanglTFModel::loadTextures(tinygltf::Model& input)
 | 
					void VulkanglTFModel::loadTextures(tinygltf::Model& input)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -142,7 +530,49 @@ void VulkanglTFModel::loadAnimations(tinygltf::Model& input)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
						glTF material
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					void glTFModel::Material::createDescriptorSet(VkDescriptorPool descriptorPool, VkDescriptorSetLayout descriptorSetLayout, uint32_t descriptorBindingFlags)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						VkDescriptorSetAllocateInfo descriptorSetAllocInfo{};
 | 
				
			||||||
 | 
						descriptorSetAllocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
 | 
				
			||||||
 | 
						descriptorSetAllocInfo.descriptorPool = descriptorPool;
 | 
				
			||||||
 | 
						descriptorSetAllocInfo.pSetLayouts = &descriptorSetLayout;
 | 
				
			||||||
 | 
						descriptorSetAllocInfo.descriptorSetCount = 1;
 | 
				
			||||||
 | 
						VK_CHECK_RESULT(vkAllocateDescriptorSets(device->logicalDevice, &descriptorSetAllocInfo, &descriptorSet));
 | 
				
			||||||
 | 
						std::vector<VkDescriptorImageInfo> imageDescriptors{};
 | 
				
			||||||
 | 
						std::vector<VkWriteDescriptorSet> writeDescriptorSets{};
 | 
				
			||||||
 | 
						if (descriptorBindingFlags & DescriptorBindingFlags::ImageBaseColor) {
 | 
				
			||||||
 | 
							imageDescriptors.push_back(baseColorTexture->descriptor);
 | 
				
			||||||
 | 
							VkWriteDescriptorSet writeDescriptorSet{};
 | 
				
			||||||
 | 
							writeDescriptorSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
 | 
				
			||||||
 | 
							writeDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
 | 
				
			||||||
 | 
							writeDescriptorSet.descriptorCount = 1;
 | 
				
			||||||
 | 
							writeDescriptorSet.dstSet = descriptorSet;
 | 
				
			||||||
 | 
							writeDescriptorSet.dstBinding = static_cast<uint32_t>(writeDescriptorSets.size());
 | 
				
			||||||
 | 
							writeDescriptorSet.pImageInfo = &baseColorTexture->descriptor;
 | 
				
			||||||
 | 
							writeDescriptorSets.push_back(writeDescriptorSet);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (normalTexture && descriptorBindingFlags & DescriptorBindingFlags::ImageNormalMap) {
 | 
				
			||||||
 | 
							imageDescriptors.push_back(normalTexture->descriptor);
 | 
				
			||||||
 | 
							VkWriteDescriptorSet writeDescriptorSet{};
 | 
				
			||||||
 | 
							writeDescriptorSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
 | 
				
			||||||
 | 
							writeDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
 | 
				
			||||||
 | 
							writeDescriptorSet.descriptorCount = 1;
 | 
				
			||||||
 | 
							writeDescriptorSet.dstSet = descriptorSet;
 | 
				
			||||||
 | 
							writeDescriptorSet.dstBinding = static_cast<uint32_t>(writeDescriptorSets.size());
 | 
				
			||||||
 | 
							writeDescriptorSet.pImageInfo = &normalTexture->descriptor;
 | 
				
			||||||
 | 
							writeDescriptorSets.push_back(writeDescriptorSet);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						vkUpdateDescriptorSets(device->logicalDevice, static_cast<uint32_t>(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
void VulkanglTFModel::loadMaterials(tinygltf::Model& input)
 | 
					void VulkanglTFModel::loadMaterials(tinygltf::Model& input)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	materials.resize(input.materials.size());
 | 
						materials.resize(input.materials.size());
 | 
				
			||||||
| 
						 | 
					@ -179,7 +609,7 @@ void VulkanglTFModel::loadMaterials(tinygltf::Model& input)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
void VulkanglTFModel::loadNode(const tinygltf::Node& inputNode, const tinygltf::Model& input, VulkanglTFModel::Node* parent, uint32_t nodeIndex, std::vector<uint32_t>& indexBuffer, std::vector<VulkanglTFModel::Vertex>& vertexBuffer)
 | 
					void VulkanglTFModel::loadNode(const tinygltf::Node& inputNode, const tinygltf::Model& input, VulkanglTFModel::Node* parent, uint32_t nodeIndex, std::vector<uint32_t>& indexBuffer, std::vector<VulkanglTFModel::Vertex>& vertexBuffer)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	VulkanglTFModel::Node* node = new VulkanglTFModel::Node{};
 | 
						VulkanglTFModel::Node* node = new VulkanglTFModel::Node{};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,148 +23,200 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "tiny_gltf.h"
 | 
					#include "tiny_gltf.h"
 | 
				
			||||||
 | 
					#include "VulkanDevice.h"
 | 
				
			||||||
#include "vulkanexamplebase.h"
 | 
					#include "vulkan/vulkan.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define ENABLE_VALIDATION false
 | 
					#define ENABLE_VALIDATION false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Contains everything required to render a glTF model in Vulkan
 | 
					// Contains everything required to render a glTF model in Vulkan
 | 
				
			||||||
// This class is heavily simplified (compared to glTF's feature set) but retains the basic glTF structure
 | 
					// This class is heavily simplified (compared to glTF's feature set) but retains the basic glTF structure
 | 
				
			||||||
namespace VulkanglTFModel
 | 
					namespace glTFModel
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// The class requires some Vulkan objects so it can create it's own resources
 | 
					 | 
				
			||||||
	vks::VulkanDevice* vulkanDevice;
 | 
					 | 
				
			||||||
	VkQueue copyQueue;
 | 
					 | 
				
			||||||
	uint32_t nodeCount;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	enum DescriptorBindingFlags {
 | 
						enum DescriptorBindingFlags {
 | 
				
			||||||
		ImageBaseColor = 0x00000001,
 | 
							ImageBaseColor = 0x00000001,
 | 
				
			||||||
		ImageNormalMap = 0x00000002
 | 
							ImageNormalMap = 0x00000002
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						enum FileLoadingFlags {
 | 
				
			||||||
 | 
							None = 0x00000000,
 | 
				
			||||||
 | 
							PreTransformVertices = 0x00000001,
 | 
				
			||||||
 | 
							PreMultiplyVertexColors = 0x00000002,
 | 
				
			||||||
 | 
							FlipY = 0x00000004,
 | 
				
			||||||
 | 
							DontLoadImages = 0x00000008
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						enum RenderFlags {
 | 
				
			||||||
 | 
							BindImages = 0x00000001,
 | 
				
			||||||
 | 
							RenderOpaqueNodes = 0x00000002,
 | 
				
			||||||
 | 
							RenderAlphaMaskedNodes = 0x00000004,
 | 
				
			||||||
 | 
							RenderAlphaBlendedNodes = 0x00000008
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	extern VkDescriptorSetLayout descriptorSetLayoutImage;
 | 
						extern VkDescriptorSetLayout descriptorSetLayoutImage;
 | 
				
			||||||
	extern VkDescriptorSetLayout descriptorSetLayoutUbo;
 | 
						extern VkDescriptorSetLayout descriptorSetLayoutUbo;
 | 
				
			||||||
	extern VkMemoryPropertyFlags memoryPropertyFlags;
 | 
						extern VkMemoryPropertyFlags memoryPropertyFlags;
 | 
				
			||||||
	extern uint32_t descriptorBindingFlags;
 | 
						extern uint32_t descriptorBindingFlags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// The vertex layout for the samples' model
 | 
						// A glTF texture stores a reference to the image and a sampler
 | 
				
			||||||
	struct Vertex {
 | 
						struct Texture {
 | 
				
			||||||
		glm::vec3 pos;
 | 
							int32_t imageIndex;
 | 
				
			||||||
		glm::vec3 normal;
 | 
							vks::VulkanDevice* device = nullptr;
 | 
				
			||||||
		glm::vec2 uv;
 | 
							VkImage image;
 | 
				
			||||||
		glm::vec3 color;
 | 
							VkImageLayout imageLayout;
 | 
				
			||||||
		glm::vec3 tangent;
 | 
							VkDeviceMemory deviceMemory;
 | 
				
			||||||
		glm::vec3 jointIndices;
 | 
							VkImageView view;
 | 
				
			||||||
		glm::vec3 jointWeights;
 | 
							uint32_t width, height;
 | 
				
			||||||
 | 
							uint32_t mipLevels;
 | 
				
			||||||
 | 
							uint32_t layerCount;
 | 
				
			||||||
 | 
							VkDescriptorImageInfo descriptor;
 | 
				
			||||||
 | 
							VkSampler sampler;
 | 
				
			||||||
 | 
							void updateDescriptor();
 | 
				
			||||||
 | 
							void destroy();
 | 
				
			||||||
 | 
							void fromglTfImage(tinygltf::Image& gltfimage, std::string path, vks::VulkanDevice* device, VkQueue copyQueue);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Single vertex buffer for all primitives
 | 
						// A glTF material stores information in e.g. the texture that is attached to it and colors
 | 
				
			||||||
	struct Vertices {
 | 
						struct Material {
 | 
				
			||||||
		VkBuffer buffer;
 | 
							vks::VulkanDevice* device = nullptr;
 | 
				
			||||||
		VkDeviceMemory memory;
 | 
							enum AlphaMode { ALPHAMODE_OPAQUE, ALPHAMODE_MASK, ALPHAMODE_BLEND };
 | 
				
			||||||
	} vertices;
 | 
							AlphaMode alphaMode = ALPHAMODE_OPAQUE;
 | 
				
			||||||
 | 
							float alphaCutoff = 1.0f;
 | 
				
			||||||
 | 
							float metallicFactor = 1.0f;
 | 
				
			||||||
 | 
							float roughnessFactor = 1.0f;
 | 
				
			||||||
 | 
							glm::vec4 baseColorFactor = glm::vec4(1.0f);
 | 
				
			||||||
 | 
							glTFModel::Texture* baseColorTexture = nullptr;
 | 
				
			||||||
 | 
							glTFModel::Texture* metallicRoughnessTexture = nullptr;
 | 
				
			||||||
 | 
							glTFModel::Texture* normalTexture = nullptr;
 | 
				
			||||||
 | 
							glTFModel::Texture* occlusionTexture = nullptr;
 | 
				
			||||||
 | 
							glTFModel::Texture* emissiveTexture = nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Single index buffer for all primitives
 | 
							glTFModel::Texture* specularGlossinessTexture;
 | 
				
			||||||
	struct Indices {
 | 
							glTFModel::Texture* diffuseTexture;
 | 
				
			||||||
		int count;
 | 
					 | 
				
			||||||
		VkBuffer buffer;
 | 
					 | 
				
			||||||
		VkDeviceMemory memory;
 | 
					 | 
				
			||||||
	} indices;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// The following structures roughly represent the glTF scene structure
 | 
							VkDescriptorSet descriptorSet = VK_NULL_HANDLE;
 | 
				
			||||||
	// To keep things simple, they only contain those properties that are required for this sample
 | 
					
 | 
				
			||||||
	struct Node;
 | 
							Material(vks::VulkanDevice* device) : device(device) {};
 | 
				
			||||||
 | 
							void createDescriptorSet(VkDescriptorPool descriptorPool, VkDescriptorSetLayout descriptorSetLayout, uint32_t descriptorBindingFlags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// A primitive contains the data for a single draw call
 | 
						// A primitive contains the data for a single draw call
 | 
				
			||||||
	struct Primitive {
 | 
						struct Primitive {
 | 
				
			||||||
		uint32_t firstIndex;
 | 
							uint32_t firstIndex;
 | 
				
			||||||
		uint32_t indexCount;
 | 
							uint32_t indexCount;
 | 
				
			||||||
		int32_t materialIndex;
 | 
							uint32_t firstVertex;
 | 
				
			||||||
 | 
							uint32_t vertexCount;
 | 
				
			||||||
 | 
							Material& material;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							struct Dimensions {
 | 
				
			||||||
 | 
								glm::vec3 min = glm::vec3(FLT_MAX);
 | 
				
			||||||
 | 
								glm::vec3 max = glm::vec3(-FLT_MAX);
 | 
				
			||||||
 | 
								glm::vec3 size;
 | 
				
			||||||
 | 
								glm::vec3 center;
 | 
				
			||||||
 | 
								float radius;
 | 
				
			||||||
 | 
							} dimensions;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							void setDimensions(glm::vec3 min, glm::vec3 max);
 | 
				
			||||||
 | 
							Primitive(uint32_t firstIndex, uint32_t indexCount, Material& material) : firstIndex(firstIndex), indexCount(indexCount), material(material) {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Contains the node's (optional) geometry and can be made up of an arbitrary number of primitives
 | 
						// Contains the node's (optional) geometry and can be made up of an arbitrary number of primitives
 | 
				
			||||||
	struct Mesh {
 | 
						struct Mesh {
 | 
				
			||||||
		std::vector<Primitive> primitives;
 | 
							vks::VulkanDevice* device;
 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// A node represents an object in the glTF scene graph
 | 
							std::vector<Primitive*> primitives;
 | 
				
			||||||
	struct Node {
 | 
							std::string name;
 | 
				
			||||||
		Node* parent;
 | 
					
 | 
				
			||||||
		uint32_t index;
 | 
							struct UniformBuffer {
 | 
				
			||||||
		std::vector<Node*>  children;
 | 
								VkBuffer buffer;
 | 
				
			||||||
		Mesh mesh;
 | 
								VkDeviceMemory memory;
 | 
				
			||||||
		glm::vec3 translation{};
 | 
								VkDescriptorBufferInfo descriptor;
 | 
				
			||||||
		glm::vec3 scale{ 1.0f };
 | 
								VkDescriptorSet descriptorSet = VK_NULL_HANDLE;
 | 
				
			||||||
		glm::quat rotation{};
 | 
								void* mapped;
 | 
				
			||||||
		int32_t             skin = -1;
 | 
							} uniformBuffer;
 | 
				
			||||||
		glm::mat4 getLocalMatrix()
 | 
					
 | 
				
			||||||
		{
 | 
							struct UniformBlock {
 | 
				
			||||||
			return bAnimateNode ? glm::translate(glm::mat4(1.0f), translation) * glm::mat4(rotation) * glm::scale(glm::mat4(1.0f), scale) : matrix;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
			glm::mat4 matrix;
 | 
								glm::mat4 matrix;
 | 
				
			||||||
		bool bAnimateNode = false;
 | 
								glm::mat4 jointMatrix[64]{};
 | 
				
			||||||
 | 
								float jointCount{ 0 };
 | 
				
			||||||
		~Node() {
 | 
							} uniformBlock;
 | 
				
			||||||
			for (auto& child : children) {
 | 
					 | 
				
			||||||
				delete child;
 | 
					 | 
				
			||||||
			};
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Mesh(vks::VulkanDevice* device, glm::mat4 matrix);
 | 
				
			||||||
 | 
							~Mesh();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
	// material data for pbr
 | 
					 | 
				
			||||||
	struct MaterialData
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		vks::Buffer buffer;
 | 
					 | 
				
			||||||
		VkDescriptorSet descriptorSet;
 | 
					 | 
				
			||||||
		struct Values
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			glm::vec3 emissiveFactor;
 | 
					 | 
				
			||||||
			glm::vec4 baseColorFactor;
 | 
					 | 
				
			||||||
		}values;
 | 
					 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	};
 | 
						struct Node;
 | 
				
			||||||
	// A glTF material stores information in e.g. the texture that is attached to it and colors
 | 
					 | 
				
			||||||
	struct Material {
 | 
					 | 
				
			||||||
		glm::vec4 baseColorFactor = glm::vec4(1.0f);
 | 
					 | 
				
			||||||
		uint32_t baseColorTextureIndex;
 | 
					 | 
				
			||||||
		uint32_t normalMapTextureIndex;
 | 
					 | 
				
			||||||
		uint32_t matalicRoughTextureIndex;
 | 
					 | 
				
			||||||
		int32_t emissiveTextureIndex = -1;
 | 
					 | 
				
			||||||
		MaterialData materialData;
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Contains the texture for a single glTF image
 | 
						/*
 | 
				
			||||||
	// Images may be reused by texture objects and are as such separated
 | 
							glTF skin
 | 
				
			||||||
	struct Image {
 | 
						*/
 | 
				
			||||||
		vks::Texture2D texture;
 | 
					 | 
				
			||||||
		// We also store (and create) a descriptor set that's used to access this texture from the fragment shader
 | 
					 | 
				
			||||||
		VkDescriptorSet descriptorSet;
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// A glTF texture stores a reference to the image and a sampler
 | 
					 | 
				
			||||||
	// In this sample, we are only interested in the image
 | 
					 | 
				
			||||||
	struct Texture {
 | 
					 | 
				
			||||||
		int32_t imageIndex;
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// structure of skin
 | 
					 | 
				
			||||||
	struct Skin {
 | 
						struct Skin {
 | 
				
			||||||
		std::string name;
 | 
							std::string name;
 | 
				
			||||||
		Node* skeletonRoot = nullptr;
 | 
							Node* skeletonRoot = nullptr;
 | 
				
			||||||
		std::vector<glm::mat4> inverseBindMatrices;
 | 
							std::vector<glm::mat4> inverseBindMatrices;
 | 
				
			||||||
		std::vector<Node*> joints;
 | 
							std::vector<Node*> joints;
 | 
				
			||||||
		vks::Buffer ssbo;
 | 
						};
 | 
				
			||||||
		VkDescriptorSet descriptorSet;
 | 
						// A node represents an object in the glTF scene graph
 | 
				
			||||||
 | 
						struct Node {
 | 
				
			||||||
 | 
							Node* parent;
 | 
				
			||||||
 | 
							uint32_t index;
 | 
				
			||||||
 | 
							std::vector<Node*> children;
 | 
				
			||||||
 | 
							glm::mat4 matrix;
 | 
				
			||||||
 | 
							std::string name;
 | 
				
			||||||
 | 
							Mesh* mesh;
 | 
				
			||||||
 | 
							Skin* skin;
 | 
				
			||||||
 | 
							int32_t skinIndex = -1;
 | 
				
			||||||
 | 
							glm::vec3 translation{};
 | 
				
			||||||
 | 
							glm::vec3 scale{ 1.0f };
 | 
				
			||||||
 | 
							glm::quat rotation{};
 | 
				
			||||||
 | 
							glm::mat4 localMatrix();
 | 
				
			||||||
 | 
							glm::mat4 getMatrix();
 | 
				
			||||||
 | 
							void update();
 | 
				
			||||||
 | 
							~Node();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
							glTF default vertex layout with easy Vulkan mapping functions
 | 
				
			||||||
 | 
						*/
 | 
				
			||||||
 | 
						enum class VertexComponent { Position, Normal, UV, Color, Tangent, Joint0, Weight0 };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// The vertex layout for the samples' model
 | 
				
			||||||
 | 
						struct Vertex {
 | 
				
			||||||
 | 
							glm::vec3 pos;
 | 
				
			||||||
 | 
							glm::vec3 normal;
 | 
				
			||||||
 | 
							glm::vec2 uv;
 | 
				
			||||||
 | 
							glm::vec4 color;
 | 
				
			||||||
 | 
							glm::vec4 joint0;
 | 
				
			||||||
 | 
							glm::vec4 weight0;
 | 
				
			||||||
 | 
							glm::vec4 tangent;
 | 
				
			||||||
 | 
							static VkVertexInputBindingDescription vertexInputBindingDescription;
 | 
				
			||||||
 | 
							static std::vector<VkVertexInputAttributeDescription> vertexInputAttributeDescriptions;
 | 
				
			||||||
 | 
							static VkPipelineVertexInputStateCreateInfo pipelineVertexInputStateCreateInfo;
 | 
				
			||||||
 | 
							static VkVertexInputBindingDescription inputBindingDescription(uint32_t binding);
 | 
				
			||||||
 | 
							static VkVertexInputAttributeDescription inputAttributeDescription(uint32_t binding, uint32_t location, VertexComponent component);
 | 
				
			||||||
 | 
							static std::vector<VkVertexInputAttributeDescription> inputAttributeDescriptions(uint32_t binding, const std::vector<VertexComponent> components);
 | 
				
			||||||
 | 
							/** @brief Returns the default pipeline vertex input state create info structure for the requested vertex components */
 | 
				
			||||||
 | 
							static VkPipelineVertexInputStateCreateInfo* getPipelineVertexInputState(const std::vector<VertexComponent> components);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct AnimationSampler
 | 
						struct AnimationSampler
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		std::string interpolation;
 | 
							enum InterpolationType { LINEAR, STEP, CUBICSPLINE };
 | 
				
			||||||
 | 
							InterpolationType interpolation;
 | 
				
			||||||
		std::vector<float> inputs;
 | 
							std::vector<float> inputs;
 | 
				
			||||||
		std::vector<glm::vec4> outputsVec4;
 | 
							std::vector<glm::vec4> outputsVec4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -172,7 +224,8 @@ namespace VulkanglTFModel
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct AnimationChannel
 | 
						struct AnimationChannel
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		std::string path;
 | 
							enum PathType { TRANSLATION, ROTATION, SCALE };
 | 
				
			||||||
 | 
							PathType path;
 | 
				
			||||||
		Node* node;
 | 
							Node* node;
 | 
				
			||||||
		uint32_t samplerIndex;
 | 
							uint32_t samplerIndex;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -190,53 +243,68 @@ namespace VulkanglTFModel
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
		Model data
 | 
							glTF model loading and rendering class
 | 
				
			||||||
	*/
 | 
						*/
 | 
				
			||||||
	std::vector<Image> images;
 | 
						class Model {
 | 
				
			||||||
 | 
						private:
 | 
				
			||||||
 | 
							glTFModel::Texture* getTexture(uint32_t index);
 | 
				
			||||||
 | 
							glTFModel::Texture emptyTexture;
 | 
				
			||||||
 | 
							void createEmptyTexture(VkQueue transferQueue);
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							vks::VulkanDevice* device;
 | 
				
			||||||
 | 
							VkDescriptorPool descriptorPool;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							struct Vertices {
 | 
				
			||||||
 | 
								int count;
 | 
				
			||||||
 | 
								VkBuffer buffer;
 | 
				
			||||||
 | 
								VkDeviceMemory memory;
 | 
				
			||||||
 | 
							} vertices;
 | 
				
			||||||
 | 
							struct Indices {
 | 
				
			||||||
 | 
								int count;
 | 
				
			||||||
 | 
								VkBuffer buffer;
 | 
				
			||||||
 | 
								VkDeviceMemory memory;
 | 
				
			||||||
 | 
							} indices;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							std::vector<Node*> nodes;
 | 
				
			||||||
 | 
							std::vector<Node*> linearNodes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							std::vector<Skin*> skins;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		std::vector<Texture> textures;
 | 
							std::vector<Texture> textures;
 | 
				
			||||||
		std::vector<Material> materials;
 | 
							std::vector<Material> materials;
 | 
				
			||||||
	std::vector<Node*> nodes;
 | 
					 | 
				
			||||||
	std::vector<Skin> skins;
 | 
					 | 
				
			||||||
		std::vector<Animation> animations;
 | 
							std::vector<Animation> animations;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	uint32_t activeAnimation = 0;
 | 
							struct Dimensions {
 | 
				
			||||||
 | 
								glm::vec3 min = glm::vec3(FLT_MAX);
 | 
				
			||||||
 | 
								glm::vec3 max = glm::vec3(-FLT_MAX);
 | 
				
			||||||
 | 
								glm::vec3 size;
 | 
				
			||||||
 | 
								glm::vec3 center;
 | 
				
			||||||
 | 
								float radius;
 | 
				
			||||||
 | 
							} dimensions;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							bool metallicRoughnessWorkflow = true;
 | 
				
			||||||
 | 
							bool buffersBound = false;
 | 
				
			||||||
 | 
							std::string path;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Model() {};
 | 
				
			||||||
	//VulkanglTFModel();
 | 
							~Model();
 | 
				
			||||||
	~VulkanglTFModel()
 | 
							void loadNode(glTFModel::Node* parent, const tinygltf::Node& node, uint32_t nodeIndex, const tinygltf::Model& model, std::vector<uint32_t>& indexBuffer, std::vector<Vertex>& vertexBuffer, float globalscale);
 | 
				
			||||||
	{
 | 
							void loadSkins(tinygltf::Model& gltfModel);
 | 
				
			||||||
		for (auto node : nodes) {
 | 
							void loadImages(tinygltf::Model& gltfModel, vks::VulkanDevice* device, VkQueue transferQueue);
 | 
				
			||||||
			delete node;
 | 
							void loadMaterials(tinygltf::Model& gltfModel);
 | 
				
			||||||
		}
 | 
							void loadAnimations(tinygltf::Model& gltfModel);
 | 
				
			||||||
		// Release all Vulkan resources allocated for the model
 | 
							void loadFromFile(std::string filename, vks::VulkanDevice* device, VkQueue transferQueue, uint32_t fileLoadingFlags = glTFModel::FileLoadingFlags::None, float scale = 1.0f);
 | 
				
			||||||
		vkDestroyBuffer(vulkanDevice->logicalDevice, vertices.buffer, nullptr);
 | 
							void bindBuffers(VkCommandBuffer commandBuffer);
 | 
				
			||||||
		vkFreeMemory(vulkanDevice->logicalDevice, vertices.memory, nullptr);
 | 
							void drawNode(Node* node, VkCommandBuffer commandBuffer, uint32_t renderFlags = 0, VkPipelineLayout pipelineLayout = VK_NULL_HANDLE, uint32_t bindImageSet = 1);
 | 
				
			||||||
		vkDestroyBuffer(vulkanDevice->logicalDevice, indices.buffer, nullptr);
 | 
							void draw(VkCommandBuffer commandBuffer, uint32_t renderFlags = 0, VkPipelineLayout pipelineLayout = VK_NULL_HANDLE, uint32_t bindImageSet = 1);
 | 
				
			||||||
		vkFreeMemory(vulkanDevice->logicalDevice, indices.memory, nullptr);
 | 
							void getNodeDimensions(Node* node, glm::vec3& min, glm::vec3& max);
 | 
				
			||||||
		for (auto& material : materials)
 | 
							void getSceneDimensions();
 | 
				
			||||||
		{
 | 
							void updateAnimation(uint32_t index, float time);
 | 
				
			||||||
			material.materialData.buffer.destroy();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		for (Image image : images) {
 | 
					 | 
				
			||||||
			vkDestroyImageView(vulkanDevice->logicalDevice, image.texture.view, nullptr);
 | 
					 | 
				
			||||||
			vkDestroyImage(vulkanDevice->logicalDevice, image.texture.image, nullptr);
 | 
					 | 
				
			||||||
			vkDestroySampler(vulkanDevice->logicalDevice, image.texture.sampler, nullptr);
 | 
					 | 
				
			||||||
			vkFreeMemory(vulkanDevice->logicalDevice, image.texture.deviceMemory, nullptr);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	void      loadImages(tinygltf::Model& input);
 | 
					 | 
				
			||||||
	void      loadTextures(tinygltf::Model& input);
 | 
					 | 
				
			||||||
	void      loadMaterials(tinygltf::Model& input);
 | 
					 | 
				
			||||||
		Node* findNode(Node* parent, uint32_t index);
 | 
							Node* findNode(Node* parent, uint32_t index);
 | 
				
			||||||
		Node* nodeFromIndex(uint32_t index);
 | 
							Node* nodeFromIndex(uint32_t index);
 | 
				
			||||||
	//void      loadSkins(tinygltf::Model& input);
 | 
							void prepareNodeDescriptor(glTFModel::Node* node, VkDescriptorSetLayout descriptorSetLayout);
 | 
				
			||||||
	void      loadAnimations(tinygltf::Model& input);
 | 
					 | 
				
			||||||
	void      loadNode(const tinygltf::Node& inputNode, const tinygltf::Model& input, VulkanglTFModel::Node* parent, uint32_t nodeIndex, std::vector<uint32_t>& indexBuffer, std::vector<VulkanglTFModel::Vertex>& vertexBuffer);
 | 
					 | 
				
			||||||
	glm::mat4 getNodeMatrix(VulkanglTFModel::Node* node);
 | 
					 | 
				
			||||||
	void updateNodeMatrix(Node* node, std::vector<glm::mat4>& nodeMatrics);
 | 
					 | 
				
			||||||
	//void      updateJoints(VulkanglTFModel::Node* node);
 | 
					 | 
				
			||||||
	void      updateAnimation(float deltaTime, vks::Buffer& buffer);
 | 
					 | 
				
			||||||
	void drawNode(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout, VulkanglTFModel::Node* node, bool bPushConstants);
 | 
					 | 
				
			||||||
	void      draw(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout, bool flag);
 | 
					 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
		Reference in New Issue