terrain_pipeline.cpp 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. #include "terrain_pipeline.h"
  2. #include "../backend.h"
  3. #include "../render_constants.h"
  4. #include "../shader_cache.h"
  5. #include <GL/gl.h>
  6. #include <QDebug>
  7. #include <QOpenGLExtraFunctions>
  8. #include <cstddef>
  9. #include <qglobal.h>
  10. #include <qopenglext.h>
  11. #include <qvectornd.h>
  12. namespace Render::GL::BackendPipelines {
  13. using namespace Render::GL::VertexAttrib;
  14. using namespace Render::GL::ComponentCount;
  15. using namespace Render::GL::Geometry;
  16. auto TerrainPipeline::initialize() -> bool {
  17. if (m_shaderCache == nullptr) {
  18. qWarning() << "TerrainPipeline::initialize: null ShaderCache";
  19. return false;
  20. }
  21. auto *gl = QOpenGLContext::currentContext()->extraFunctions();
  22. m_grassShader = m_shaderCache->get("grass_instanced");
  23. m_groundShader = m_shaderCache->get("ground_plane");
  24. m_terrainShader = m_shaderCache->get("terrain_chunk");
  25. if (m_grassShader == nullptr) {
  26. qWarning() << "TerrainPipeline: Failed to load grass_instanced shader";
  27. }
  28. if (m_groundShader == nullptr) {
  29. qWarning() << "TerrainPipeline: Failed to load ground_plane shader";
  30. }
  31. if (m_terrainShader == nullptr) {
  32. qWarning() << "TerrainPipeline: Failed to load basic (terrain) shader";
  33. }
  34. initializeGrassGeometry();
  35. cacheUniforms();
  36. return isInitialized();
  37. }
  38. void TerrainPipeline::shutdown() {
  39. shutdownGrassGeometry();
  40. m_grassShader = nullptr;
  41. m_groundShader = nullptr;
  42. m_terrainShader = nullptr;
  43. }
  44. void TerrainPipeline::cacheUniforms() {
  45. cacheGrassUniforms();
  46. cacheGroundUniforms();
  47. cacheTerrainUniforms();
  48. }
  49. auto TerrainPipeline::isInitialized() const -> bool {
  50. return m_grassShader != nullptr && m_groundShader != nullptr &&
  51. m_terrainShader != nullptr && m_grassVao != 0;
  52. }
  53. void TerrainPipeline::cacheGrassUniforms() {
  54. if (m_grassShader == nullptr) {
  55. return;
  56. }
  57. m_grassUniforms.view_proj = m_grassShader->uniformHandle("u_viewProj");
  58. m_grassUniforms.time = m_grassShader->uniformHandle("u_time");
  59. m_grassUniforms.windStrength = m_grassShader->uniformHandle("u_windStrength");
  60. m_grassUniforms.windSpeed = m_grassShader->uniformHandle("u_windSpeed");
  61. m_grassUniforms.soilColor = m_grassShader->uniformHandle("u_soilColor");
  62. m_grassUniforms.light_dir = m_grassShader->uniformHandle("u_lightDir");
  63. }
  64. void TerrainPipeline::cacheGroundUniforms() {
  65. if (m_groundShader == nullptr) {
  66. return;
  67. }
  68. m_groundUniforms.mvp = m_groundShader->uniformHandle("u_mvp");
  69. m_groundUniforms.model = m_groundShader->uniformHandle("u_model");
  70. m_groundUniforms.grassPrimary =
  71. m_groundShader->uniformHandle("u_grassPrimary");
  72. m_groundUniforms.grassSecondary =
  73. m_groundShader->uniformHandle("u_grassSecondary");
  74. m_groundUniforms.grassDry = m_groundShader->uniformHandle("u_grassDry");
  75. m_groundUniforms.soilColor = m_groundShader->uniformHandle("u_soilColor");
  76. m_groundUniforms.tint = m_groundShader->uniformHandle("u_tint");
  77. m_groundUniforms.noiseOffset = m_groundShader->uniformHandle("u_noiseOffset");
  78. m_groundUniforms.tile_size = m_groundShader->uniformHandle("u_tileSize");
  79. m_groundUniforms.macroNoiseScale =
  80. m_groundShader->uniformHandle("u_macroNoiseScale");
  81. m_groundUniforms.detail_noiseScale =
  82. m_groundShader->uniformHandle("u_detailNoiseScale");
  83. m_groundUniforms.soilBlendHeight =
  84. m_groundShader->uniformHandle("u_soilBlendHeight");
  85. m_groundUniforms.soilBlendSharpness =
  86. m_groundShader->uniformHandle("u_soilBlendSharpness");
  87. m_groundUniforms.ambientBoost =
  88. m_groundShader->uniformHandle("u_ambientBoost");
  89. m_groundUniforms.light_dir = m_groundShader->uniformHandle("u_lightDir");
  90. }
  91. void TerrainPipeline::cacheTerrainUniforms() {
  92. if (m_terrainShader == nullptr) {
  93. return;
  94. }
  95. m_terrainUniforms.mvp = m_terrainShader->uniformHandle("u_mvp");
  96. m_terrainUniforms.model = m_terrainShader->uniformHandle("u_model");
  97. m_terrainUniforms.grassPrimary =
  98. m_terrainShader->uniformHandle("u_grassPrimary");
  99. m_terrainUniforms.grassSecondary =
  100. m_terrainShader->uniformHandle("u_grassSecondary");
  101. m_terrainUniforms.grassDry = m_terrainShader->uniformHandle("u_grassDry");
  102. m_terrainUniforms.soilColor = m_terrainShader->uniformHandle("u_soilColor");
  103. m_terrainUniforms.rockLow = m_terrainShader->uniformHandle("u_rockLow");
  104. m_terrainUniforms.rockHigh = m_terrainShader->uniformHandle("u_rockHigh");
  105. m_terrainUniforms.tint = m_terrainShader->uniformHandle("u_tint");
  106. m_terrainUniforms.noiseOffset =
  107. m_terrainShader->uniformHandle("u_noiseOffset");
  108. m_terrainUniforms.tile_size = m_terrainShader->uniformHandle("u_tileSize");
  109. m_terrainUniforms.macroNoiseScale =
  110. m_terrainShader->uniformHandle("u_macroNoiseScale");
  111. m_terrainUniforms.detail_noiseScale =
  112. m_terrainShader->uniformHandle("u_detailNoiseScale");
  113. m_terrainUniforms.slopeRockThreshold =
  114. m_terrainShader->uniformHandle("u_slopeRockThreshold");
  115. m_terrainUniforms.slopeRockSharpness =
  116. m_terrainShader->uniformHandle("u_slopeRockSharpness");
  117. m_terrainUniforms.soilBlendHeight =
  118. m_terrainShader->uniformHandle("u_soilBlendHeight");
  119. m_terrainUniforms.soilBlendSharpness =
  120. m_terrainShader->uniformHandle("u_soilBlendSharpness");
  121. m_terrainUniforms.heightNoiseStrength =
  122. m_terrainShader->uniformHandle("u_heightNoiseStrength");
  123. m_terrainUniforms.heightNoiseFrequency =
  124. m_terrainShader->uniformHandle("u_heightNoiseFrequency");
  125. m_terrainUniforms.ambientBoost =
  126. m_terrainShader->uniformHandle("u_ambientBoost");
  127. m_terrainUniforms.rockDetailStrength =
  128. m_terrainShader->uniformHandle("u_rockDetailStrength");
  129. m_terrainUniforms.light_dir = m_terrainShader->uniformHandle("u_lightDir");
  130. }
  131. void TerrainPipeline::initializeGrassGeometry() {
  132. auto *gl = QOpenGLContext::currentContext()->extraFunctions();
  133. if (gl == nullptr) {
  134. qWarning() << "TerrainPipeline::initializeGrassGeometry: no OpenGL context";
  135. return;
  136. }
  137. shutdownGrassGeometry();
  138. struct GrassVertex {
  139. QVector3D position;
  140. QVector2D uv;
  141. };
  142. const GrassVertex blade_vertices[6] = {
  143. {{-0.5F, 0.0F, 0.0F}, {0.0F, 0.0F}},
  144. {{0.5F, 0.0F, 0.0F}, {1.0F, 0.0F}},
  145. {{-0.35F, 1.0F, 0.0F}, {0.1F, 1.0F}},
  146. {{-0.35F, 1.0F, 0.0F}, {0.1F, 1.0F}},
  147. {{0.5F, 0.0F, 0.0F}, {1.0F, 0.0F}},
  148. {{0.35F, 1.0F, 0.0F}, {0.9F, 1.0F}},
  149. };
  150. gl->glGenVertexArrays(1, &m_grassVao);
  151. gl->glBindVertexArray(m_grassVao);
  152. gl->glGenBuffers(1, &m_grassVertexBuffer);
  153. gl->glBindBuffer(GL_ARRAY_BUFFER, m_grassVertexBuffer);
  154. gl->glBufferData(GL_ARRAY_BUFFER, sizeof(blade_vertices), blade_vertices,
  155. GL_STATIC_DRAW);
  156. m_grassVertexCount = GrassBladeVertexCount;
  157. gl->glEnableVertexAttribArray(Position);
  158. gl->glVertexAttribPointer(
  159. Position, Vec3, GL_FLOAT, GL_FALSE, sizeof(GrassVertex),
  160. reinterpret_cast<void *>(offsetof(GrassVertex, position)));
  161. gl->glEnableVertexAttribArray(Normal);
  162. gl->glVertexAttribPointer(
  163. Normal, Vec2, GL_FLOAT, GL_FALSE, sizeof(GrassVertex),
  164. reinterpret_cast<void *>(offsetof(GrassVertex, uv)));
  165. gl->glEnableVertexAttribArray(TexCoord);
  166. gl->glVertexAttribDivisor(TexCoord, 1);
  167. gl->glEnableVertexAttribArray(InstancePosition);
  168. gl->glVertexAttribDivisor(InstancePosition, 1);
  169. gl->glEnableVertexAttribArray(InstanceScale);
  170. gl->glVertexAttribDivisor(InstanceScale, 1);
  171. gl->glBindVertexArray(0);
  172. gl->glBindBuffer(GL_ARRAY_BUFFER, 0);
  173. }
  174. void TerrainPipeline::shutdownGrassGeometry() {
  175. auto *gl = QOpenGLContext::currentContext()->extraFunctions();
  176. if (gl == nullptr) {
  177. return;
  178. }
  179. if (m_grassVertexBuffer != 0U) {
  180. gl->glDeleteBuffers(1, &m_grassVertexBuffer);
  181. m_grassVertexBuffer = 0;
  182. }
  183. if (m_grassVao != 0U) {
  184. gl->glDeleteVertexArrays(1, &m_grassVao);
  185. m_grassVao = 0;
  186. }
  187. m_grassVertexCount = 0;
  188. }
  189. } // namespace Render::GL::BackendPipelines