coral_cubemap.cpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. #include "coral_cubemap.h"
  2. #include "coral_buffer.h"
  3. #include "vk_initializers.h"
  4. #include "stb_image.h"
  5. // STD
  6. #include <iostream>
  7. namespace coral_3d
  8. {
  9. coral_cubemap::coral_cubemap(coral_device &device, bool nearest_filter)
  10. : device_(device), file_names_({""}), width_(0), height_(0)
  11. , bytes_per_pixel_(0), mip_levels_(1), nearest_filter_(nearest_filter), sRGB_(false)
  12. {}
  13. coral_cubemap::~coral_cubemap()
  14. {
  15. vkDestroyImageView(device_.device(), image_view_, nullptr);
  16. vkDestroySampler(device_.device(), sampler_, nullptr);
  17. vmaDestroyImage(device_.allocator(), cubemap_image_.image, cubemap_image_.allocation);
  18. }
  19. bool coral_cubemap::init(const std::vector<std::string> &file_names, bool sRGB, bool flip)
  20. {
  21. stbi_set_flip_vertically_on_load(flip);
  22. file_names_ = file_names;
  23. sRGB_ = sRGB;
  24. return create();
  25. }
  26. bool coral_cubemap::create()
  27. {
  28. stbi_uc* pixels;
  29. // Load first face to get size
  30. pixels = stbi_load(file_names_[0].c_str(), &width_, &height_, &bytes_per_pixel_, STBI_rgb_alpha);
  31. if (!pixels)
  32. {
  33. std::cout << "Failed to load texture file " << file_names_[0] << std::endl;
  34. return false;
  35. }
  36. VkDeviceSize layer_size = width_ * height_ * 4;
  37. VkDeviceSize image_size = layer_size * NUMBER_OF_CUBEMAP_IMAGES;
  38. coral_buffer staging_buffer
  39. {
  40. device_,image_size,1,
  41. VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
  42. VMA_MEMORY_USAGE_AUTO,
  43. VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT
  44. };
  45. staging_buffer.map();
  46. staging_buffer.write_to_buffer(pixels, layer_size);
  47. stbi_image_free(pixels);
  48. // Load other 5 faces
  49. for (int i = 1; i < NUMBER_OF_CUBEMAP_IMAGES; ++i)
  50. {
  51. pixels = stbi_load(file_names_[i].c_str(), &width_, &height_, &bytes_per_pixel_, STBI_rgb_alpha);
  52. if (!pixels)
  53. {
  54. std::cout << "Failed to load texture file " << file_names_[i] << std::endl;
  55. return false;
  56. }
  57. staging_buffer.write_to_buffer(pixels, layer_size, layer_size * i);
  58. stbi_image_free(pixels);
  59. }
  60. // CREATE IMAGE
  61. image_format_ = sRGB_ ? VK_FORMAT_R8G8B8A8_SRGB : VK_FORMAT_R8G8B8A8_UNORM;
  62. create_image(image_format_);
  63. // Transition and copy image to buffer
  64. device_.transition_image_layout(cubemap_image_.image, image_format_, VK_IMAGE_LAYOUT_UNDEFINED,
  65. VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, NUMBER_OF_CUBEMAP_IMAGES, mip_levels_);
  66. device_.copy_buffer_to_image(staging_buffer.get_buffer(), cubemap_image_, width_, height_,
  67. NUMBER_OF_CUBEMAP_IMAGES);
  68. device_.transition_image_layout(cubemap_image_.image, image_format_, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
  69. VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, NUMBER_OF_CUBEMAP_IMAGES, mip_levels_);
  70. image_layout_ = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
  71. create_image_sampler();
  72. create_image_view();
  73. descriptor_image_info_.sampler = sampler_;
  74. descriptor_image_info_.imageLayout = image_layout_;
  75. descriptor_image_info_.imageView = image_view_;
  76. return true;
  77. }
  78. bool coral_cubemap::create_image(VkFormat format)
  79. {
  80. VkExtent3D img_extent;
  81. img_extent.width = static_cast<uint32_t>(width_);
  82. img_extent.height = static_cast<uint32_t>(height_);
  83. img_extent.depth = 1;
  84. VkImageCreateInfo create_info{vkinit::image_ci(
  85. format,
  86. VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
  87. img_extent)};
  88. create_info.mipLevels = mip_levels_;
  89. create_info.arrayLayers = NUMBER_OF_CUBEMAP_IMAGES;
  90. create_info.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
  91. VmaAllocationCreateInfo alloc_create_info{};
  92. alloc_create_info.usage = VMA_MEMORY_USAGE_GPU_ONLY;
  93. vmaCreateImage(device_.allocator(), &create_info, &alloc_create_info,
  94. &cubemap_image_.image, &cubemap_image_.allocation, nullptr);
  95. return true;
  96. }
  97. bool coral_cubemap::create_image_view()
  98. {
  99. VkImageViewCreateInfo image_info{ vkinit::image_view_ci(image_format_, cubemap_image_.image, VK_IMAGE_ASPECT_COLOR_BIT) };
  100. image_info.subresourceRange.levelCount = mip_levels_;
  101. image_info.subresourceRange.layerCount = NUMBER_OF_CUBEMAP_IMAGES;
  102. image_info.viewType = VK_IMAGE_VIEW_TYPE_CUBE;
  103. image_info.components = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
  104. if (vkCreateImageView(device_.device(), &image_info, nullptr, &image_view_) != VK_SUCCESS)
  105. throw std::runtime_error("ERROR! coral_cubemap::create_image_view() >> Failed to create image view!");
  106. return true;
  107. }
  108. bool coral_cubemap::create_image_sampler()
  109. {
  110. VkFilter filter = nearest_filter_ ? VK_FILTER_NEAREST : VK_FILTER_LINEAR;
  111. VkSamplerCreateInfo sampler_info{ vkinit::sampler_ci(filter, device_.properties.limits.maxSamplerAnisotropy) };
  112. sampler_info.maxLod = static_cast<float>(mip_levels_);
  113. if (vkCreateSampler(device_.device(), &sampler_info, nullptr, &sampler_) != VK_SUCCESS)
  114. throw std::runtime_error("ERROR! coral_cubemap::create_image_sampler() >> Failed to create texture sampler!");
  115. return true;
  116. }
  117. } // coral_3d