river_renderer.cpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. #include "river_renderer.h"
  2. #include "../../game/map/visibility_service.h"
  3. #include "../gl/mesh.h"
  4. #include "../gl/resources.h"
  5. #include "../scene_renderer.h"
  6. #include "ground_utils.h"
  7. #include "map/terrain.h"
  8. #include <QVector2D>
  9. #include <QVector3D>
  10. #include <algorithm>
  11. #include <cmath>
  12. #include <cstddef>
  13. #include <memory>
  14. #include <qglobal.h>
  15. #include <qmatrix4x4.h>
  16. #include <qvectornd.h>
  17. #include <vector>
  18. namespace Render::GL {
  19. RiverRenderer::RiverRenderer() = default;
  20. RiverRenderer::~RiverRenderer() = default;
  21. void RiverRenderer::configure(
  22. const std::vector<Game::Map::RiverSegment> &riverSegments,
  23. float tile_size) {
  24. m_riverSegments = riverSegments;
  25. m_tile_size = tile_size;
  26. buildMeshes();
  27. }
  28. void RiverRenderer::buildMeshes() {
  29. m_meshes.clear();
  30. if (m_riverSegments.empty()) {
  31. return;
  32. }
  33. auto noise = [](float x, float y) -> float {
  34. float const ix = std::floor(x);
  35. float const iy = std::floor(y);
  36. float fx = x - ix;
  37. float fy = y - iy;
  38. fx = fx * fx * (3.0F - 2.0F * fx);
  39. fy = fy * fy * (3.0F - 2.0F * fy);
  40. float const a = Ground::noise_hash(ix, iy);
  41. float const b = Ground::noise_hash(ix + 1.0F, iy);
  42. float const c = Ground::noise_hash(ix, iy + 1.0F);
  43. float const d = Ground::noise_hash(ix + 1.0F, iy + 1.0F);
  44. return a * (1.0F - fx) * (1.0F - fy) + b * fx * (1.0F - fy) +
  45. c * (1.0F - fx) * fy + d * fx * fy;
  46. };
  47. for (const auto &segment : m_riverSegments) {
  48. QVector3D dir = segment.end - segment.start;
  49. float const length = dir.length();
  50. if (length < 0.01F) {
  51. m_meshes.push_back(nullptr);
  52. continue;
  53. }
  54. dir.normalize();
  55. QVector3D const perpendicular(-dir.z(), 0.0F, dir.x());
  56. float const half_width = segment.width * 0.5F;
  57. int length_steps =
  58. static_cast<int>(std::ceil(length / (m_tile_size * 0.5F))) + 1;
  59. length_steps = std::max(length_steps, 8);
  60. std::vector<Vertex> vertices;
  61. std::vector<unsigned int> indices;
  62. for (int i = 0; i < length_steps; ++i) {
  63. float const t =
  64. static_cast<float>(i) / static_cast<float>(length_steps - 1);
  65. QVector3D center_pos = segment.start + dir * (length * t);
  66. constexpr float k_edge_noise_freq_1 = 2.0F;
  67. constexpr float k_edge_noise_freq_2 = 5.0F;
  68. constexpr float k_edge_noise_freq_3 = 10.0F;
  69. float const edge_noise1 = noise(center_pos.x() * k_edge_noise_freq_1,
  70. center_pos.z() * k_edge_noise_freq_1);
  71. float const edge_noise2 = noise(center_pos.x() * k_edge_noise_freq_2,
  72. center_pos.z() * k_edge_noise_freq_2);
  73. float const edge_noise3 = noise(center_pos.x() * k_edge_noise_freq_3,
  74. center_pos.z() * k_edge_noise_freq_3);
  75. float combined_noise =
  76. edge_noise1 * 0.5F + edge_noise2 * 0.3F + edge_noise3 * 0.2F;
  77. combined_noise = (combined_noise - 0.5F) * 2.0F;
  78. float const width_variation = combined_noise * half_width * 0.35F;
  79. float const meander = noise(t * 3.0F, length * 0.1F) * 0.3F;
  80. QVector3D const center_offset = perpendicular * meander;
  81. center_pos += center_offset;
  82. QVector3D const left =
  83. center_pos - perpendicular * (half_width + width_variation);
  84. QVector3D const right =
  85. center_pos + perpendicular * (half_width + width_variation);
  86. float const normal[3] = {0.0F, 1.0F, 0.0F};
  87. Vertex left_vertex;
  88. left_vertex.position[0] = left.x();
  89. left_vertex.position[1] = left.y();
  90. left_vertex.position[2] = left.z();
  91. left_vertex.normal[0] = normal[0];
  92. left_vertex.normal[1] = normal[1];
  93. left_vertex.normal[2] = normal[2];
  94. left_vertex.tex_coord[0] = 0.0F;
  95. left_vertex.tex_coord[1] = t;
  96. vertices.push_back(left_vertex);
  97. Vertex right_vertex;
  98. right_vertex.position[0] = right.x();
  99. right_vertex.position[1] = right.y();
  100. right_vertex.position[2] = right.z();
  101. right_vertex.normal[0] = normal[0];
  102. right_vertex.normal[1] = normal[1];
  103. right_vertex.normal[2] = normal[2];
  104. right_vertex.tex_coord[0] = 1.0F;
  105. right_vertex.tex_coord[1] = t;
  106. vertices.push_back(right_vertex);
  107. if (i < length_steps - 1) {
  108. unsigned int const idx0 = i * 2;
  109. unsigned int const idx1 = idx0 + 1;
  110. unsigned int const idx2 = idx0 + 2;
  111. unsigned int const idx3 = idx0 + 3;
  112. indices.push_back(idx0);
  113. indices.push_back(idx2);
  114. indices.push_back(idx1);
  115. indices.push_back(idx1);
  116. indices.push_back(idx2);
  117. indices.push_back(idx3);
  118. }
  119. }
  120. if (!vertices.empty() && !indices.empty()) {
  121. m_meshes.push_back(std::make_unique<Mesh>(vertices, indices));
  122. } else {
  123. m_meshes.push_back(nullptr);
  124. }
  125. }
  126. }
  127. void RiverRenderer::submit(Renderer &renderer, ResourceManager *resources) {
  128. if (m_meshes.empty() || m_riverSegments.empty()) {
  129. return;
  130. }
  131. Q_UNUSED(resources);
  132. auto &visibility = Game::Map::VisibilityService::instance();
  133. const bool use_visibility = visibility.isInitialized();
  134. auto *shader = renderer.getShader("river");
  135. if (shader == nullptr) {
  136. return;
  137. }
  138. renderer.setCurrentShader(shader);
  139. QMatrix4x4 model;
  140. model.setToIdentity();
  141. size_t mesh_index = 0;
  142. for (const auto &segment : m_riverSegments) {
  143. if (mesh_index >= m_meshes.size()) {
  144. break;
  145. }
  146. auto *mesh = m_meshes[mesh_index].get();
  147. ++mesh_index;
  148. if (mesh == nullptr) {
  149. continue;
  150. }
  151. QVector3D dir = segment.end - segment.start;
  152. float const length = dir.length();
  153. float alpha = 1.0F;
  154. QVector3D color_multiplier(1.0F, 1.0F, 1.0F);
  155. if (use_visibility) {
  156. int max_visibility_state = 0;
  157. dir.normalize();
  158. int const samples_per_segment = 5;
  159. for (int i = 0; i < samples_per_segment; ++i) {
  160. float const t =
  161. static_cast<float>(i) / static_cast<float>(samples_per_segment - 1);
  162. QVector3D const pos = segment.start + dir * (length * t);
  163. if (visibility.isVisibleWorld(pos.x(), pos.z())) {
  164. max_visibility_state = 2;
  165. break;
  166. }
  167. if (visibility.isExploredWorld(pos.x(), pos.z())) {
  168. max_visibility_state = std::max(max_visibility_state, 1);
  169. }
  170. }
  171. if (max_visibility_state == 0) {
  172. continue;
  173. }
  174. if (max_visibility_state == 1) {
  175. alpha = 0.5F;
  176. color_multiplier = QVector3D(0.4F, 0.4F, 0.45F);
  177. }
  178. }
  179. QVector3D const final_color(color_multiplier.x(), color_multiplier.y(),
  180. color_multiplier.z());
  181. renderer.mesh(mesh, model, final_color, nullptr, alpha);
  182. }
  183. renderer.setCurrentShader(nullptr);
  184. }
  185. } // namespace Render::GL