08/20/2020
文章目录
纹理贴图(Texture Mapping)
这边一共两个知识点:
- 加载外部图片作为纹理
- 如何过滤纹理,生成贴图
纹理属性
用到纹理贴图,至少需要设置下面的所有属性
struct Texture
{
VkImage image;
VkImageLayout imageLayout;
VkDeviceMemory deviceMemory;
VkImageView view;
uint32_t width, height;
uint32_t mipLevels; //采样器的过滤器,贴图
uint32_t layerCount; //用于天空盒,或者贴图数组
VkDescriptorImageInfo descriptor; //用于写入到描述符集合中
VkSampler sampler; //采样器
} texture;
加载图片
图片格式有很多,比如png,jpg,ktx等等,通常使用第三库来加载图片
- 可以获得图片长宽
- 图片格式
- 图片miplevels
void loadTexture()
{
// We use the Khronos texture format (https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/)
std::string filename = getAssetPath() + "textures/metalplate01_rgba.ktx";
// Texture data contains 4 channels (RGBA) with unnormalized 8-bit values, this is the most commonly supported format
VkFormat format = VK_FORMAT_R8G8B8A8_UNORM;
ktxResult result;
ktxTexture* ktxTexture;
texture.width = ktxTexture->baseWidth;
texture.height = ktxTexture->baseHeight;
texture.mipLevels = ktxTexture->numLevels;
ktx_uint8_t *ktxTextureData = ktxTexture_GetData(ktxTexture);
ktx_size_t ktxTextureSize = ktxTexture_GetSize(ktxTexture);
//是否使用linear sampling
//使用stageing buffer来存储,再传输数据
}
临时缓冲区储存图片信息
- 创建临时缓冲区
- 分配内存
- memcpy 拷贝数据
// Copy data to an optimal tiled image
// This loads the texture data into a host local buffer that is copied to the optimal tiled image on the device
// Create a host-visible staging buffer that contains the raw image data
// This buffer will be the data source for copying texture data to the optimal tiled image on the device
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, &bufferCreateInfo, nullptr, &stagingBuffer));
// Get memory requirements for the staging buffer (alignment, memory type bits)
vkGetBufferMemoryRequirements(device, stagingBuffer, &memReqs);
memAllocInfo.allocationSize = memReqs.size;
// Get memory type index for a host visible buffer
memAllocInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
VK_CHECK_RESULT(vkAllocateMemory(device, &memAllocInfo, nullptr, &stagingMemory));
VK_CHECK_RESULT(vkBindBufferMemory(device, stagingBuffer, stagingMemory, 0