- 可以resize
- 套用貼圖
STB讀取圖片
#define STB_IMAGE_IMPLEMENTATION #include <stb_image.h> |
void ltn::Image::load_texture(const char* path) { // STBI_rgb_alpha value forces the image to be loaded with an alpha channel, even if it doesn't have one. // The pixels are laid out row by row with 4 bytes per pixel in the case of STBI_rgb_alpha. stbi_uc* pixels = stbi_load(path, &m_width, &m_height, &m_channel, STBI_rgb_alpha); VkDeviceSize imageSize = m_width * m_height * 4; if (!pixels) { throw std::runtime_error("failed to load texture image!"); } // create a buffer to hold the pixel data createBuffer( m_core_instance.get_device(), m_core_instance.get_physical_device(), imageSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, m_staging_buffer, m_staging_buffer_memory); void* data; vkMapMemory(m_core_instance.get_device(), m_staging_buffer_memory, 0, imageSize, 0, &data); memcpy(data, pixels, static_cast<size_t>(imageSize)); vkUnmapMemory(m_core_instance.get_device(), m_staging_buffer_memory); stbi_image_free(pixels); // move buffer to image memory create_texture(); createTextureImageView(); createTextureSampler(); //---------------- // Descriptor //---------------- create_descriptor_pool(); createDescriptorSetLayout(); create_descriptor(); } |
Image view
void ltn::Image::createTextureImageView() { VkImageViewCreateInfo viewInfo{}; viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; viewInfo.image = m_texture_image; viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; viewInfo.format = VK_FORMAT_R8G8B8A8_SRGB; viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; viewInfo.subresourceRange.baseMipLevel = 0; viewInfo.subresourceRange.levelCount = 1; viewInfo.subresourceRange.baseArrayLayer = 0; viewInfo.subresourceRange.layerCount = 1; if (vkCreateImageView( m_core_instance.get_device(), &viewInfo, nullptr, &m_texture_imageView) != VK_SUCCESS) { throw std::runtime_error("failed to create texture image view!"); } } |
Sampler
void ltn::Image::createTextureSampler() { // Get maxAnisotropy VkPhysicalDeviceProperties properties{}; vkGetPhysicalDeviceProperties(m_core_instance.get_physical_device(), &properties); VkSamplerCreateInfo samplerInfo{}; samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; samplerInfo.magFilter = VK_FILTER_LINEAR; samplerInfo.minFilter = VK_FILTER_LINEAR; samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; //samplerInfo.anisotropyEnable = VK_TRUE; samplerInfo.maxAnisotropy = properties.limits.maxSamplerAnisotropy; samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK; samplerInfo.unnormalizedCoordinates = VK_FALSE; samplerInfo.compareEnable = VK_FALSE; samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS; samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; samplerInfo.mipLodBias = 0.0f; samplerInfo.minLod = 0.0f; samplerInfo.maxLod = 0.0f; samplerInfo.anisotropyEnable = VK_FALSE; // Temp samplerInfo.maxAnisotropy = 1.0f; if (vkCreateSampler(m_core_instance.get_device(), &samplerInfo, nullptr, &m_texture_sampler) != VK_SUCCESS) { throw std::runtime_error("failed to create texture sampler!"); } } |
在Pipeline要設定
pipelineLayoutInfo.setLayoutCount = descriptors->size(); pipelineLayoutInfo.pSetLayouts = descriptors->data(); |
#version 450 layout(location = 0) in vec3 fragColor; layout(location = 1) in vec2 fragTexCoord; layout(location = 0) out vec4 outColor; layout(set=1,binding = 0) uniform sampler2D texSampler; void main() { outColor = texture(texSampler, fragTexCoord); } |
- 未來優化方向: 應該規劃好哪些元件會綁到哪個descriptorSet編號。
std::vector<VkDescriptorSetLayout>* ltn::GameObject::get_all_descriptorLayouts() { for (int i = 0; i < m_components.size(); ++i) { auto descrip = m_components[i]->get_descriptorset_layout(); if (descrip != NULL) { m_descriptorSetLayouts.push_back(descrip); } } return &m_descriptorSetLayouts; } |