cylinder_pipeline.cpp 14 KB

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