cylinder_pipeline.cpp 14 KB

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