Create empty texture to be used with materials that miss e.g. normal maps
This commit is contained in:
parent
9aea7d1550
commit
144c0b66c0
2 changed files with 111 additions and 1 deletions
|
|
@ -613,6 +613,110 @@ vkglTF::Texture* vkglTF::Model::getTexture(uint32_t index)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vkglTF::Model::createEmptyTexture(VkQueue transferQueue)
|
||||||
|
{
|
||||||
|
emptyTexture.device = device;
|
||||||
|
emptyTexture.width = 1;
|
||||||
|
emptyTexture.height = 1;
|
||||||
|
emptyTexture.layerCount = 1;
|
||||||
|
emptyTexture.mipLevels = 1;
|
||||||
|
|
||||||
|
size_t bufferSize = emptyTexture.width * emptyTexture.height * 4;
|
||||||
|
unsigned char* buffer = new unsigned char[bufferSize];
|
||||||
|
memset(buffer, 0, bufferSize);
|
||||||
|
|
||||||
|
VkBuffer stagingBuffer;
|
||||||
|
VkDeviceMemory stagingMemory;
|
||||||
|
VkBufferCreateInfo bufferCreateInfo = vks::initializers::bufferCreateInfo();
|
||||||
|
bufferCreateInfo.size = bufferSize;
|
||||||
|
// 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));
|
||||||
|
|
||||||
|
// Copy texture data into staging buffer
|
||||||
|
uint8_t* data;
|
||||||
|
VK_CHECK_RESULT(vkMapMemory(device->logicalDevice, stagingMemory, 0, memReqs.size, 0, (void**)&data));
|
||||||
|
memcpy(data, buffer, bufferSize);
|
||||||
|
vkUnmapMemory(device->logicalDevice, stagingMemory);
|
||||||
|
|
||||||
|
VkBufferImageCopy bufferCopyRegion = {};
|
||||||
|
bufferCopyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
|
bufferCopyRegion.imageSubresource.layerCount = 1;
|
||||||
|
bufferCopyRegion.imageExtent.width = emptyTexture.width;
|
||||||
|
bufferCopyRegion.imageExtent.height = emptyTexture.height;
|
||||||
|
bufferCopyRegion.imageExtent.depth = 1;
|
||||||
|
|
||||||
|
// Create optimal tiled target image
|
||||||
|
VkImageCreateInfo imageCreateInfo = vks::initializers::imageCreateInfo();
|
||||||
|
imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
|
||||||
|
imageCreateInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
|
||||||
|
imageCreateInfo.mipLevels = 1;
|
||||||
|
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 = { emptyTexture.width, emptyTexture.height, 1 };
|
||||||
|
imageCreateInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||||
|
VK_CHECK_RESULT(vkCreateImage(device->logicalDevice, &imageCreateInfo, nullptr, &emptyTexture.image));
|
||||||
|
|
||||||
|
vkGetImageMemoryRequirements(device->logicalDevice, emptyTexture.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, &emptyTexture.deviceMemory));
|
||||||
|
VK_CHECK_RESULT(vkBindImageMemory(device->logicalDevice, emptyTexture.image, emptyTexture.deviceMemory, 0));
|
||||||
|
|
||||||
|
VkImageSubresourceRange subresourceRange{};
|
||||||
|
subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
|
subresourceRange.baseMipLevel = 0;
|
||||||
|
subresourceRange.levelCount = 1;
|
||||||
|
subresourceRange.layerCount = 1;
|
||||||
|
|
||||||
|
VkCommandBuffer copyCmd = device->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);
|
||||||
|
vks::tools::setImageLayout(copyCmd, emptyTexture.image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, subresourceRange);
|
||||||
|
vkCmdCopyBufferToImage(copyCmd, stagingBuffer, emptyTexture.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &bufferCopyRegion);
|
||||||
|
vks::tools::setImageLayout(copyCmd, emptyTexture.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, subresourceRange);
|
||||||
|
device->flushCommandBuffer(copyCmd, transferQueue);
|
||||||
|
emptyTexture.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||||
|
|
||||||
|
// Clean up staging resources
|
||||||
|
vkFreeMemory(device->logicalDevice, stagingMemory, nullptr);
|
||||||
|
vkDestroyBuffer(device->logicalDevice, stagingBuffer, nullptr);
|
||||||
|
|
||||||
|
VkSamplerCreateInfo samplerCreateInfo = vks::initializers::samplerCreateInfo();
|
||||||
|
samplerCreateInfo.magFilter = VK_FILTER_LINEAR;
|
||||||
|
samplerCreateInfo.minFilter = VK_FILTER_LINEAR;
|
||||||
|
samplerCreateInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
|
||||||
|
samplerCreateInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
||||||
|
samplerCreateInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
||||||
|
samplerCreateInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
||||||
|
samplerCreateInfo.compareOp = VK_COMPARE_OP_NEVER;
|
||||||
|
samplerCreateInfo.maxAnisotropy = 1.0f;
|
||||||
|
VK_CHECK_RESULT(vkCreateSampler(device->logicalDevice, &samplerCreateInfo, nullptr, &emptyTexture.sampler));
|
||||||
|
|
||||||
|
VkImageViewCreateInfo viewCreateInfo = vks::initializers::imageViewCreateInfo();
|
||||||
|
viewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||||
|
viewCreateInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
|
||||||
|
viewCreateInfo.components = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
|
||||||
|
viewCreateInfo.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
|
||||||
|
viewCreateInfo.subresourceRange.levelCount = 1;
|
||||||
|
viewCreateInfo.image = emptyTexture.image;
|
||||||
|
VK_CHECK_RESULT(vkCreateImageView(device->logicalDevice, &viewCreateInfo, nullptr, &emptyTexture.view));
|
||||||
|
|
||||||
|
emptyTexture.descriptor.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||||
|
emptyTexture.descriptor.imageView = emptyTexture.view;
|
||||||
|
emptyTexture.descriptor.sampler = emptyTexture.sampler;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
glTF model loading and rendering class
|
glTF model loading and rendering class
|
||||||
*/
|
*/
|
||||||
|
|
@ -637,6 +741,7 @@ vkglTF::Model::~Model()
|
||||||
descriptorSetLayoutImage = VK_NULL_HANDLE;
|
descriptorSetLayoutImage = VK_NULL_HANDLE;
|
||||||
}
|
}
|
||||||
vkDestroyDescriptorPool(device->logicalDevice, descriptorPool, nullptr);
|
vkDestroyDescriptorPool(device->logicalDevice, descriptorPool, nullptr);
|
||||||
|
emptyTexture.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
void vkglTF::Model::loadNode(vkglTF::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 vkglTF::Model::loadNode(vkglTF::Node *parent, const tinygltf::Node &node, uint32_t nodeIndex, const tinygltf::Model &model, std::vector<uint32_t>& indexBuffer, std::vector<Vertex>& vertexBuffer, float globalscale)
|
||||||
|
|
@ -876,6 +981,8 @@ void vkglTF::Model::loadImages(tinygltf::Model &gltfModel, vks::VulkanDevice *de
|
||||||
texture.fromglTfImage(image, path, device, transferQueue);
|
texture.fromglTfImage(image, path, device, transferQueue);
|
||||||
textures.push_back(texture);
|
textures.push_back(texture);
|
||||||
}
|
}
|
||||||
|
// Create an empty texture to be used for empty material images
|
||||||
|
createEmptyTexture(transferQueue);
|
||||||
}
|
}
|
||||||
|
|
||||||
void vkglTF::Model::loadMaterials(tinygltf::Model &gltfModel)
|
void vkglTF::Model::loadMaterials(tinygltf::Model &gltfModel)
|
||||||
|
|
@ -900,6 +1007,8 @@ void vkglTF::Model::loadMaterials(tinygltf::Model &gltfModel)
|
||||||
}
|
}
|
||||||
if (mat.additionalValues.find("normalTexture") != mat.additionalValues.end()) {
|
if (mat.additionalValues.find("normalTexture") != mat.additionalValues.end()) {
|
||||||
material.normalTexture = getTexture(gltfModel.textures[mat.additionalValues["normalTexture"].TextureIndex()].source);
|
material.normalTexture = getTexture(gltfModel.textures[mat.additionalValues["normalTexture"].TextureIndex()].source);
|
||||||
|
} else {
|
||||||
|
material.normalTexture = &emptyTexture;
|
||||||
}
|
}
|
||||||
if (mat.additionalValues.find("emissiveTexture") != mat.additionalValues.end()) {
|
if (mat.additionalValues.find("emissiveTexture") != mat.additionalValues.end()) {
|
||||||
material.emissiveTexture = getTexture(gltfModel.textures[mat.additionalValues["emissiveTexture"].TextureIndex()].source);
|
material.emissiveTexture = getTexture(gltfModel.textures[mat.additionalValues["emissiveTexture"].TextureIndex()].source);
|
||||||
|
|
@ -924,7 +1033,6 @@ void vkglTF::Model::loadMaterials(tinygltf::Model &gltfModel)
|
||||||
}
|
}
|
||||||
// Push a default material at the end of the list for meshes with no material assigned
|
// Push a default material at the end of the list for meshes with no material assigned
|
||||||
materials.push_back(Material(device));
|
materials.push_back(Material(device));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void vkglTF::Model::loadAnimations(tinygltf::Model &gltfModel)
|
void vkglTF::Model::loadAnimations(tinygltf::Model &gltfModel)
|
||||||
|
|
|
||||||
|
|
@ -249,6 +249,8 @@ namespace vkglTF
|
||||||
class Model {
|
class Model {
|
||||||
private:
|
private:
|
||||||
vkglTF::Texture* getTexture(uint32_t index);
|
vkglTF::Texture* getTexture(uint32_t index);
|
||||||
|
vkglTF::Texture emptyTexture;
|
||||||
|
void createEmptyTexture(VkQueue transferQueue);
|
||||||
public:
|
public:
|
||||||
vks::VulkanDevice* device;
|
vks::VulkanDevice* device;
|
||||||
VkDescriptorPool descriptorPool;
|
VkDescriptorPool descriptorPool;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue