manager.cxx 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. //
  2. // manager.cxx
  3. // graphics
  4. //
  5. // Created by Sam Jaffe on 5/25/19.
  6. // Copyright © 2019 Sam Jaffe. All rights reserved.
  7. //
  8. #include "game/graphics/manager.hpp"
  9. #include "game/graphics/material.hpp"
  10. #include "game/graphics/object.hpp"
  11. #include "game/graphics/shader.hpp"
  12. #include "game/graphics/shader_program.hpp"
  13. #include "game/graphics/texture.hpp"
  14. #include "game/math/shape.hpp"
  15. #include "game/util/hash.hpp"
  16. #include "helper.hpp"
  17. using namespace graphics;
  18. template <typename> struct key;
  19. template <typename T> using key_t = typename key<T>::type;
  20. template <> struct key<texture> { using type = std::string; };
  21. template <> struct key<shader> {
  22. using type = std::pair<shaders::type, std::string>;
  23. };
  24. template <> struct key<shader_program> {
  25. using type = std::pair<std::string, std::string>;
  26. };
  27. template <> struct key<material> {
  28. using type = std::tuple<identity<shader_program>, std::string, std::string>;
  29. };
  30. template <typename T> struct cache {
  31. identity<T> emplace(key_t<T> const & key, T && value);
  32. std::unordered_map<identity<T>, key_t<T>> keys;
  33. std::unordered_map<key_t<T>, T> values;
  34. };
  35. template <typename T>
  36. identity<T> cache<T>::emplace(key_t<T> const & key, T && value) {
  37. keys.emplace(value, key);
  38. return values.emplace(key, std::forward<T>(value)).first->second;
  39. }
  40. struct graphics::manager_impl {
  41. cache<material> materials;
  42. cache<shader> shaders;
  43. cache<shader_program> programs;
  44. cache<texture> textures;
  45. };
  46. manager::manager() : pimpl_(new manager_impl) {}
  47. manager::~manager() {}
  48. identity<material> manager::get(identity<shader_program> program,
  49. std::string const & texture,
  50. std::string const & uniform) const {
  51. auto key = std::make_tuple(program, texture, uniform);
  52. auto & cache = pimpl_->materials;
  53. auto found = cache.values.find(key);
  54. if (found != cache.values.end()) { return found->second; }
  55. std::vector<struct uniform> uniforms;
  56. uniforms.push_back({texture_or_uniform(texture, uniform),
  57. shaders::uniform_location(program, uniform)});
  58. math::vec2i size = get(uniforms[0].texture).size;
  59. // if (!uniforms.empty()) { size = ...; }
  60. return cache.emplace(key, material(program, size, uniforms));
  61. }
  62. material const & manager::get(identity<material> identity) const {
  63. auto & cache = pimpl_->materials;
  64. return cache.values.find(cache.keys.find(identity)->second)->second;
  65. }
  66. texture const & manager::get(identity<texture> identity) const {
  67. auto & cache = pimpl_->textures;
  68. auto it = cache.keys.find(identity);
  69. if (it == cache.keys.end()) { return texture::WHITE(); }
  70. return cache.values.find(it->second)->second;
  71. }
  72. identity<shader> manager::get(shaders::type type,
  73. std::string const & path) const {
  74. auto key = std::make_pair(type, path);
  75. auto & cache = pimpl_->shaders;
  76. auto found = cache.values.find(key);
  77. if (found != cache.values.end()) { return found->second; }
  78. return cache.emplace(key, shader(type, path));
  79. }
  80. identity<texture>
  81. manager::texture_or_uniform(std::string const & path,
  82. std::string const & uniform) const {
  83. if (!path.empty()) {
  84. try {
  85. return get(path);
  86. } catch (std::exception const & e) {
  87. // TODO: Logging
  88. }
  89. }
  90. if (uniform == "u_normalMap") {
  91. return texture::LIGHT_BLUE();
  92. } else if (uniform == "u_specularMap") {
  93. return texture::DARK_YELLOW();
  94. } else if (uniform == "u_diffuseMap") {
  95. return texture::WHITE();
  96. }
  97. throw;
  98. }
  99. identity<shader_program> manager::get(std::string const & fragment,
  100. std::string const & vertex) const {
  101. auto key = std::make_pair(fragment, vertex);
  102. auto & cache = pimpl_->programs;
  103. auto found = cache.values.find(key);
  104. if (found != cache.values.end()) { return found->second; }
  105. auto fragment_shader = get(shaders::type::FRAGMENT, fragment);
  106. auto vertex_shader = get(shaders::type::VERTEX, vertex);
  107. return cache.emplace(key, shader_program(fragment_shader, vertex_shader));
  108. }
  109. identity<texture> manager::get(std::string const & path) const {
  110. auto & cache = pimpl_->textures;
  111. auto found = cache.values.find(path);
  112. if (found != cache.values.end()) { return found->second; }
  113. return cache.emplace(path, texture(path));
  114. }
  115. object manager::create_object(identity<material> fromMaterial,
  116. math::vec2 atPosition,
  117. math::vec2 frameWidth) const {
  118. math::dim2::rectangle bounds{atPosition, frameWidth * get(fromMaterial).size};
  119. return {bounds, bounds, fromMaterial, {make_vector(0.f, 0.f), frameWidth}};
  120. }