character_pipeline.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. #include "character_pipeline.h"
  2. #include "../backend.h"
  3. #include "../shader_cache.h"
  4. #include <QDebug>
  5. #include <QStringList>
  6. #include <qglobal.h>
  7. #include <utility>
  8. namespace Render::GL::BackendPipelines {
  9. auto CharacterPipeline::initialize() -> bool {
  10. if (m_shader_cache == nullptr) {
  11. qWarning() << "CharacterPipeline::initialize: null ShaderCache";
  12. return false;
  13. }
  14. m_basic_shader = m_shader_cache->get("basic");
  15. m_archer_shader = m_shader_cache->get("archer");
  16. m_swordsman_shader = m_shader_cache->get("swordsman");
  17. m_spearman_shader = m_shader_cache->get("spearman");
  18. if (m_basic_shader == nullptr) {
  19. qWarning() << "CharacterPipeline: Failed to load basic shader";
  20. }
  21. if (m_archer_shader == nullptr) {
  22. qWarning() << "CharacterPipeline: Failed to load archer shader";
  23. }
  24. if (m_swordsman_shader == nullptr) {
  25. qWarning() << "CharacterPipeline: Failed to load swordsman shader";
  26. }
  27. if (m_spearman_shader == nullptr) {
  28. qWarning() << "CharacterPipeline: Failed to load spearman shader";
  29. }
  30. cache_uniforms();
  31. return is_initialized();
  32. }
  33. void CharacterPipeline::shutdown() {
  34. m_basic_shader = nullptr;
  35. m_archer_shader = nullptr;
  36. m_swordsman_shader = nullptr;
  37. m_spearman_shader = nullptr;
  38. }
  39. void CharacterPipeline::cache_uniforms() {
  40. m_uniform_cache.clear();
  41. cache_basic_uniforms();
  42. cache_archer_uniforms();
  43. cache_knight_uniforms();
  44. cache_spearman_uniforms();
  45. }
  46. auto CharacterPipeline::is_initialized() const -> bool {
  47. return m_basic_shader != nullptr && m_archer_shader != nullptr &&
  48. m_swordsman_shader != nullptr && m_spearman_shader != nullptr;
  49. }
  50. void CharacterPipeline::cache_basic_uniforms() {
  51. if (m_basic_shader == nullptr) {
  52. return;
  53. }
  54. m_basic_uniforms = build_uniform_set(m_basic_shader);
  55. m_uniform_cache[m_basic_shader] = m_basic_uniforms;
  56. }
  57. void CharacterPipeline::cache_archer_uniforms() {
  58. if (m_archer_shader == nullptr) {
  59. return;
  60. }
  61. m_archer_uniforms = build_uniform_set(m_archer_shader);
  62. m_uniform_cache[m_archer_shader] = m_archer_uniforms;
  63. cache_nation_variants(QStringLiteral("archer"));
  64. }
  65. void CharacterPipeline::cache_knight_uniforms() {
  66. if (m_swordsman_shader == nullptr) {
  67. return;
  68. }
  69. m_swordsman_uniforms = build_uniform_set(m_swordsman_shader);
  70. m_uniform_cache[m_swordsman_shader] = m_swordsman_uniforms;
  71. cache_nation_variants(QStringLiteral("swordsman"));
  72. }
  73. void CharacterPipeline::cache_spearman_uniforms() {
  74. if (m_spearman_shader == nullptr) {
  75. return;
  76. }
  77. m_spearman_uniforms = build_uniform_set(m_spearman_shader);
  78. m_uniform_cache[m_spearman_shader] = m_spearman_uniforms;
  79. cache_nation_variants(QStringLiteral("spearman"));
  80. }
  81. auto CharacterPipeline::build_uniform_set(GL::Shader *shader) const
  82. -> BasicUniforms {
  83. BasicUniforms uniforms;
  84. if (shader == nullptr) {
  85. return uniforms;
  86. }
  87. uniforms.mvp = shader->optional_uniform_handle("u_mvp");
  88. uniforms.model = shader->uniform_handle("u_model");
  89. uniforms.texture = shader->uniform_handle("u_texture");
  90. uniforms.use_texture = shader->uniform_handle("u_useTexture");
  91. uniforms.color = shader->uniform_handle("u_color");
  92. uniforms.alpha = shader->uniform_handle("u_alpha");
  93. uniforms.material_id = shader->optional_uniform_handle("u_materialId");
  94. uniforms.instanced = shader->optional_uniform_handle("u_instanced");
  95. uniforms.view_proj = shader->optional_uniform_handle("u_viewProj");
  96. return uniforms;
  97. }
  98. void CharacterPipeline::cache_nation_variants(const QString &base_key) {
  99. if (m_shader_cache == nullptr) {
  100. return;
  101. }
  102. static const QStringList nations{QStringLiteral("roman_republic"),
  103. QStringLiteral("carthage")};
  104. for (const QString &nation : nations) {
  105. const QString shader_name = base_key + QStringLiteral("_") + nation;
  106. if (GL::Shader *variant = m_shader_cache->get(shader_name)) {
  107. m_uniform_cache.emplace(variant, build_uniform_set(variant));
  108. }
  109. }
  110. }
  111. auto CharacterPipeline::resolve_uniforms(GL::Shader *shader)
  112. -> BasicUniforms * {
  113. if (shader == nullptr) {
  114. return nullptr;
  115. }
  116. if (shader == m_last_resolved_shader) {
  117. return m_last_resolved_uniforms;
  118. }
  119. auto it = m_uniform_cache.find(shader);
  120. if (it != m_uniform_cache.end()) {
  121. m_last_resolved_shader = shader;
  122. m_last_resolved_uniforms = &it->second;
  123. return m_last_resolved_uniforms;
  124. }
  125. BasicUniforms uniforms = build_uniform_set(shader);
  126. auto [inserted, success] = m_uniform_cache.emplace(shader, uniforms);
  127. m_last_resolved_shader = shader;
  128. m_last_resolved_uniforms = &inserted->second;
  129. return m_last_resolved_uniforms;
  130. }
  131. } // namespace Render::GL::BackendPipelines