💿🐜 Antkeeper source code https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

143 lines
4.5 KiB

  1. /*
  2. * Copyright (C) 2021 Christopher J. Howard
  3. *
  4. * This file is part of Antkeeper source code.
  5. *
  6. * Antkeeper source code is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Antkeeper source code is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "resources/resource-loader.hpp"
  20. #include "resources/resource-manager.hpp"
  21. #include "resources/image.hpp"
  22. #include "gl/pixel-type.hpp"
  23. #include "gl/pixel-format.hpp"
  24. #include "gl/color-space.hpp"
  25. #include "gl/texture-2d.hpp"
  26. #include "gl/texture-wrapping.hpp"
  27. #include "gl/texture-filter.hpp"
  28. #include <sstream>
  29. #include <nlohmann/json.hpp>
  30. #include <physfs.h>
  31. template <>
  32. gl::texture_2d* resource_loader<gl::texture_2d>::load(resource_manager* resource_manager, PHYSFS_File* file)
  33. {
  34. // Read file into buffer
  35. std::size_t size = static_cast<int>(PHYSFS_fileLength(file));
  36. std::string buffer;
  37. buffer.resize(size);
  38. PHYSFS_readBytes(file, &buffer[0], size);
  39. // Parse json from file buffer
  40. nlohmann::json json = nlohmann::json::parse(buffer);
  41. // Read image filename
  42. std::string image_filename;
  43. if (auto element = json.find("image"); element != json.end())
  44. image_filename = element.value().get<std::string>();
  45. // Read color space
  46. gl::color_space color_space = gl::color_space::linear;
  47. if (auto element = json.find("color_space"); element != json.end())
  48. {
  49. std::string value = element.value().get<std::string>();
  50. if (value == "linear")
  51. color_space = gl::color_space::linear;
  52. else if (value == "srgb")
  53. color_space = gl::color_space::srgb;
  54. }
  55. // Read extension mode
  56. gl::texture_wrapping wrapping = gl::texture_wrapping::repeat;
  57. if (auto element = json.find("extension"); element != json.end())
  58. {
  59. std::string value = element.value().get<std::string>();
  60. if (value == "clip")
  61. wrapping = gl::texture_wrapping::clip;
  62. else if (value == "extend")
  63. wrapping = gl::texture_wrapping::extend;
  64. else if (value == "repeat")
  65. wrapping = gl::texture_wrapping::repeat;
  66. else if (value == "mirrored_repeat")
  67. wrapping = gl::texture_wrapping::mirrored_repeat;
  68. }
  69. // Read interpolation mode
  70. gl::texture_min_filter min_filter = gl::texture_min_filter::linear_mipmap_linear;
  71. gl::texture_mag_filter mag_filter = gl::texture_mag_filter::linear;
  72. if (auto element = json.find("interpolation"); element != json.end())
  73. {
  74. std::string value = element.value().get<std::string>();
  75. if (value == "linear")
  76. {
  77. min_filter = gl::texture_min_filter::linear_mipmap_linear;
  78. mag_filter = gl::texture_mag_filter::linear;
  79. }
  80. else if (value == "closest")
  81. {
  82. min_filter = gl::texture_min_filter::nearest_mipmap_nearest;
  83. mag_filter = gl::texture_mag_filter::nearest;
  84. }
  85. }
  86. // Read max anisotropy
  87. float max_anisotropy = 0.0f;
  88. if (auto element = json.find("max_anisotropy"); element != json.end())
  89. max_anisotropy = element.value().get<float>();
  90. // Load image
  91. ::image* image = resource_manager->load<::image>(image_filename);
  92. // Determine pixel type
  93. gl::pixel_type type = (image->is_hdr()) ? gl::pixel_type::float_32 : gl::pixel_type::uint_8;
  94. // Determine pixel format
  95. gl::pixel_format format;
  96. if (image->get_channels() == 1)
  97. {
  98. format = gl::pixel_format::r;
  99. }
  100. else if (image->get_channels() == 2)
  101. {
  102. format = gl::pixel_format::rg;
  103. }
  104. else if (image->get_channels() == 3)
  105. {
  106. format = gl::pixel_format::rgb;
  107. }
  108. else if (image->get_channels() == 4)
  109. {
  110. format = gl::pixel_format::rgba;
  111. }
  112. else
  113. {
  114. std::stringstream stream;
  115. stream << std::string("Texture cannot be created from an image with an unsupported number of color channels (") << image->get_channels() << std::string(").");
  116. delete image;
  117. throw std::runtime_error(stream.str().c_str());
  118. }
  119. // Create texture
  120. gl::texture_2d* texture = new gl::texture_2d(image->get_width(), image->get_height(), type, format, color_space, image->get_pixels());
  121. // Set wrapping and filtering
  122. texture->set_wrapping(wrapping, wrapping);
  123. texture->set_filters(min_filter, mag_filter);
  124. texture->set_max_anisotropy(max_anisotropy);
  125. // Free loaded image
  126. resource_manager->unload(image_filename);
  127. return texture;
  128. }