cylinder_pipeline.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. #include "cylinder_pipeline.h"
  2. #include "../backend.h"
  3. #include "../mesh.h"
  4. #include "../primitives.h"
  5. #include "../render_constants.h"
  6. #include "gl/shader_cache.h"
  7. #include <GL/gl.h>
  8. #include <algorithm>
  9. #include <cstddef>
  10. #include <qopenglext.h>
  11. #include <qstringliteral.h>
  12. namespace Render::GL::BackendPipelines {
  13. using namespace Render::GL::VertexAttrib;
  14. using namespace Render::GL::ComponentCount;
  15. using namespace Render::GL::BufferCapacity;
  16. using namespace Render::GL::Geometry;
  17. using namespace Render::GL::Growth;
  18. CylinderPipeline::CylinderPipeline(ShaderCache *shaderCache)
  19. : m_shaderCache(shaderCache) {}
  20. CylinderPipeline::~CylinderPipeline() { shutdown(); }
  21. auto CylinderPipeline::initialize() -> bool {
  22. initializeOpenGLFunctions();
  23. if (m_shaderCache == nullptr) {
  24. return false;
  25. }
  26. m_cylinderShader = m_shaderCache->get(QStringLiteral("cylinder_instanced"));
  27. m_fogShader = m_shaderCache->get(QStringLiteral("fog_instanced"));
  28. if ((m_cylinderShader == nullptr) || (m_fogShader == nullptr)) {
  29. return false;
  30. }
  31. initializeCylinderPipeline();
  32. initializeFogPipeline();
  33. cacheUniforms();
  34. m_initialized = true;
  35. return true;
  36. }
  37. void CylinderPipeline::shutdown() {
  38. shutdownCylinderPipeline();
  39. shutdownFogPipeline();
  40. m_initialized = false;
  41. }
  42. void CylinderPipeline::cacheUniforms() {
  43. if (m_cylinderShader != nullptr) {
  44. m_cylinderUniforms.view_proj =
  45. m_cylinderShader->uniformHandle("u_viewProj");
  46. }
  47. if (m_fogShader != nullptr) {
  48. m_fogUniforms.view_proj = m_fogShader->uniformHandle("u_viewProj");
  49. }
  50. }
  51. void CylinderPipeline::beginFrame() {
  52. if (m_cylinderPersistentBuffer.isValid()) {
  53. m_cylinderPersistentBuffer.beginFrame();
  54. }
  55. if (m_fogPersistentBuffer.isValid()) {
  56. m_fogPersistentBuffer.beginFrame();
  57. }
  58. }
  59. void CylinderPipeline::initializeCylinderPipeline() {
  60. initializeOpenGLFunctions();
  61. shutdownCylinderPipeline();
  62. Mesh *unit = getUnitCylinder();
  63. if (unit == nullptr) {
  64. return;
  65. }
  66. const auto &vertices = unit->getVertices();
  67. const auto &indices = unit->getIndices();
  68. if (vertices.empty() || indices.empty()) {
  69. return;
  70. }
  71. glGenVertexArrays(1, &m_cylinderVao);
  72. glBindVertexArray(m_cylinderVao);
  73. glGenBuffers(1, &m_cylinderVertexBuffer);
  74. glBindBuffer(GL_ARRAY_BUFFER, m_cylinderVertexBuffer);
  75. glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex),
  76. vertices.data(), GL_STATIC_DRAW);
  77. glGenBuffers(1, &m_cylinderIndexBuffer);
  78. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_cylinderIndexBuffer);
  79. glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int),
  80. indices.data(), GL_STATIC_DRAW);
  81. m_cylinderIndexCount = static_cast<GLsizei>(indices.size());
  82. glEnableVertexAttribArray(VertexAttrib::Position);
  83. glVertexAttribPointer(VertexAttrib::Position, ComponentCount::Vec3, GL_FLOAT,
  84. GL_FALSE, sizeof(Vertex),
  85. reinterpret_cast<void *>(offsetof(Vertex, position)));
  86. glEnableVertexAttribArray(VertexAttrib::Normal);
  87. glVertexAttribPointer(VertexAttrib::Normal, ComponentCount::Vec3, GL_FLOAT,
  88. GL_FALSE, sizeof(Vertex),
  89. reinterpret_cast<void *>(offsetof(Vertex, normal)));
  90. glEnableVertexAttribArray(VertexAttrib::TexCoord);
  91. glVertexAttribPointer(VertexAttrib::TexCoord, ComponentCount::Vec2, GL_FLOAT,
  92. GL_FALSE, sizeof(Vertex),
  93. reinterpret_cast<void *>(offsetof(Vertex, tex_coord)));
  94. const std::size_t persistent_capacity = 10000;
  95. if (m_cylinderPersistentBuffer.initialize(persistent_capacity,
  96. BufferCapacity::BuffersInFlight)) {
  97. m_usePersistentBuffers = true;
  98. glBindBuffer(GL_ARRAY_BUFFER, m_cylinderPersistentBuffer.buffer());
  99. } else {
  100. m_usePersistentBuffers = false;
  101. glGenBuffers(1, &m_cylinderInstanceBuffer);
  102. glBindBuffer(GL_ARRAY_BUFFER, m_cylinderInstanceBuffer);
  103. m_cylinderInstanceCapacity = BufferCapacity::DefaultCylinderInstances;
  104. glBufferData(GL_ARRAY_BUFFER,
  105. m_cylinderInstanceCapacity * sizeof(CylinderInstanceGpu),
  106. nullptr, GL_DYNAMIC_DRAW);
  107. }
  108. const auto stride = static_cast<GLsizei>(sizeof(CylinderInstanceGpu));
  109. glEnableVertexAttribArray(VertexAttrib::InstancePosition);
  110. glVertexAttribPointer(
  111. VertexAttrib::InstancePosition, ComponentCount::Vec3, GL_FLOAT, GL_FALSE,
  112. stride, reinterpret_cast<void *>(offsetof(CylinderInstanceGpu, start)));
  113. glVertexAttribDivisor(VertexAttrib::InstancePosition, 1);
  114. glEnableVertexAttribArray(VertexAttrib::InstanceScale);
  115. glVertexAttribPointer(
  116. VertexAttrib::InstanceScale, ComponentCount::Vec3, GL_FLOAT, GL_FALSE,
  117. stride, reinterpret_cast<void *>(offsetof(CylinderInstanceGpu, end)));
  118. glVertexAttribDivisor(VertexAttrib::InstanceScale, 1);
  119. glEnableVertexAttribArray(VertexAttrib::InstanceColor);
  120. glVertexAttribPointer(
  121. VertexAttrib::InstanceColor, 1, GL_FLOAT, GL_FALSE, stride,
  122. reinterpret_cast<void *>(offsetof(CylinderInstanceGpu, radius)));
  123. glVertexAttribDivisor(VertexAttrib::InstanceColor, 1);
  124. glEnableVertexAttribArray(VertexAttrib::InstanceAlpha);
  125. glVertexAttribPointer(
  126. VertexAttrib::InstanceAlpha, 1, GL_FLOAT, GL_FALSE, stride,
  127. reinterpret_cast<void *>(offsetof(CylinderInstanceGpu, alpha)));
  128. glVertexAttribDivisor(VertexAttrib::InstanceAlpha, 1);
  129. glEnableVertexAttribArray(VertexAttrib::InstanceTint);
  130. glVertexAttribPointer(
  131. VertexAttrib::InstanceTint, ComponentCount::Vec3, GL_FLOAT, GL_FALSE,
  132. stride, reinterpret_cast<void *>(offsetof(CylinderInstanceGpu, color)));
  133. glVertexAttribDivisor(VertexAttrib::InstanceTint, 1);
  134. glBindVertexArray(0);
  135. glBindBuffer(GL_ARRAY_BUFFER, 0);
  136. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
  137. m_cylinderScratch.reserve(m_usePersistentBuffers
  138. ? persistent_capacity
  139. : m_cylinderInstanceCapacity);
  140. }
  141. void CylinderPipeline::shutdownCylinderPipeline() {
  142. initializeOpenGLFunctions();
  143. m_cylinderPersistentBuffer.destroy();
  144. if (m_cylinderInstanceBuffer != 0U) {
  145. glDeleteBuffers(1, &m_cylinderInstanceBuffer);
  146. m_cylinderInstanceBuffer = 0;
  147. }
  148. if (m_cylinderVertexBuffer != 0U) {
  149. glDeleteBuffers(1, &m_cylinderVertexBuffer);
  150. m_cylinderVertexBuffer = 0;
  151. }
  152. if (m_cylinderIndexBuffer != 0U) {
  153. glDeleteBuffers(1, &m_cylinderIndexBuffer);
  154. m_cylinderIndexBuffer = 0;
  155. }
  156. if (m_cylinderVao != 0U) {
  157. glDeleteVertexArrays(1, &m_cylinderVao);
  158. m_cylinderVao = 0;
  159. }
  160. m_cylinderIndexCount = 0;
  161. m_cylinderInstanceCapacity = 0;
  162. m_cylinderScratch.clear();
  163. }
  164. void CylinderPipeline::uploadCylinderInstances(std::size_t count) {
  165. if (count == 0) {
  166. return;
  167. }
  168. initializeOpenGLFunctions();
  169. if (m_usePersistentBuffers && m_cylinderPersistentBuffer.isValid()) {
  170. if (count > m_cylinderPersistentBuffer.capacity()) {
  171. count = m_cylinderPersistentBuffer.capacity();
  172. }
  173. m_cylinderPersistentBuffer.write(m_cylinderScratch.data(), count);
  174. glBindBuffer(GL_ARRAY_BUFFER, m_cylinderPersistentBuffer.buffer());
  175. glBindBuffer(GL_ARRAY_BUFFER, 0);
  176. return;
  177. }
  178. if (m_cylinderInstanceBuffer == 0U) {
  179. return;
  180. }
  181. glBindBuffer(GL_ARRAY_BUFFER, m_cylinderInstanceBuffer);
  182. if (count > m_cylinderInstanceCapacity) {
  183. m_cylinderInstanceCapacity = std::max<std::size_t>(
  184. count, (m_cylinderInstanceCapacity != 0U)
  185. ? m_cylinderInstanceCapacity * Growth::CapacityMultiplier
  186. : count);
  187. glBufferData(GL_ARRAY_BUFFER,
  188. m_cylinderInstanceCapacity * sizeof(CylinderInstanceGpu),
  189. nullptr, GL_DYNAMIC_DRAW);
  190. m_cylinderScratch.reserve(m_cylinderInstanceCapacity);
  191. }
  192. glBufferSubData(GL_ARRAY_BUFFER, 0, count * sizeof(CylinderInstanceGpu),
  193. m_cylinderScratch.data());
  194. glBindBuffer(GL_ARRAY_BUFFER, 0);
  195. }
  196. void CylinderPipeline::drawCylinders(std::size_t count) {
  197. if ((m_cylinderVao == 0U) || m_cylinderIndexCount == 0 || count == 0) {
  198. return;
  199. }
  200. initializeOpenGLFunctions();
  201. glBindVertexArray(m_cylinderVao);
  202. glDrawElementsInstanced(GL_TRIANGLES, m_cylinderIndexCount, GL_UNSIGNED_INT,
  203. nullptr, static_cast<GLsizei>(count));
  204. glBindVertexArray(0);
  205. }
  206. void CylinderPipeline::initializeFogPipeline() {
  207. initializeOpenGLFunctions();
  208. shutdownFogPipeline();
  209. const Vertex vertices[Geometry::QuadVertexCount] = {
  210. {{-0.5F, 0.0F, -0.5F}, {0.0F, 1.0F, 0.0F}, {0.0F, 0.0F}},
  211. {{0.5F, 0.0F, -0.5F}, {0.0F, 1.0F, 0.0F}, {1.0F, 0.0F}},
  212. {{-0.5F, 0.0F, 0.5F}, {0.0F, 1.0F, 0.0F}, {0.0F, 1.0F}},
  213. {{0.5F, 0.0F, 0.5F}, {0.0F, 1.0F, 0.0F}, {1.0F, 1.0F}},
  214. };
  215. const unsigned int indices[Geometry::QuadIndexCount] = {0, 1, 2, 2, 1, 3};
  216. glGenVertexArrays(1, &m_fogVao);
  217. glBindVertexArray(m_fogVao);
  218. glGenBuffers(1, &m_fogVertexBuffer);
  219. glBindBuffer(GL_ARRAY_BUFFER, m_fogVertexBuffer);
  220. glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
  221. glGenBuffers(1, &m_fogIndexBuffer);
  222. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_fogIndexBuffer);
  223. glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices,
  224. GL_STATIC_DRAW);
  225. m_fogIndexCount = Geometry::QuadIndexCount;
  226. glEnableVertexAttribArray(VertexAttrib::Position);
  227. glVertexAttribPointer(VertexAttrib::Position, ComponentCount::Vec3, GL_FLOAT,
  228. GL_FALSE, sizeof(Vertex),
  229. reinterpret_cast<void *>(offsetof(Vertex, position)));
  230. glEnableVertexAttribArray(VertexAttrib::Normal);
  231. glVertexAttribPointer(VertexAttrib::Normal, ComponentCount::Vec3, GL_FLOAT,
  232. GL_FALSE, sizeof(Vertex),
  233. reinterpret_cast<void *>(offsetof(Vertex, normal)));
  234. glEnableVertexAttribArray(VertexAttrib::TexCoord);
  235. glVertexAttribPointer(VertexAttrib::TexCoord, ComponentCount::Vec2, GL_FLOAT,
  236. GL_FALSE, sizeof(Vertex),
  237. reinterpret_cast<void *>(offsetof(Vertex, tex_coord)));
  238. glGenBuffers(1, &m_fogInstanceBuffer);
  239. glBindBuffer(GL_ARRAY_BUFFER, m_fogInstanceBuffer);
  240. m_fogInstanceCapacity = BufferCapacity::DefaultFogInstances;
  241. glBufferData(GL_ARRAY_BUFFER, m_fogInstanceCapacity * sizeof(FogInstanceGpu),
  242. nullptr, GL_DYNAMIC_DRAW);
  243. const auto stride = static_cast<GLsizei>(sizeof(FogInstanceGpu));
  244. glEnableVertexAttribArray(VertexAttrib::InstancePosition);
  245. glVertexAttribPointer(
  246. VertexAttrib::InstancePosition, ComponentCount::Vec3, GL_FLOAT, GL_FALSE,
  247. stride, reinterpret_cast<void *>(offsetof(FogInstanceGpu, center)));
  248. glVertexAttribDivisor(VertexAttrib::InstancePosition, 1);
  249. glEnableVertexAttribArray(VertexAttrib::InstanceScale);
  250. glVertexAttribPointer(
  251. VertexAttrib::InstanceScale, 1, GL_FLOAT, GL_FALSE, stride,
  252. reinterpret_cast<void *>(offsetof(FogInstanceGpu, size)));
  253. glVertexAttribDivisor(VertexAttrib::InstanceScale, 1);
  254. glEnableVertexAttribArray(VertexAttrib::InstanceColor);
  255. glVertexAttribPointer(
  256. VertexAttrib::InstanceColor, ComponentCount::Vec3, GL_FLOAT, GL_FALSE,
  257. stride, reinterpret_cast<void *>(offsetof(FogInstanceGpu, color)));
  258. glVertexAttribDivisor(VertexAttrib::InstanceColor, 1);
  259. glEnableVertexAttribArray(VertexAttrib::InstanceAlpha);
  260. glVertexAttribPointer(
  261. VertexAttrib::InstanceAlpha, 1, GL_FLOAT, GL_FALSE, stride,
  262. reinterpret_cast<void *>(offsetof(FogInstanceGpu, alpha)));
  263. glVertexAttribDivisor(VertexAttrib::InstanceAlpha, 1);
  264. glBindVertexArray(0);
  265. glBindBuffer(GL_ARRAY_BUFFER, 0);
  266. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
  267. m_fogScratch.reserve(m_fogInstanceCapacity);
  268. }
  269. void CylinderPipeline::shutdownFogPipeline() {
  270. initializeOpenGLFunctions();
  271. if (m_fogInstanceBuffer != 0U) {
  272. glDeleteBuffers(1, &m_fogInstanceBuffer);
  273. m_fogInstanceBuffer = 0;
  274. }
  275. if (m_fogVertexBuffer != 0U) {
  276. glDeleteBuffers(1, &m_fogVertexBuffer);
  277. m_fogVertexBuffer = 0;
  278. }
  279. if (m_fogIndexBuffer != 0U) {
  280. glDeleteBuffers(1, &m_fogIndexBuffer);
  281. m_fogIndexBuffer = 0;
  282. }
  283. if (m_fogVao != 0U) {
  284. glDeleteVertexArrays(1, &m_fogVao);
  285. m_fogVao = 0;
  286. }
  287. m_fogIndexCount = 0;
  288. m_fogInstanceCapacity = 0;
  289. m_fogScratch.clear();
  290. }
  291. void CylinderPipeline::uploadFogInstances(std::size_t count) {
  292. if ((m_fogInstanceBuffer == 0U) || count == 0) {
  293. return;
  294. }
  295. initializeOpenGLFunctions();
  296. glBindBuffer(GL_ARRAY_BUFFER, m_fogInstanceBuffer);
  297. if (count > m_fogInstanceCapacity) {
  298. m_fogInstanceCapacity = std::max<std::size_t>(
  299. count, (m_fogInstanceCapacity != 0U)
  300. ? m_fogInstanceCapacity * Growth::CapacityMultiplier
  301. : count);
  302. glBufferData(GL_ARRAY_BUFFER,
  303. m_fogInstanceCapacity * sizeof(FogInstanceGpu), nullptr,
  304. GL_DYNAMIC_DRAW);
  305. m_fogScratch.reserve(m_fogInstanceCapacity);
  306. }
  307. glBufferSubData(GL_ARRAY_BUFFER, 0, count * sizeof(FogInstanceGpu),
  308. m_fogScratch.data());
  309. glBindBuffer(GL_ARRAY_BUFFER, 0);
  310. }
  311. void CylinderPipeline::drawFog(std::size_t count) {
  312. if ((m_fogVao == 0U) || m_fogIndexCount == 0 || count == 0) {
  313. return;
  314. }
  315. initializeOpenGLFunctions();
  316. glBindVertexArray(m_fogVao);
  317. glDrawElementsInstanced(GL_TRIANGLES, m_fogIndexCount, GL_UNSIGNED_INT,
  318. nullptr, static_cast<GLsizei>(count));
  319. glBindVertexArray(0);
  320. }
  321. } // namespace Render::GL::BackendPipelines