backend.cpp 58 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636
  1. #include "backend.h"
  2. #include "../draw_queue.h"
  3. #include "../geom/selection_disc.h"
  4. #include "../geom/selection_ring.h"
  5. #include "buffer.h"
  6. #include "mesh.h"
  7. #include "primitives.h"
  8. #include "shader.h"
  9. #include "state_scopes.h"
  10. #include "texture.h"
  11. #include <QDebug>
  12. #include <algorithm>
  13. #include <cmath>
  14. #include <cstddef>
  15. #include <memory>
  16. #include <vector>
  17. namespace Render::GL {
  18. namespace {
  19. const QVector3D kGridLineColor(0.22f, 0.25f, 0.22f);
  20. }
  21. Backend::~Backend() {
  22. shutdownCylinderPipeline();
  23. shutdownFogPipeline();
  24. shutdownGrassPipeline();
  25. shutdownStonePipeline();
  26. shutdownPlantPipeline();
  27. }
  28. void Backend::initialize() {
  29. initializeOpenGLFunctions();
  30. glEnable(GL_DEPTH_TEST);
  31. glDepthFunc(GL_LESS);
  32. glDepthRange(0.0, 1.0);
  33. glDepthMask(GL_TRUE);
  34. glEnable(GL_BLEND);
  35. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  36. m_resources = std::make_unique<ResourceManager>();
  37. if (!m_resources->initialize()) {
  38. qWarning() << "Backend: failed to initialize ResourceManager";
  39. }
  40. m_shaderCache = std::make_unique<ShaderCache>();
  41. m_shaderCache->initializeDefaults();
  42. m_basicShader = m_shaderCache->get(QStringLiteral("basic"));
  43. m_gridShader = m_shaderCache->get(QStringLiteral("grid"));
  44. m_cylinderShader = m_shaderCache->get(QStringLiteral("cylinder_instanced"));
  45. m_fogShader = m_shaderCache->get(QStringLiteral("fog_instanced"));
  46. m_grassShader = m_shaderCache->get(QStringLiteral("grass_instanced"));
  47. m_stoneShader = m_shaderCache->get(QStringLiteral("stone_instanced"));
  48. m_plantShader = m_shaderCache->get(QStringLiteral("plant_instanced"));
  49. m_pineShader = m_shaderCache->get(QStringLiteral("pine_instanced"));
  50. m_groundShader = m_shaderCache->get(QStringLiteral("ground_plane"));
  51. m_terrainShader = m_shaderCache->get(QStringLiteral("terrain_chunk"));
  52. m_archerShader = m_shaderCache->get(QStringLiteral("archer"));
  53. m_knightShader = m_shaderCache->get(QStringLiteral("knight"));
  54. if (!m_basicShader)
  55. qWarning() << "Backend: basic shader missing";
  56. if (!m_gridShader)
  57. qWarning() << "Backend: grid shader missing";
  58. if (!m_cylinderShader)
  59. qWarning() << "Backend: cylinder shader missing";
  60. if (!m_fogShader)
  61. qWarning() << "Backend: fog shader missing";
  62. if (!m_grassShader)
  63. qWarning() << "Backend: grass shader missing";
  64. if (!m_stoneShader)
  65. qWarning() << "Backend: stone shader missing";
  66. if (!m_plantShader)
  67. qWarning()
  68. << "Backend: plant shader missing - check plant_instanced.vert/frag";
  69. if (!m_pineShader)
  70. qWarning()
  71. << "Backend: pine shader missing - check pine_instanced.vert/frag";
  72. if (!m_groundShader)
  73. qWarning() << "Backend: ground_plane shader missing";
  74. if (!m_terrainShader)
  75. qWarning() << "Backend: terrain shader missing";
  76. if (!m_archerShader)
  77. qWarning() << "Backend: archer shader missing";
  78. if (!m_knightShader)
  79. qWarning() << "Backend: knight shader missing";
  80. cacheBasicUniforms();
  81. cacheArcherUniforms();
  82. cacheKnightUniforms();
  83. cacheGridUniforms();
  84. cacheCylinderUniforms();
  85. cacheFogUniforms();
  86. cacheGrassUniforms();
  87. cacheStoneUniforms();
  88. cachePlantUniforms();
  89. cachePineUniforms();
  90. cacheGroundUniforms();
  91. cacheTerrainUniforms();
  92. initializeCylinderPipeline();
  93. initializeFogPipeline();
  94. initializeGrassPipeline();
  95. initializeStonePipeline();
  96. initializePlantPipeline();
  97. initializePinePipeline();
  98. }
  99. void Backend::beginFrame() {
  100. if (m_viewportWidth > 0 && m_viewportHeight > 0) {
  101. glViewport(0, 0, m_viewportWidth, m_viewportHeight);
  102. }
  103. glClearColor(m_clearColor[0], m_clearColor[1], m_clearColor[2],
  104. m_clearColor[3]);
  105. glClearDepth(1.0);
  106. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  107. glEnable(GL_DEPTH_TEST);
  108. glDepthFunc(GL_LESS);
  109. glDepthMask(GL_TRUE);
  110. if (m_usePersistentBuffers) {
  111. if (m_cylinderPersistentBuffer.isValid()) {
  112. m_cylinderPersistentBuffer.beginFrame();
  113. }
  114. if (m_fogPersistentBuffer.isValid()) {
  115. m_fogPersistentBuffer.beginFrame();
  116. }
  117. }
  118. }
  119. void Backend::setViewport(int w, int h) {
  120. m_viewportWidth = w;
  121. m_viewportHeight = h;
  122. }
  123. void Backend::setClearColor(float r, float g, float b, float a) {
  124. m_clearColor[0] = r;
  125. m_clearColor[1] = g;
  126. m_clearColor[2] = b;
  127. m_clearColor[3] = a;
  128. }
  129. void Backend::execute(const DrawQueue &queue, const Camera &cam) {
  130. if (!m_basicShader)
  131. return;
  132. const QMatrix4x4 viewProj = cam.getProjectionMatrix() * cam.getViewMatrix();
  133. m_lastBoundShader = nullptr;
  134. m_lastBoundTexture = nullptr;
  135. const std::size_t count = queue.size();
  136. std::size_t i = 0;
  137. while (i < count) {
  138. const auto &cmd = queue.getSorted(i);
  139. switch (cmd.index()) {
  140. case CylinderCmdIndex: {
  141. m_cylinderScratch.clear();
  142. do {
  143. const auto &cy = std::get<CylinderCmdIndex>(queue.getSorted(i));
  144. CylinderInstanceGpu gpu{};
  145. gpu.start = cy.start;
  146. gpu.end = cy.end;
  147. gpu.radius = cy.radius;
  148. gpu.alpha = cy.alpha;
  149. gpu.color = cy.color;
  150. m_cylinderScratch.emplace_back(gpu);
  151. ++i;
  152. } while (i < count && queue.getSorted(i).index() == CylinderCmdIndex);
  153. const std::size_t instanceCount = m_cylinderScratch.size();
  154. if (instanceCount > 0 && m_cylinderShader && m_cylinderVao) {
  155. glDepthMask(GL_TRUE);
  156. if (glIsEnabled(GL_POLYGON_OFFSET_FILL))
  157. glDisable(GL_POLYGON_OFFSET_FILL);
  158. if (m_lastBoundShader != m_cylinderShader) {
  159. m_cylinderShader->use();
  160. m_lastBoundShader = m_cylinderShader;
  161. m_lastBoundTexture = nullptr;
  162. }
  163. if (m_cylinderUniforms.viewProj != Shader::InvalidUniform) {
  164. m_cylinderShader->setUniform(m_cylinderUniforms.viewProj, viewProj);
  165. }
  166. uploadCylinderInstances(instanceCount);
  167. drawCylinders(instanceCount);
  168. }
  169. continue;
  170. }
  171. case FogBatchCmdIndex: {
  172. const auto &batch = std::get<FogBatchCmdIndex>(cmd);
  173. const FogInstanceData *instances = batch.instances;
  174. const std::size_t instanceCount = batch.count;
  175. if (instances && instanceCount > 0 && m_fogShader && m_fogVao) {
  176. m_fogScratch.resize(instanceCount);
  177. for (std::size_t idx = 0; idx < instanceCount; ++idx) {
  178. FogInstanceGpu gpu{};
  179. gpu.center = instances[idx].center;
  180. gpu.size = instances[idx].size;
  181. gpu.color = instances[idx].color;
  182. gpu.alpha = instances[idx].alpha;
  183. m_fogScratch[idx] = gpu;
  184. }
  185. glDepthMask(GL_TRUE);
  186. if (glIsEnabled(GL_POLYGON_OFFSET_FILL))
  187. glDisable(GL_POLYGON_OFFSET_FILL);
  188. if (m_lastBoundShader != m_fogShader) {
  189. m_fogShader->use();
  190. m_lastBoundShader = m_fogShader;
  191. m_lastBoundTexture = nullptr;
  192. }
  193. if (m_fogUniforms.viewProj != Shader::InvalidUniform) {
  194. m_fogShader->setUniform(m_fogUniforms.viewProj, viewProj);
  195. }
  196. uploadFogInstances(instanceCount);
  197. drawFog(instanceCount);
  198. }
  199. ++i;
  200. continue;
  201. }
  202. case GrassBatchCmdIndex: {
  203. const auto &grass = std::get<GrassBatchCmdIndex>(cmd);
  204. if (!grass.instanceBuffer || grass.instanceCount == 0 || !m_grassShader ||
  205. !m_grassVao || m_grassVertexCount == 0)
  206. break;
  207. DepthMaskScope depthMask(false);
  208. BlendScope blend(true);
  209. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  210. GLboolean prevCull = glIsEnabled(GL_CULL_FACE);
  211. if (prevCull)
  212. glDisable(GL_CULL_FACE);
  213. if (m_lastBoundShader != m_grassShader) {
  214. m_grassShader->use();
  215. m_lastBoundShader = m_grassShader;
  216. m_lastBoundTexture = nullptr;
  217. }
  218. if (m_grassUniforms.viewProj != Shader::InvalidUniform) {
  219. m_grassShader->setUniform(m_grassUniforms.viewProj, viewProj);
  220. }
  221. if (m_grassUniforms.time != Shader::InvalidUniform) {
  222. m_grassShader->setUniform(m_grassUniforms.time, grass.params.time);
  223. }
  224. if (m_grassUniforms.windStrength != Shader::InvalidUniform) {
  225. m_grassShader->setUniform(m_grassUniforms.windStrength,
  226. grass.params.windStrength);
  227. }
  228. if (m_grassUniforms.windSpeed != Shader::InvalidUniform) {
  229. m_grassShader->setUniform(m_grassUniforms.windSpeed,
  230. grass.params.windSpeed);
  231. }
  232. if (m_grassUniforms.soilColor != Shader::InvalidUniform) {
  233. m_grassShader->setUniform(m_grassUniforms.soilColor,
  234. grass.params.soilColor);
  235. }
  236. if (m_grassUniforms.lightDir != Shader::InvalidUniform) {
  237. QVector3D lightDir = grass.params.lightDirection;
  238. if (!lightDir.isNull())
  239. lightDir.normalize();
  240. m_grassShader->setUniform(m_grassUniforms.lightDir, lightDir);
  241. }
  242. glBindVertexArray(m_grassVao);
  243. grass.instanceBuffer->bind();
  244. const GLsizei stride = static_cast<GLsizei>(sizeof(GrassInstanceGpu));
  245. glVertexAttribPointer(
  246. 2, 4, GL_FLOAT, GL_FALSE, stride,
  247. reinterpret_cast<void *>(offsetof(GrassInstanceGpu, posHeight)));
  248. glVertexAttribPointer(
  249. 3, 4, GL_FLOAT, GL_FALSE, stride,
  250. reinterpret_cast<void *>(offsetof(GrassInstanceGpu, colorWidth)));
  251. glVertexAttribPointer(
  252. 4, 4, GL_FLOAT, GL_FALSE, stride,
  253. reinterpret_cast<void *>(offsetof(GrassInstanceGpu, swayParams)));
  254. grass.instanceBuffer->unbind();
  255. glDrawArraysInstanced(GL_TRIANGLES, 0, m_grassVertexCount,
  256. static_cast<GLsizei>(grass.instanceCount));
  257. glBindVertexArray(0);
  258. if (prevCull)
  259. glEnable(GL_CULL_FACE);
  260. break;
  261. }
  262. case StoneBatchCmdIndex: {
  263. const auto &stone = std::get<StoneBatchCmdIndex>(cmd);
  264. if (!stone.instanceBuffer || stone.instanceCount == 0 || !m_stoneShader ||
  265. !m_stoneVao || m_stoneIndexCount == 0)
  266. break;
  267. DepthMaskScope depthMask(true);
  268. BlendScope blend(false);
  269. if (m_lastBoundShader != m_stoneShader) {
  270. m_stoneShader->use();
  271. m_lastBoundShader = m_stoneShader;
  272. m_lastBoundTexture = nullptr;
  273. }
  274. if (m_stoneUniforms.viewProj != Shader::InvalidUniform) {
  275. m_stoneShader->setUniform(m_stoneUniforms.viewProj, viewProj);
  276. }
  277. if (m_stoneUniforms.lightDirection != Shader::InvalidUniform) {
  278. QVector3D lightDir = stone.params.lightDirection;
  279. if (!lightDir.isNull())
  280. lightDir.normalize();
  281. m_stoneShader->setUniform(m_stoneUniforms.lightDirection, lightDir);
  282. }
  283. glBindVertexArray(m_stoneVao);
  284. stone.instanceBuffer->bind();
  285. const GLsizei stride = static_cast<GLsizei>(sizeof(StoneInstanceGpu));
  286. glVertexAttribPointer(
  287. 2, 4, GL_FLOAT, GL_FALSE, stride,
  288. reinterpret_cast<void *>(offsetof(StoneInstanceGpu, posScale)));
  289. glVertexAttribPointer(
  290. 3, 4, GL_FLOAT, GL_FALSE, stride,
  291. reinterpret_cast<void *>(offsetof(StoneInstanceGpu, colorRot)));
  292. stone.instanceBuffer->unbind();
  293. glDrawElementsInstanced(GL_TRIANGLES, m_stoneIndexCount,
  294. GL_UNSIGNED_SHORT, nullptr,
  295. static_cast<GLsizei>(stone.instanceCount));
  296. glBindVertexArray(0);
  297. break;
  298. }
  299. case PlantBatchCmdIndex: {
  300. const auto &plant = std::get<PlantBatchCmdIndex>(cmd);
  301. if (!plant.instanceBuffer || plant.instanceCount == 0 || !m_plantShader ||
  302. !m_plantVao || m_plantIndexCount == 0) {
  303. break;
  304. }
  305. DepthMaskScope depthMask(false);
  306. glEnable(GL_DEPTH_TEST);
  307. BlendScope blend(true);
  308. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  309. GLboolean prevCull = glIsEnabled(GL_CULL_FACE);
  310. if (prevCull)
  311. glDisable(GL_CULL_FACE);
  312. if (m_lastBoundShader != m_plantShader) {
  313. m_plantShader->use();
  314. m_lastBoundShader = m_plantShader;
  315. m_lastBoundTexture = nullptr;
  316. }
  317. if (m_plantUniforms.viewProj != Shader::InvalidUniform) {
  318. m_plantShader->setUniform(m_plantUniforms.viewProj, viewProj);
  319. }
  320. if (m_plantUniforms.time != Shader::InvalidUniform) {
  321. m_plantShader->setUniform(m_plantUniforms.time, plant.params.time);
  322. }
  323. if (m_plantUniforms.windStrength != Shader::InvalidUniform) {
  324. m_plantShader->setUniform(m_plantUniforms.windStrength,
  325. plant.params.windStrength);
  326. }
  327. if (m_plantUniforms.windSpeed != Shader::InvalidUniform) {
  328. m_plantShader->setUniform(m_plantUniforms.windSpeed,
  329. plant.params.windSpeed);
  330. }
  331. if (m_plantUniforms.lightDirection != Shader::InvalidUniform) {
  332. QVector3D lightDir = plant.params.lightDirection;
  333. if (!lightDir.isNull())
  334. lightDir.normalize();
  335. m_plantShader->setUniform(m_plantUniforms.lightDirection, lightDir);
  336. }
  337. glBindVertexArray(m_plantVao);
  338. plant.instanceBuffer->bind();
  339. const GLsizei stride = static_cast<GLsizei>(sizeof(PlantInstanceGpu));
  340. glVertexAttribPointer(
  341. 3, 4, GL_FLOAT, GL_FALSE, stride,
  342. reinterpret_cast<void *>(offsetof(PlantInstanceGpu, posScale)));
  343. glVertexAttribPointer(
  344. 4, 4, GL_FLOAT, GL_FALSE, stride,
  345. reinterpret_cast<void *>(offsetof(PlantInstanceGpu, colorSway)));
  346. glVertexAttribPointer(
  347. 5, 4, GL_FLOAT, GL_FALSE, stride,
  348. reinterpret_cast<void *>(offsetof(PlantInstanceGpu, typeParams)));
  349. plant.instanceBuffer->unbind();
  350. glDrawElementsInstanced(GL_TRIANGLES, m_plantIndexCount,
  351. GL_UNSIGNED_SHORT, nullptr,
  352. static_cast<GLsizei>(plant.instanceCount));
  353. glBindVertexArray(0);
  354. if (prevCull)
  355. glEnable(GL_CULL_FACE);
  356. break;
  357. }
  358. case PineBatchCmdIndex: {
  359. const auto &pine = std::get<PineBatchCmdIndex>(cmd);
  360. if (!pine.instanceBuffer || pine.instanceCount == 0 || !m_pineShader ||
  361. !m_pineVao || m_pineIndexCount == 0) {
  362. break;
  363. }
  364. DepthMaskScope depthMask(false);
  365. glEnable(GL_DEPTH_TEST);
  366. BlendScope blend(true);
  367. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  368. GLboolean prevCull = glIsEnabled(GL_CULL_FACE);
  369. if (prevCull)
  370. glDisable(GL_CULL_FACE);
  371. if (m_lastBoundShader != m_pineShader) {
  372. m_pineShader->use();
  373. m_lastBoundShader = m_pineShader;
  374. m_lastBoundTexture = nullptr;
  375. }
  376. if (m_pineUniforms.viewProj != Shader::InvalidUniform) {
  377. m_pineShader->setUniform(m_pineUniforms.viewProj, viewProj);
  378. }
  379. if (m_pineUniforms.time != Shader::InvalidUniform) {
  380. m_pineShader->setUniform(m_pineUniforms.time, pine.params.time);
  381. }
  382. if (m_pineUniforms.windStrength != Shader::InvalidUniform) {
  383. m_pineShader->setUniform(m_pineUniforms.windStrength,
  384. pine.params.windStrength);
  385. }
  386. if (m_pineUniforms.windSpeed != Shader::InvalidUniform) {
  387. m_pineShader->setUniform(m_pineUniforms.windSpeed,
  388. pine.params.windSpeed);
  389. }
  390. if (m_pineUniforms.lightDirection != Shader::InvalidUniform) {
  391. QVector3D lightDir = pine.params.lightDirection;
  392. if (!lightDir.isNull())
  393. lightDir.normalize();
  394. m_pineShader->setUniform(m_pineUniforms.lightDirection, lightDir);
  395. }
  396. glBindVertexArray(m_pineVao);
  397. pine.instanceBuffer->bind();
  398. const GLsizei stride = static_cast<GLsizei>(sizeof(PineInstanceGpu));
  399. glVertexAttribPointer(
  400. 3, 4, GL_FLOAT, GL_FALSE, stride,
  401. reinterpret_cast<void *>(offsetof(PineInstanceGpu, posScale)));
  402. glVertexAttribPointer(
  403. 4, 4, GL_FLOAT, GL_FALSE, stride,
  404. reinterpret_cast<void *>(offsetof(PineInstanceGpu, colorSway)));
  405. glVertexAttribPointer(
  406. 5, 4, GL_FLOAT, GL_FALSE, stride,
  407. reinterpret_cast<void *>(offsetof(PineInstanceGpu, rotation)));
  408. pine.instanceBuffer->unbind();
  409. glDrawElementsInstanced(GL_TRIANGLES, m_pineIndexCount, GL_UNSIGNED_SHORT,
  410. nullptr,
  411. static_cast<GLsizei>(pine.instanceCount));
  412. glBindVertexArray(0);
  413. if (prevCull)
  414. glEnable(GL_CULL_FACE);
  415. break;
  416. }
  417. case TerrainChunkCmdIndex: {
  418. const auto &terrain = std::get<TerrainChunkCmdIndex>(cmd);
  419. Shader *activeShader =
  420. terrain.params.isGroundPlane ? m_groundShader : m_terrainShader;
  421. if (!terrain.mesh || !activeShader)
  422. break;
  423. if (m_lastBoundShader != activeShader) {
  424. activeShader->use();
  425. m_lastBoundShader = activeShader;
  426. m_lastBoundTexture = nullptr;
  427. }
  428. const QMatrix4x4 mvp = viewProj * terrain.model;
  429. if (terrain.params.isGroundPlane) {
  430. if (m_groundUniforms.mvp != Shader::InvalidUniform)
  431. activeShader->setUniform(m_groundUniforms.mvp, mvp);
  432. if (m_groundUniforms.model != Shader::InvalidUniform)
  433. activeShader->setUniform(m_groundUniforms.model, terrain.model);
  434. if (m_groundUniforms.grassPrimary != Shader::InvalidUniform)
  435. activeShader->setUniform(m_groundUniforms.grassPrimary,
  436. terrain.params.grassPrimary);
  437. if (m_groundUniforms.grassSecondary != Shader::InvalidUniform)
  438. activeShader->setUniform(m_groundUniforms.grassSecondary,
  439. terrain.params.grassSecondary);
  440. if (m_groundUniforms.grassDry != Shader::InvalidUniform)
  441. activeShader->setUniform(m_groundUniforms.grassDry,
  442. terrain.params.grassDry);
  443. if (m_groundUniforms.soilColor != Shader::InvalidUniform)
  444. activeShader->setUniform(m_groundUniforms.soilColor,
  445. terrain.params.soilColor);
  446. if (m_groundUniforms.tint != Shader::InvalidUniform)
  447. activeShader->setUniform(m_groundUniforms.tint, terrain.params.tint);
  448. if (m_groundUniforms.noiseOffset != Shader::InvalidUniform)
  449. activeShader->setUniform(m_groundUniforms.noiseOffset,
  450. terrain.params.noiseOffset);
  451. if (m_groundUniforms.tileSize != Shader::InvalidUniform)
  452. activeShader->setUniform(m_groundUniforms.tileSize,
  453. terrain.params.tileSize);
  454. if (m_groundUniforms.macroNoiseScale != Shader::InvalidUniform)
  455. activeShader->setUniform(m_groundUniforms.macroNoiseScale,
  456. terrain.params.macroNoiseScale);
  457. if (m_groundUniforms.detailNoiseScale != Shader::InvalidUniform)
  458. activeShader->setUniform(m_groundUniforms.detailNoiseScale,
  459. terrain.params.detailNoiseScale);
  460. if (m_groundUniforms.soilBlendHeight != Shader::InvalidUniform)
  461. activeShader->setUniform(m_groundUniforms.soilBlendHeight,
  462. terrain.params.soilBlendHeight);
  463. if (m_groundUniforms.soilBlendSharpness != Shader::InvalidUniform)
  464. activeShader->setUniform(m_groundUniforms.soilBlendSharpness,
  465. terrain.params.soilBlendSharpness);
  466. if (m_groundUniforms.ambientBoost != Shader::InvalidUniform)
  467. activeShader->setUniform(m_groundUniforms.ambientBoost,
  468. terrain.params.ambientBoost);
  469. if (m_groundUniforms.lightDir != Shader::InvalidUniform) {
  470. QVector3D lightDir = terrain.params.lightDirection;
  471. if (!lightDir.isNull())
  472. lightDir.normalize();
  473. activeShader->setUniform(m_groundUniforms.lightDir, lightDir);
  474. }
  475. } else {
  476. if (m_terrainUniforms.mvp != Shader::InvalidUniform)
  477. activeShader->setUniform(m_terrainUniforms.mvp, mvp);
  478. if (m_terrainUniforms.model != Shader::InvalidUniform)
  479. activeShader->setUniform(m_terrainUniforms.model, terrain.model);
  480. if (m_terrainUniforms.grassPrimary != Shader::InvalidUniform)
  481. activeShader->setUniform(m_terrainUniforms.grassPrimary,
  482. terrain.params.grassPrimary);
  483. if (m_terrainUniforms.grassSecondary != Shader::InvalidUniform)
  484. activeShader->setUniform(m_terrainUniforms.grassSecondary,
  485. terrain.params.grassSecondary);
  486. if (m_terrainUniforms.grassDry != Shader::InvalidUniform)
  487. activeShader->setUniform(m_terrainUniforms.grassDry,
  488. terrain.params.grassDry);
  489. if (m_terrainUniforms.soilColor != Shader::InvalidUniform)
  490. activeShader->setUniform(m_terrainUniforms.soilColor,
  491. terrain.params.soilColor);
  492. if (m_terrainUniforms.rockLow != Shader::InvalidUniform)
  493. activeShader->setUniform(m_terrainUniforms.rockLow,
  494. terrain.params.rockLow);
  495. if (m_terrainUniforms.rockHigh != Shader::InvalidUniform)
  496. activeShader->setUniform(m_terrainUniforms.rockHigh,
  497. terrain.params.rockHigh);
  498. if (m_terrainUniforms.tint != Shader::InvalidUniform)
  499. activeShader->setUniform(m_terrainUniforms.tint, terrain.params.tint);
  500. if (m_terrainUniforms.noiseOffset != Shader::InvalidUniform)
  501. activeShader->setUniform(m_terrainUniforms.noiseOffset,
  502. terrain.params.noiseOffset);
  503. if (m_terrainUniforms.tileSize != Shader::InvalidUniform)
  504. activeShader->setUniform(m_terrainUniforms.tileSize,
  505. terrain.params.tileSize);
  506. if (m_terrainUniforms.macroNoiseScale != Shader::InvalidUniform)
  507. activeShader->setUniform(m_terrainUniforms.macroNoiseScale,
  508. terrain.params.macroNoiseScale);
  509. if (m_terrainUniforms.detailNoiseScale != Shader::InvalidUniform)
  510. activeShader->setUniform(m_terrainUniforms.detailNoiseScale,
  511. terrain.params.detailNoiseScale);
  512. if (m_terrainUniforms.slopeRockThreshold != Shader::InvalidUniform)
  513. activeShader->setUniform(m_terrainUniforms.slopeRockThreshold,
  514. terrain.params.slopeRockThreshold);
  515. if (m_terrainUniforms.slopeRockSharpness != Shader::InvalidUniform)
  516. activeShader->setUniform(m_terrainUniforms.slopeRockSharpness,
  517. terrain.params.slopeRockSharpness);
  518. if (m_terrainUniforms.soilBlendHeight != Shader::InvalidUniform)
  519. activeShader->setUniform(m_terrainUniforms.soilBlendHeight,
  520. terrain.params.soilBlendHeight);
  521. if (m_terrainUniforms.soilBlendSharpness != Shader::InvalidUniform)
  522. activeShader->setUniform(m_terrainUniforms.soilBlendSharpness,
  523. terrain.params.soilBlendSharpness);
  524. if (m_terrainUniforms.heightNoiseStrength != Shader::InvalidUniform)
  525. activeShader->setUniform(m_terrainUniforms.heightNoiseStrength,
  526. terrain.params.heightNoiseStrength);
  527. if (m_terrainUniforms.heightNoiseFrequency != Shader::InvalidUniform)
  528. activeShader->setUniform(m_terrainUniforms.heightNoiseFrequency,
  529. terrain.params.heightNoiseFrequency);
  530. if (m_terrainUniforms.ambientBoost != Shader::InvalidUniform)
  531. activeShader->setUniform(m_terrainUniforms.ambientBoost,
  532. terrain.params.ambientBoost);
  533. if (m_terrainUniforms.rockDetailStrength != Shader::InvalidUniform)
  534. activeShader->setUniform(m_terrainUniforms.rockDetailStrength,
  535. terrain.params.rockDetailStrength);
  536. if (m_terrainUniforms.lightDir != Shader::InvalidUniform) {
  537. QVector3D lightDir = terrain.params.lightDirection;
  538. if (!lightDir.isNull())
  539. lightDir.normalize();
  540. activeShader->setUniform(m_terrainUniforms.lightDir, lightDir);
  541. }
  542. }
  543. DepthMaskScope depthMask(terrain.depthWrite);
  544. std::unique_ptr<PolygonOffsetScope> polyScope;
  545. if (terrain.depthBias != 0.0f)
  546. polyScope = std::make_unique<PolygonOffsetScope>(terrain.depthBias,
  547. terrain.depthBias);
  548. terrain.mesh->draw();
  549. break;
  550. }
  551. case MeshCmdIndex: {
  552. const auto &it = std::get<MeshCmdIndex>(cmd);
  553. if (!it.mesh)
  554. break;
  555. glDepthMask(GL_TRUE);
  556. if (glIsEnabled(GL_POLYGON_OFFSET_FILL))
  557. glDisable(GL_POLYGON_OFFSET_FILL);
  558. Shader *activeShader = it.shader ? it.shader : m_basicShader;
  559. if (!activeShader)
  560. break;
  561. BasicUniforms *uniforms = &m_basicUniforms;
  562. if (activeShader == m_archerShader)
  563. uniforms = &m_archerUniforms;
  564. else if (activeShader == m_knightShader)
  565. uniforms = &m_knightUniforms;
  566. if (m_lastBoundShader != activeShader) {
  567. activeShader->use();
  568. m_lastBoundShader = activeShader;
  569. }
  570. activeShader->setUniform(uniforms->mvp, it.mvp);
  571. activeShader->setUniform(uniforms->model, it.model);
  572. Texture *texToUse = it.texture
  573. ? it.texture
  574. : (m_resources ? m_resources->white() : nullptr);
  575. if (texToUse && texToUse != m_lastBoundTexture) {
  576. texToUse->bind(0);
  577. m_lastBoundTexture = texToUse;
  578. activeShader->setUniform(uniforms->texture, 0);
  579. }
  580. activeShader->setUniform(uniforms->useTexture, it.texture != nullptr);
  581. activeShader->setUniform(uniforms->color, it.color);
  582. activeShader->setUniform(uniforms->alpha, it.alpha);
  583. it.mesh->draw();
  584. break;
  585. }
  586. case GridCmdIndex: {
  587. if (!m_gridShader)
  588. break;
  589. const auto &gc = std::get<GridCmdIndex>(cmd);
  590. if (m_lastBoundShader != m_gridShader) {
  591. m_gridShader->use();
  592. m_lastBoundShader = m_gridShader;
  593. }
  594. m_gridShader->setUniform(m_gridUniforms.mvp, gc.mvp);
  595. m_gridShader->setUniform(m_gridUniforms.model, gc.model);
  596. m_gridShader->setUniform(m_gridUniforms.gridColor, gc.color);
  597. m_gridShader->setUniform(m_gridUniforms.lineColor, kGridLineColor);
  598. m_gridShader->setUniform(m_gridUniforms.cellSize, gc.cellSize);
  599. m_gridShader->setUniform(m_gridUniforms.thickness, gc.thickness);
  600. if (m_resources) {
  601. if (auto *plane = m_resources->ground())
  602. plane->draw();
  603. }
  604. break;
  605. }
  606. case SelectionRingCmdIndex: {
  607. const auto &sc = std::get<SelectionRingCmdIndex>(cmd);
  608. Mesh *ring = Render::Geom::SelectionRing::get();
  609. if (!ring)
  610. break;
  611. if (m_lastBoundShader != m_basicShader) {
  612. m_basicShader->use();
  613. m_lastBoundShader = m_basicShader;
  614. }
  615. m_basicShader->use();
  616. m_basicShader->setUniform(m_basicUniforms.useTexture, false);
  617. m_basicShader->setUniform(m_basicUniforms.color, sc.color);
  618. DepthMaskScope depthMask(false);
  619. DepthTestScope depthTest(false);
  620. PolygonOffsetScope poly(-1.0f, -1.0f);
  621. BlendScope blend(true);
  622. {
  623. QMatrix4x4 m = sc.model;
  624. m.scale(1.08f, 1.0f, 1.08f);
  625. const QMatrix4x4 mvp = viewProj * m;
  626. m_basicShader->setUniform(m_basicUniforms.mvp, mvp);
  627. m_basicShader->setUniform(m_basicUniforms.model, m);
  628. m_basicShader->setUniform(m_basicUniforms.alpha, sc.alphaOuter);
  629. ring->draw();
  630. }
  631. {
  632. const QMatrix4x4 mvp = viewProj * sc.model;
  633. m_basicShader->setUniform(m_basicUniforms.mvp, mvp);
  634. m_basicShader->setUniform(m_basicUniforms.model, sc.model);
  635. m_basicShader->setUniform(m_basicUniforms.alpha, sc.alphaInner);
  636. ring->draw();
  637. }
  638. break;
  639. }
  640. case SelectionSmokeCmdIndex: {
  641. const auto &sm = std::get<SelectionSmokeCmdIndex>(cmd);
  642. Mesh *disc = Render::Geom::SelectionDisc::get();
  643. if (!disc)
  644. break;
  645. if (m_lastBoundShader != m_basicShader) {
  646. m_basicShader->use();
  647. m_lastBoundShader = m_basicShader;
  648. }
  649. m_basicShader->setUniform(m_basicUniforms.useTexture, false);
  650. m_basicShader->setUniform(m_basicUniforms.color, sm.color);
  651. DepthMaskScope depthMask(false);
  652. DepthTestScope depthTest(true);
  653. PolygonOffsetScope poly(-1.0f, -1.0f);
  654. BlendScope blend(true);
  655. for (int i = 0; i < 7; ++i) {
  656. float scale = 1.35f + 0.12f * i;
  657. float a = sm.baseAlpha * (1.0f - 0.09f * i);
  658. QMatrix4x4 m = sm.model;
  659. m.translate(0.0f, 0.02f, 0.0f);
  660. m.scale(scale, 1.0f, scale);
  661. const QMatrix4x4 mvp = viewProj * m;
  662. m_basicShader->setUniform(m_basicUniforms.mvp, mvp);
  663. m_basicShader->setUniform(m_basicUniforms.model, m);
  664. m_basicShader->setUniform(m_basicUniforms.alpha, a);
  665. disc->draw();
  666. }
  667. break;
  668. }
  669. default:
  670. break;
  671. }
  672. ++i;
  673. }
  674. if (m_lastBoundShader) {
  675. m_lastBoundShader->release();
  676. m_lastBoundShader = nullptr;
  677. }
  678. }
  679. void Backend::cacheBasicUniforms() {
  680. if (!m_basicShader)
  681. return;
  682. m_basicUniforms.mvp = m_basicShader->uniformHandle("u_mvp");
  683. m_basicUniforms.model = m_basicShader->uniformHandle("u_model");
  684. m_basicUniforms.texture = m_basicShader->uniformHandle("u_texture");
  685. m_basicUniforms.useTexture = m_basicShader->uniformHandle("u_useTexture");
  686. m_basicUniforms.color = m_basicShader->uniformHandle("u_color");
  687. m_basicUniforms.alpha = m_basicShader->uniformHandle("u_alpha");
  688. }
  689. void Backend::cacheArcherUniforms() {
  690. if (!m_archerShader)
  691. return;
  692. m_archerUniforms.mvp = m_archerShader->uniformHandle("u_mvp");
  693. m_archerUniforms.model = m_archerShader->uniformHandle("u_model");
  694. m_archerUniforms.texture = m_archerShader->uniformHandle("u_texture");
  695. m_archerUniforms.useTexture = m_archerShader->uniformHandle("u_useTexture");
  696. m_archerUniforms.color = m_archerShader->uniformHandle("u_color");
  697. m_archerUniforms.alpha = m_archerShader->uniformHandle("u_alpha");
  698. }
  699. void Backend::cacheKnightUniforms() {
  700. if (!m_knightShader)
  701. return;
  702. m_knightUniforms.mvp = m_knightShader->uniformHandle("u_mvp");
  703. m_knightUniforms.model = m_knightShader->uniformHandle("u_model");
  704. m_knightUniforms.texture = m_knightShader->uniformHandle("u_texture");
  705. m_knightUniforms.useTexture = m_knightShader->uniformHandle("u_useTexture");
  706. m_knightUniforms.color = m_knightShader->uniformHandle("u_color");
  707. m_knightUniforms.alpha = m_knightShader->uniformHandle("u_alpha");
  708. }
  709. void Backend::cacheGridUniforms() {
  710. if (!m_gridShader)
  711. return;
  712. m_gridUniforms.mvp = m_gridShader->uniformHandle("u_mvp");
  713. m_gridUniforms.model = m_gridShader->uniformHandle("u_model");
  714. m_gridUniforms.gridColor = m_gridShader->uniformHandle("u_gridColor");
  715. m_gridUniforms.lineColor = m_gridShader->uniformHandle("u_lineColor");
  716. m_gridUniforms.cellSize = m_gridShader->uniformHandle("u_cellSize");
  717. m_gridUniforms.thickness = m_gridShader->uniformHandle("u_thickness");
  718. }
  719. void Backend::cacheCylinderUniforms() {
  720. if (!m_cylinderShader)
  721. return;
  722. m_cylinderUniforms.viewProj = m_cylinderShader->uniformHandle("u_viewProj");
  723. }
  724. void Backend::cacheFogUniforms() {
  725. if (!m_fogShader)
  726. return;
  727. m_fogUniforms.viewProj = m_fogShader->uniformHandle("u_viewProj");
  728. }
  729. void Backend::initializeCylinderPipeline() {
  730. initializeOpenGLFunctions();
  731. shutdownCylinderPipeline();
  732. Mesh *unit = getUnitCylinder();
  733. if (!unit)
  734. return;
  735. const auto &vertices = unit->getVertices();
  736. const auto &indices = unit->getIndices();
  737. if (vertices.empty() || indices.empty())
  738. return;
  739. glGenVertexArrays(1, &m_cylinderVao);
  740. glBindVertexArray(m_cylinderVao);
  741. glGenBuffers(1, &m_cylinderVertexBuffer);
  742. glBindBuffer(GL_ARRAY_BUFFER, m_cylinderVertexBuffer);
  743. glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex),
  744. vertices.data(), GL_STATIC_DRAW);
  745. glGenBuffers(1, &m_cylinderIndexBuffer);
  746. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_cylinderIndexBuffer);
  747. glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int),
  748. indices.data(), GL_STATIC_DRAW);
  749. m_cylinderIndexCount = static_cast<GLsizei>(indices.size());
  750. glEnableVertexAttribArray(0);
  751. glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
  752. reinterpret_cast<void *>(offsetof(Vertex, position)));
  753. glEnableVertexAttribArray(1);
  754. glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
  755. reinterpret_cast<void *>(offsetof(Vertex, normal)));
  756. glEnableVertexAttribArray(2);
  757. glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex),
  758. reinterpret_cast<void *>(offsetof(Vertex, texCoord)));
  759. const std::size_t persistentCapacity = 10000;
  760. if (m_cylinderPersistentBuffer.initialize(persistentCapacity, 3)) {
  761. m_usePersistentBuffers = true;
  762. glBindBuffer(GL_ARRAY_BUFFER, m_cylinderPersistentBuffer.buffer());
  763. } else {
  764. m_usePersistentBuffers = false;
  765. glGenBuffers(1, &m_cylinderInstanceBuffer);
  766. glBindBuffer(GL_ARRAY_BUFFER, m_cylinderInstanceBuffer);
  767. m_cylinderInstanceCapacity = 256;
  768. glBufferData(GL_ARRAY_BUFFER,
  769. m_cylinderInstanceCapacity * sizeof(CylinderInstanceGpu),
  770. nullptr, GL_DYNAMIC_DRAW);
  771. }
  772. const GLsizei stride = static_cast<GLsizei>(sizeof(CylinderInstanceGpu));
  773. glEnableVertexAttribArray(3);
  774. glVertexAttribPointer(
  775. 3, 3, GL_FLOAT, GL_FALSE, stride,
  776. reinterpret_cast<void *>(offsetof(CylinderInstanceGpu, start)));
  777. glVertexAttribDivisor(3, 1);
  778. glEnableVertexAttribArray(4);
  779. glVertexAttribPointer(
  780. 4, 3, GL_FLOAT, GL_FALSE, stride,
  781. reinterpret_cast<void *>(offsetof(CylinderInstanceGpu, end)));
  782. glVertexAttribDivisor(4, 1);
  783. glEnableVertexAttribArray(5);
  784. glVertexAttribPointer(
  785. 5, 1, GL_FLOAT, GL_FALSE, stride,
  786. reinterpret_cast<void *>(offsetof(CylinderInstanceGpu, radius)));
  787. glVertexAttribDivisor(5, 1);
  788. glEnableVertexAttribArray(6);
  789. glVertexAttribPointer(
  790. 6, 1, GL_FLOAT, GL_FALSE, stride,
  791. reinterpret_cast<void *>(offsetof(CylinderInstanceGpu, alpha)));
  792. glVertexAttribDivisor(6, 1);
  793. glEnableVertexAttribArray(7);
  794. glVertexAttribPointer(
  795. 7, 3, GL_FLOAT, GL_FALSE, stride,
  796. reinterpret_cast<void *>(offsetof(CylinderInstanceGpu, color)));
  797. glVertexAttribDivisor(7, 1);
  798. glBindVertexArray(0);
  799. glBindBuffer(GL_ARRAY_BUFFER, 0);
  800. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
  801. m_cylinderScratch.reserve(
  802. m_usePersistentBuffers ? persistentCapacity : m_cylinderInstanceCapacity);
  803. }
  804. void Backend::shutdownCylinderPipeline() {
  805. initializeOpenGLFunctions();
  806. m_cylinderPersistentBuffer.destroy();
  807. if (m_cylinderInstanceBuffer) {
  808. glDeleteBuffers(1, &m_cylinderInstanceBuffer);
  809. m_cylinderInstanceBuffer = 0;
  810. }
  811. if (m_cylinderVertexBuffer) {
  812. glDeleteBuffers(1, &m_cylinderVertexBuffer);
  813. m_cylinderVertexBuffer = 0;
  814. }
  815. if (m_cylinderIndexBuffer) {
  816. glDeleteBuffers(1, &m_cylinderIndexBuffer);
  817. m_cylinderIndexBuffer = 0;
  818. }
  819. if (m_cylinderVao) {
  820. glDeleteVertexArrays(1, &m_cylinderVao);
  821. m_cylinderVao = 0;
  822. }
  823. m_cylinderIndexCount = 0;
  824. m_cylinderInstanceCapacity = 0;
  825. m_cylinderScratch.clear();
  826. }
  827. void Backend::uploadCylinderInstances(std::size_t count) {
  828. if (count == 0)
  829. return;
  830. initializeOpenGLFunctions();
  831. if (m_usePersistentBuffers && m_cylinderPersistentBuffer.isValid()) {
  832. if (count > m_cylinderPersistentBuffer.capacity()) {
  833. count = m_cylinderPersistentBuffer.capacity();
  834. }
  835. m_cylinderPersistentBuffer.write(m_cylinderScratch.data(), count);
  836. glBindBuffer(GL_ARRAY_BUFFER, m_cylinderPersistentBuffer.buffer());
  837. glBindBuffer(GL_ARRAY_BUFFER, 0);
  838. return;
  839. }
  840. if (!m_cylinderInstanceBuffer)
  841. return;
  842. glBindBuffer(GL_ARRAY_BUFFER, m_cylinderInstanceBuffer);
  843. if (count > m_cylinderInstanceCapacity) {
  844. m_cylinderInstanceCapacity = std::max<std::size_t>(
  845. count,
  846. m_cylinderInstanceCapacity ? m_cylinderInstanceCapacity * 2 : count);
  847. glBufferData(GL_ARRAY_BUFFER,
  848. m_cylinderInstanceCapacity * sizeof(CylinderInstanceGpu),
  849. nullptr, GL_DYNAMIC_DRAW);
  850. m_cylinderScratch.reserve(m_cylinderInstanceCapacity);
  851. }
  852. glBufferSubData(GL_ARRAY_BUFFER, 0, count * sizeof(CylinderInstanceGpu),
  853. m_cylinderScratch.data());
  854. glBindBuffer(GL_ARRAY_BUFFER, 0);
  855. }
  856. void Backend::drawCylinders(std::size_t count) {
  857. if (!m_cylinderVao || m_cylinderIndexCount == 0 || count == 0)
  858. return;
  859. initializeOpenGLFunctions();
  860. glBindVertexArray(m_cylinderVao);
  861. glDrawElementsInstanced(GL_TRIANGLES, m_cylinderIndexCount, GL_UNSIGNED_INT,
  862. nullptr, static_cast<GLsizei>(count));
  863. glBindVertexArray(0);
  864. }
  865. void Backend::initializeFogPipeline() {
  866. initializeOpenGLFunctions();
  867. shutdownFogPipeline();
  868. const Vertex vertices[4] = {
  869. {{-0.5f, 0.0f, -0.5f}, {0.0f, 1.0f, 0.0f}, {0.0f, 0.0f}},
  870. {{0.5f, 0.0f, -0.5f}, {0.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
  871. {{-0.5f, 0.0f, 0.5f}, {0.0f, 1.0f, 0.0f}, {0.0f, 1.0f}},
  872. {{0.5f, 0.0f, 0.5f}, {0.0f, 1.0f, 0.0f}, {1.0f, 1.0f}},
  873. };
  874. const unsigned int indices[6] = {0, 1, 2, 2, 1, 3};
  875. glGenVertexArrays(1, &m_fogVao);
  876. glBindVertexArray(m_fogVao);
  877. glGenBuffers(1, &m_fogVertexBuffer);
  878. glBindBuffer(GL_ARRAY_BUFFER, m_fogVertexBuffer);
  879. glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
  880. glGenBuffers(1, &m_fogIndexBuffer);
  881. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_fogIndexBuffer);
  882. glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices,
  883. GL_STATIC_DRAW);
  884. m_fogIndexCount = 6;
  885. glEnableVertexAttribArray(0);
  886. glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
  887. reinterpret_cast<void *>(offsetof(Vertex, position)));
  888. glEnableVertexAttribArray(1);
  889. glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
  890. reinterpret_cast<void *>(offsetof(Vertex, normal)));
  891. glEnableVertexAttribArray(2);
  892. glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex),
  893. reinterpret_cast<void *>(offsetof(Vertex, texCoord)));
  894. glGenBuffers(1, &m_fogInstanceBuffer);
  895. glBindBuffer(GL_ARRAY_BUFFER, m_fogInstanceBuffer);
  896. m_fogInstanceCapacity = 512;
  897. glBufferData(GL_ARRAY_BUFFER, m_fogInstanceCapacity * sizeof(FogInstanceGpu),
  898. nullptr, GL_DYNAMIC_DRAW);
  899. const GLsizei stride = static_cast<GLsizei>(sizeof(FogInstanceGpu));
  900. glEnableVertexAttribArray(3);
  901. glVertexAttribPointer(
  902. 3, 3, GL_FLOAT, GL_FALSE, stride,
  903. reinterpret_cast<void *>(offsetof(FogInstanceGpu, center)));
  904. glVertexAttribDivisor(3, 1);
  905. glEnableVertexAttribArray(4);
  906. glVertexAttribPointer(
  907. 4, 1, GL_FLOAT, GL_FALSE, stride,
  908. reinterpret_cast<void *>(offsetof(FogInstanceGpu, size)));
  909. glVertexAttribDivisor(4, 1);
  910. glEnableVertexAttribArray(5);
  911. glVertexAttribPointer(
  912. 5, 3, GL_FLOAT, GL_FALSE, stride,
  913. reinterpret_cast<void *>(offsetof(FogInstanceGpu, color)));
  914. glVertexAttribDivisor(5, 1);
  915. glEnableVertexAttribArray(6);
  916. glVertexAttribPointer(
  917. 6, 1, GL_FLOAT, GL_FALSE, stride,
  918. reinterpret_cast<void *>(offsetof(FogInstanceGpu, alpha)));
  919. glVertexAttribDivisor(6, 1);
  920. glBindVertexArray(0);
  921. glBindBuffer(GL_ARRAY_BUFFER, 0);
  922. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
  923. m_fogScratch.reserve(m_fogInstanceCapacity);
  924. }
  925. void Backend::shutdownFogPipeline() {
  926. initializeOpenGLFunctions();
  927. if (m_fogInstanceBuffer) {
  928. glDeleteBuffers(1, &m_fogInstanceBuffer);
  929. m_fogInstanceBuffer = 0;
  930. }
  931. if (m_fogVertexBuffer) {
  932. glDeleteBuffers(1, &m_fogVertexBuffer);
  933. m_fogVertexBuffer = 0;
  934. }
  935. if (m_fogIndexBuffer) {
  936. glDeleteBuffers(1, &m_fogIndexBuffer);
  937. m_fogIndexBuffer = 0;
  938. }
  939. if (m_fogVao) {
  940. glDeleteVertexArrays(1, &m_fogVao);
  941. m_fogVao = 0;
  942. }
  943. m_fogIndexCount = 0;
  944. m_fogInstanceCapacity = 0;
  945. m_fogScratch.clear();
  946. }
  947. void Backend::uploadFogInstances(std::size_t count) {
  948. if (!m_fogInstanceBuffer || count == 0)
  949. return;
  950. initializeOpenGLFunctions();
  951. glBindBuffer(GL_ARRAY_BUFFER, m_fogInstanceBuffer);
  952. if (count > m_fogInstanceCapacity) {
  953. m_fogInstanceCapacity = std::max<std::size_t>(
  954. count, m_fogInstanceCapacity ? m_fogInstanceCapacity * 2 : count);
  955. glBufferData(GL_ARRAY_BUFFER,
  956. m_fogInstanceCapacity * sizeof(FogInstanceGpu), nullptr,
  957. GL_DYNAMIC_DRAW);
  958. m_fogScratch.reserve(m_fogInstanceCapacity);
  959. }
  960. glBufferSubData(GL_ARRAY_BUFFER, 0, count * sizeof(FogInstanceGpu),
  961. m_fogScratch.data());
  962. glBindBuffer(GL_ARRAY_BUFFER, 0);
  963. }
  964. void Backend::drawFog(std::size_t count) {
  965. if (!m_fogVao || m_fogIndexCount == 0 || count == 0)
  966. return;
  967. initializeOpenGLFunctions();
  968. glBindVertexArray(m_fogVao);
  969. glDrawElementsInstanced(GL_TRIANGLES, m_fogIndexCount, GL_UNSIGNED_INT,
  970. nullptr, static_cast<GLsizei>(count));
  971. glBindVertexArray(0);
  972. }
  973. void Backend::cacheGrassUniforms() {
  974. if (!m_grassShader)
  975. return;
  976. m_grassUniforms.viewProj = m_grassShader->uniformHandle("u_viewProj");
  977. m_grassUniforms.time = m_grassShader->uniformHandle("u_time");
  978. m_grassUniforms.windStrength = m_grassShader->uniformHandle("u_windStrength");
  979. m_grassUniforms.windSpeed = m_grassShader->uniformHandle("u_windSpeed");
  980. m_grassUniforms.soilColor = m_grassShader->uniformHandle("u_soilColor");
  981. m_grassUniforms.lightDir = m_grassShader->uniformHandle("u_lightDir");
  982. }
  983. void Backend::cacheGroundUniforms() {
  984. if (!m_groundShader)
  985. return;
  986. m_groundUniforms.mvp = m_groundShader->uniformHandle("u_mvp");
  987. m_groundUniforms.model = m_groundShader->uniformHandle("u_model");
  988. m_groundUniforms.grassPrimary =
  989. m_groundShader->uniformHandle("u_grassPrimary");
  990. m_groundUniforms.grassSecondary =
  991. m_groundShader->uniformHandle("u_grassSecondary");
  992. m_groundUniforms.grassDry = m_groundShader->uniformHandle("u_grassDry");
  993. m_groundUniforms.soilColor = m_groundShader->uniformHandle("u_soilColor");
  994. m_groundUniforms.tint = m_groundShader->uniformHandle("u_tint");
  995. m_groundUniforms.noiseOffset = m_groundShader->uniformHandle("u_noiseOffset");
  996. m_groundUniforms.tileSize = m_groundShader->uniformHandle("u_tileSize");
  997. m_groundUniforms.macroNoiseScale =
  998. m_groundShader->uniformHandle("u_macroNoiseScale");
  999. m_groundUniforms.detailNoiseScale =
  1000. m_groundShader->uniformHandle("u_detailNoiseScale");
  1001. m_groundUniforms.soilBlendHeight =
  1002. m_groundShader->uniformHandle("u_soilBlendHeight");
  1003. m_groundUniforms.soilBlendSharpness =
  1004. m_groundShader->uniformHandle("u_soilBlendSharpness");
  1005. m_groundUniforms.ambientBoost =
  1006. m_groundShader->uniformHandle("u_ambientBoost");
  1007. m_groundUniforms.lightDir = m_groundShader->uniformHandle("u_lightDir");
  1008. }
  1009. void Backend::cacheTerrainUniforms() {
  1010. if (!m_terrainShader)
  1011. return;
  1012. m_terrainUniforms.mvp = m_terrainShader->uniformHandle("u_mvp");
  1013. m_terrainUniforms.model = m_terrainShader->uniformHandle("u_model");
  1014. m_terrainUniforms.grassPrimary =
  1015. m_terrainShader->uniformHandle("u_grassPrimary");
  1016. m_terrainUniforms.grassSecondary =
  1017. m_terrainShader->uniformHandle("u_grassSecondary");
  1018. m_terrainUniforms.grassDry = m_terrainShader->uniformHandle("u_grassDry");
  1019. m_terrainUniforms.soilColor = m_terrainShader->uniformHandle("u_soilColor");
  1020. m_terrainUniforms.rockLow = m_terrainShader->uniformHandle("u_rockLow");
  1021. m_terrainUniforms.rockHigh = m_terrainShader->uniformHandle("u_rockHigh");
  1022. m_terrainUniforms.tint = m_terrainShader->uniformHandle("u_tint");
  1023. m_terrainUniforms.noiseOffset =
  1024. m_terrainShader->uniformHandle("u_noiseOffset");
  1025. m_terrainUniforms.tileSize = m_terrainShader->uniformHandle("u_tileSize");
  1026. m_terrainUniforms.macroNoiseScale =
  1027. m_terrainShader->uniformHandle("u_macroNoiseScale");
  1028. m_terrainUniforms.detailNoiseScale =
  1029. m_terrainShader->uniformHandle("u_detailNoiseScale");
  1030. m_terrainUniforms.slopeRockThreshold =
  1031. m_terrainShader->uniformHandle("u_slopeRockThreshold");
  1032. m_terrainUniforms.slopeRockSharpness =
  1033. m_terrainShader->uniformHandle("u_slopeRockSharpness");
  1034. m_terrainUniforms.soilBlendHeight =
  1035. m_terrainShader->uniformHandle("u_soilBlendHeight");
  1036. m_terrainUniforms.soilBlendSharpness =
  1037. m_terrainShader->uniformHandle("u_soilBlendSharpness");
  1038. m_terrainUniforms.heightNoiseStrength =
  1039. m_terrainShader->uniformHandle("u_heightNoiseStrength");
  1040. m_terrainUniforms.heightNoiseFrequency =
  1041. m_terrainShader->uniformHandle("u_heightNoiseFrequency");
  1042. m_terrainUniforms.ambientBoost =
  1043. m_terrainShader->uniformHandle("u_ambientBoost");
  1044. m_terrainUniforms.rockDetailStrength =
  1045. m_terrainShader->uniformHandle("u_rockDetailStrength");
  1046. m_terrainUniforms.lightDir = m_terrainShader->uniformHandle("u_lightDir");
  1047. }
  1048. void Backend::initializeGrassPipeline() {
  1049. initializeOpenGLFunctions();
  1050. shutdownGrassPipeline();
  1051. struct GrassVertex {
  1052. QVector3D position;
  1053. QVector2D uv;
  1054. };
  1055. const GrassVertex bladeVertices[6] = {
  1056. {{-0.5f, 0.0f, 0.0f}, {0.0f, 0.0f}},
  1057. {{0.5f, 0.0f, 0.0f}, {1.0f, 0.0f}},
  1058. {{-0.35f, 1.0f, 0.0f}, {0.1f, 1.0f}},
  1059. {{-0.35f, 1.0f, 0.0f}, {0.1f, 1.0f}},
  1060. {{0.5f, 0.0f, 0.0f}, {1.0f, 0.0f}},
  1061. {{0.35f, 1.0f, 0.0f}, {0.9f, 1.0f}},
  1062. };
  1063. glGenVertexArrays(1, &m_grassVao);
  1064. glBindVertexArray(m_grassVao);
  1065. glGenBuffers(1, &m_grassVertexBuffer);
  1066. glBindBuffer(GL_ARRAY_BUFFER, m_grassVertexBuffer);
  1067. glBufferData(GL_ARRAY_BUFFER, sizeof(bladeVertices), bladeVertices,
  1068. GL_STATIC_DRAW);
  1069. m_grassVertexCount = 6;
  1070. glEnableVertexAttribArray(0);
  1071. glVertexAttribPointer(
  1072. 0, 3, GL_FLOAT, GL_FALSE, sizeof(GrassVertex),
  1073. reinterpret_cast<void *>(offsetof(GrassVertex, position)));
  1074. glEnableVertexAttribArray(1);
  1075. glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(GrassVertex),
  1076. reinterpret_cast<void *>(offsetof(GrassVertex, uv)));
  1077. glEnableVertexAttribArray(2);
  1078. glVertexAttribDivisor(2, 1);
  1079. glEnableVertexAttribArray(3);
  1080. glVertexAttribDivisor(3, 1);
  1081. glEnableVertexAttribArray(4);
  1082. glVertexAttribDivisor(4, 1);
  1083. glBindVertexArray(0);
  1084. glBindBuffer(GL_ARRAY_BUFFER, 0);
  1085. }
  1086. void Backend::shutdownGrassPipeline() {
  1087. initializeOpenGLFunctions();
  1088. if (m_grassVertexBuffer) {
  1089. glDeleteBuffers(1, &m_grassVertexBuffer);
  1090. m_grassVertexBuffer = 0;
  1091. }
  1092. if (m_grassVao) {
  1093. glDeleteVertexArrays(1, &m_grassVao);
  1094. m_grassVao = 0;
  1095. }
  1096. m_grassVertexCount = 0;
  1097. }
  1098. void Backend::cacheStoneUniforms() {
  1099. if (m_stoneShader) {
  1100. m_stoneUniforms.viewProj = m_stoneShader->uniformHandle("uViewProj");
  1101. m_stoneUniforms.lightDirection =
  1102. m_stoneShader->uniformHandle("uLightDirection");
  1103. }
  1104. }
  1105. void Backend::initializeStonePipeline() {
  1106. initializeOpenGLFunctions();
  1107. shutdownStonePipeline();
  1108. struct StoneVertex {
  1109. QVector3D position;
  1110. QVector3D normal;
  1111. };
  1112. const StoneVertex stoneVertices[] = {
  1113. {{-0.5f, -0.5f, 0.5f}, {0.0f, 0.0f, 1.0f}},
  1114. {{0.5f, -0.5f, 0.5f}, {0.0f, 0.0f, 1.0f}},
  1115. {{0.5f, 0.5f, 0.5f}, {0.0f, 0.0f, 1.0f}},
  1116. {{-0.5f, 0.5f, 0.5f}, {0.0f, 0.0f, 1.0f}},
  1117. {{-0.5f, -0.5f, -0.5f}, {0.0f, 0.0f, -1.0f}},
  1118. {{-0.5f, 0.5f, -0.5f}, {0.0f, 0.0f, -1.0f}},
  1119. {{0.5f, 0.5f, -0.5f}, {0.0f, 0.0f, -1.0f}},
  1120. {{0.5f, -0.5f, -0.5f}, {0.0f, 0.0f, -1.0f}},
  1121. {{-0.5f, 0.5f, -0.5f}, {0.0f, 1.0f, 0.0f}},
  1122. {{-0.5f, 0.5f, 0.5f}, {0.0f, 1.0f, 0.0f}},
  1123. {{0.5f, 0.5f, 0.5f}, {0.0f, 1.0f, 0.0f}},
  1124. {{0.5f, 0.5f, -0.5f}, {0.0f, 1.0f, 0.0f}},
  1125. {{-0.5f, -0.5f, -0.5f}, {0.0f, -1.0f, 0.0f}},
  1126. {{0.5f, -0.5f, -0.5f}, {0.0f, -1.0f, 0.0f}},
  1127. {{0.5f, -0.5f, 0.5f}, {0.0f, -1.0f, 0.0f}},
  1128. {{-0.5f, -0.5f, 0.5f}, {0.0f, -1.0f, 0.0f}},
  1129. {{0.5f, -0.5f, -0.5f}, {1.0f, 0.0f, 0.0f}},
  1130. {{0.5f, 0.5f, -0.5f}, {1.0f, 0.0f, 0.0f}},
  1131. {{0.5f, 0.5f, 0.5f}, {1.0f, 0.0f, 0.0f}},
  1132. {{0.5f, -0.5f, 0.5f}, {1.0f, 0.0f, 0.0f}},
  1133. {{-0.5f, -0.5f, -0.5f}, {-1.0f, 0.0f, 0.0f}},
  1134. {{-0.5f, -0.5f, 0.5f}, {-1.0f, 0.0f, 0.0f}},
  1135. {{-0.5f, 0.5f, 0.5f}, {-1.0f, 0.0f, 0.0f}},
  1136. {{-0.5f, 0.5f, -0.5f}, {-1.0f, 0.0f, 0.0f}},
  1137. };
  1138. const uint16_t stoneIndices[] = {
  1139. 0, 1, 2, 2, 3, 0, 4, 5, 6, 6, 7, 4, 8, 9, 10, 10, 11, 8,
  1140. 12, 13, 14, 14, 15, 12, 16, 17, 18, 18, 19, 16, 20, 21, 22, 22, 23, 20};
  1141. glGenVertexArrays(1, &m_stoneVao);
  1142. glBindVertexArray(m_stoneVao);
  1143. glGenBuffers(1, &m_stoneVertexBuffer);
  1144. glBindBuffer(GL_ARRAY_BUFFER, m_stoneVertexBuffer);
  1145. glBufferData(GL_ARRAY_BUFFER, sizeof(stoneVertices), stoneVertices,
  1146. GL_STATIC_DRAW);
  1147. m_stoneVertexCount = 24;
  1148. glGenBuffers(1, &m_stoneIndexBuffer);
  1149. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_stoneIndexBuffer);
  1150. glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(stoneIndices), stoneIndices,
  1151. GL_STATIC_DRAW);
  1152. m_stoneIndexCount = 36;
  1153. glEnableVertexAttribArray(0);
  1154. glVertexAttribPointer(
  1155. 0, 3, GL_FLOAT, GL_FALSE, sizeof(StoneVertex),
  1156. reinterpret_cast<void *>(offsetof(StoneVertex, position)));
  1157. glEnableVertexAttribArray(1);
  1158. glVertexAttribPointer(
  1159. 1, 3, GL_FLOAT, GL_FALSE, sizeof(StoneVertex),
  1160. reinterpret_cast<void *>(offsetof(StoneVertex, normal)));
  1161. glEnableVertexAttribArray(2);
  1162. glVertexAttribDivisor(2, 1);
  1163. glEnableVertexAttribArray(3);
  1164. glVertexAttribDivisor(3, 1);
  1165. glBindVertexArray(0);
  1166. glBindBuffer(GL_ARRAY_BUFFER, 0);
  1167. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
  1168. }
  1169. void Backend::shutdownStonePipeline() {
  1170. initializeOpenGLFunctions();
  1171. if (m_stoneIndexBuffer) {
  1172. glDeleteBuffers(1, &m_stoneIndexBuffer);
  1173. m_stoneIndexBuffer = 0;
  1174. }
  1175. if (m_stoneVertexBuffer) {
  1176. glDeleteBuffers(1, &m_stoneVertexBuffer);
  1177. m_stoneVertexBuffer = 0;
  1178. }
  1179. if (m_stoneVao) {
  1180. glDeleteVertexArrays(1, &m_stoneVao);
  1181. m_stoneVao = 0;
  1182. }
  1183. m_stoneVertexCount = 0;
  1184. m_stoneIndexCount = 0;
  1185. }
  1186. void Backend::cachePlantUniforms() {
  1187. if (m_plantShader) {
  1188. m_plantUniforms.viewProj = m_plantShader->uniformHandle("uViewProj");
  1189. m_plantUniforms.time = m_plantShader->uniformHandle("uTime");
  1190. m_plantUniforms.windStrength =
  1191. m_plantShader->uniformHandle("uWindStrength");
  1192. m_plantUniforms.windSpeed = m_plantShader->uniformHandle("uWindSpeed");
  1193. m_plantUniforms.lightDirection =
  1194. m_plantShader->uniformHandle("uLightDirection");
  1195. }
  1196. }
  1197. void Backend::cachePineUniforms() {
  1198. if (m_pineShader) {
  1199. m_pineUniforms.viewProj = m_pineShader->uniformHandle("uViewProj");
  1200. m_pineUniforms.time = m_pineShader->uniformHandle("uTime");
  1201. m_pineUniforms.windStrength = m_pineShader->uniformHandle("uWindStrength");
  1202. m_pineUniforms.windSpeed = m_pineShader->uniformHandle("uWindSpeed");
  1203. m_pineUniforms.lightDirection =
  1204. m_pineShader->uniformHandle("uLightDirection");
  1205. }
  1206. }
  1207. void Backend::initializePlantPipeline() {
  1208. initializeOpenGLFunctions();
  1209. shutdownPlantPipeline();
  1210. struct PlantVertex {
  1211. QVector3D position;
  1212. QVector2D texCoord;
  1213. QVector3D normal;
  1214. };
  1215. const PlantVertex plantVertices[] = {
  1216. {{-0.5f, 0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f, 1.0f}},
  1217. {{0.5f, 0.0f, 0.0f}, {1.0f, 0.0f}, {0.0f, 0.0f, 1.0f}},
  1218. {{0.5f, 1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 0.0f, 1.0f}},
  1219. {{-0.5f, 1.0f, 0.0f}, {0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}},
  1220. {{0.5f, 0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f, -1.0f}},
  1221. {{-0.5f, 0.0f, 0.0f}, {1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}},
  1222. {{-0.5f, 1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 0.0f, -1.0f}},
  1223. {{0.5f, 1.0f, 0.0f}, {0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}},
  1224. {{0.0f, 0.0f, -0.5f}, {0.0f, 0.0f}, {1.0f, 0.0f, 0.0f}},
  1225. {{0.0f, 0.0f, 0.5f}, {1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}},
  1226. {{0.0f, 1.0f, 0.5f}, {1.0f, 1.0f}, {1.0f, 0.0f, 0.0f}},
  1227. {{0.0f, 1.0f, -0.5f}, {0.0f, 1.0f}, {1.0f, 0.0f, 0.0f}},
  1228. {{0.0f, 0.0f, 0.5f}, {0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}},
  1229. {{0.0f, 0.0f, -0.5f}, {1.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}},
  1230. {{0.0f, 1.0f, -0.5f}, {1.0f, 1.0f}, {-1.0f, 0.0f, 0.0f}},
  1231. {{0.0f, 1.0f, 0.5f}, {0.0f, 1.0f}, {-1.0f, 0.0f, 0.0f}},
  1232. };
  1233. const unsigned short plantIndices[] = {
  1234. 0, 1, 2, 0, 2, 3,
  1235. 4, 5, 6, 4, 6, 7,
  1236. 8, 9, 10, 8, 10, 11,
  1237. 12, 13, 14, 12, 14, 15,
  1238. };
  1239. glGenVertexArrays(1, &m_plantVao);
  1240. glBindVertexArray(m_plantVao);
  1241. glGenBuffers(1, &m_plantVertexBuffer);
  1242. glBindBuffer(GL_ARRAY_BUFFER, m_plantVertexBuffer);
  1243. glBufferData(GL_ARRAY_BUFFER, sizeof(plantVertices), plantVertices,
  1244. GL_STATIC_DRAW);
  1245. m_plantVertexCount = 16;
  1246. glEnableVertexAttribArray(0);
  1247. glVertexAttribPointer(
  1248. 0, 3, GL_FLOAT, GL_FALSE, sizeof(PlantVertex),
  1249. reinterpret_cast<void *>(offsetof(PlantVertex, position)));
  1250. glEnableVertexAttribArray(1);
  1251. glVertexAttribPointer(
  1252. 1, 2, GL_FLOAT, GL_FALSE, sizeof(PlantVertex),
  1253. reinterpret_cast<void *>(offsetof(PlantVertex, texCoord)));
  1254. glEnableVertexAttribArray(2);
  1255. glVertexAttribPointer(
  1256. 2, 3, GL_FLOAT, GL_FALSE, sizeof(PlantVertex),
  1257. reinterpret_cast<void *>(offsetof(PlantVertex, normal)));
  1258. glGenBuffers(1, &m_plantIndexBuffer);
  1259. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_plantIndexBuffer);
  1260. glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(plantIndices), plantIndices,
  1261. GL_STATIC_DRAW);
  1262. m_plantIndexCount = 24;
  1263. glEnableVertexAttribArray(3);
  1264. glVertexAttribDivisor(3, 1);
  1265. glEnableVertexAttribArray(4);
  1266. glVertexAttribDivisor(4, 1);
  1267. glEnableVertexAttribArray(5);
  1268. glVertexAttribDivisor(5, 1);
  1269. glBindVertexArray(0);
  1270. glBindBuffer(GL_ARRAY_BUFFER, 0);
  1271. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
  1272. }
  1273. void Backend::shutdownPlantPipeline() {
  1274. initializeOpenGLFunctions();
  1275. if (m_plantIndexBuffer) {
  1276. glDeleteBuffers(1, &m_plantIndexBuffer);
  1277. m_plantIndexBuffer = 0;
  1278. }
  1279. if (m_plantVertexBuffer) {
  1280. glDeleteBuffers(1, &m_plantVertexBuffer);
  1281. m_plantVertexBuffer = 0;
  1282. }
  1283. if (m_plantVao) {
  1284. glDeleteVertexArrays(1, &m_plantVao);
  1285. m_plantVao = 0;
  1286. }
  1287. m_plantVertexCount = 0;
  1288. m_plantIndexCount = 0;
  1289. }
  1290. void Backend::initializePinePipeline() {
  1291. initializeOpenGLFunctions();
  1292. shutdownPinePipeline();
  1293. struct PineVertex {
  1294. QVector3D position;
  1295. QVector2D texCoord;
  1296. QVector3D normal;
  1297. };
  1298. constexpr int kSegments = 6;
  1299. constexpr float kTwoPi = 6.28318530718f;
  1300. std::vector<PineVertex> vertices;
  1301. vertices.reserve(kSegments * 5 + 1);
  1302. std::vector<unsigned short> indices;
  1303. indices.reserve(kSegments * 6 * 4 + kSegments * 3);
  1304. auto addRing = [&](float radius, float y, float normalUp,
  1305. float vCoord) -> int {
  1306. const int start = static_cast<int>(vertices.size());
  1307. for (int i = 0; i < kSegments; ++i) {
  1308. const float t = static_cast<float>(i) / static_cast<float>(kSegments);
  1309. const float angle = t * kTwoPi;
  1310. const float nx = std::cos(angle);
  1311. const float nz = std::sin(angle);
  1312. QVector3D normal(nx, normalUp, nz);
  1313. normal.normalize();
  1314. QVector3D position(radius * nx, y, radius * nz);
  1315. QVector2D texCoord(t, vCoord);
  1316. vertices.push_back({position, texCoord, normal});
  1317. }
  1318. return start;
  1319. };
  1320. auto connectRings = [&](int lowerStart, int upperStart) {
  1321. for (int i = 0; i < kSegments; ++i) {
  1322. const int next = (i + 1) % kSegments;
  1323. const unsigned short lower0 = static_cast<unsigned short>(lowerStart + i);
  1324. const unsigned short lower1 =
  1325. static_cast<unsigned short>(lowerStart + next);
  1326. const unsigned short upper0 = static_cast<unsigned short>(upperStart + i);
  1327. const unsigned short upper1 =
  1328. static_cast<unsigned short>(upperStart + next);
  1329. indices.push_back(lower0);
  1330. indices.push_back(lower1);
  1331. indices.push_back(upper1);
  1332. indices.push_back(lower0);
  1333. indices.push_back(upper1);
  1334. indices.push_back(upper0);
  1335. }
  1336. };
  1337. const int trunkBottom = addRing(0.12f, 0.0f, 0.0f, 0.0f);
  1338. const int trunkMid = addRing(0.11f, 0.35f, 0.0f, 0.12f);
  1339. const int trunkTop = addRing(0.10f, 0.58f, 0.05f, 0.30f);
  1340. const int branchBase = addRing(0.60f, 0.64f, 0.35f, 0.46f);
  1341. const int branchMid = addRing(0.42f, 0.82f, 0.6f, 0.68f);
  1342. const int branchUpper = addRing(0.24f, 1.00f, 0.7f, 0.88f);
  1343. const int branchTip = addRing(0.12f, 1.10f, 0.85f, 0.96f);
  1344. connectRings(trunkBottom, trunkMid);
  1345. connectRings(trunkMid, trunkTop);
  1346. connectRings(trunkTop, branchBase);
  1347. connectRings(branchBase, branchMid);
  1348. connectRings(branchMid, branchUpper);
  1349. connectRings(branchUpper, branchTip);
  1350. const unsigned short trunkCapIndex =
  1351. static_cast<unsigned short>(vertices.size());
  1352. vertices.push_back({QVector3D(0.0f, 0.0f, 0.0f), QVector2D(0.5f, 0.0f),
  1353. QVector3D(0.0f, -1.0f, 0.0f)});
  1354. for (int i = 0; i < kSegments; ++i) {
  1355. const int next = (i + 1) % kSegments;
  1356. indices.push_back(static_cast<unsigned short>(trunkBottom + next));
  1357. indices.push_back(static_cast<unsigned short>(trunkBottom + i));
  1358. indices.push_back(trunkCapIndex);
  1359. }
  1360. const unsigned short apexIndex = static_cast<unsigned short>(vertices.size());
  1361. vertices.push_back({QVector3D(0.0f, 1.18f, 0.0f), QVector2D(0.5f, 1.0f),
  1362. QVector3D(0.0f, 1.0f, 0.0f)});
  1363. for (int i = 0; i < kSegments; ++i) {
  1364. const int next = (i + 1) % kSegments;
  1365. indices.push_back(static_cast<unsigned short>(branchTip + i));
  1366. indices.push_back(static_cast<unsigned short>(branchTip + next));
  1367. indices.push_back(apexIndex);
  1368. }
  1369. glGenVertexArrays(1, &m_pineVao);
  1370. glBindVertexArray(m_pineVao);
  1371. glGenBuffers(1, &m_pineVertexBuffer);
  1372. glBindBuffer(GL_ARRAY_BUFFER, m_pineVertexBuffer);
  1373. glBufferData(GL_ARRAY_BUFFER,
  1374. static_cast<GLsizeiptr>(vertices.size() * sizeof(PineVertex)),
  1375. vertices.data(), GL_STATIC_DRAW);
  1376. m_pineVertexCount = static_cast<GLsizei>(vertices.size());
  1377. glEnableVertexAttribArray(0);
  1378. glVertexAttribPointer(
  1379. 0, 3, GL_FLOAT, GL_FALSE, sizeof(PineVertex),
  1380. reinterpret_cast<void *>(offsetof(PineVertex, position)));
  1381. glEnableVertexAttribArray(1);
  1382. glVertexAttribPointer(
  1383. 1, 2, GL_FLOAT, GL_FALSE, sizeof(PineVertex),
  1384. reinterpret_cast<void *>(offsetof(PineVertex, texCoord)));
  1385. glEnableVertexAttribArray(2);
  1386. glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(PineVertex),
  1387. reinterpret_cast<void *>(offsetof(PineVertex, normal)));
  1388. glGenBuffers(1, &m_pineIndexBuffer);
  1389. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_pineIndexBuffer);
  1390. glBufferData(GL_ELEMENT_ARRAY_BUFFER,
  1391. static_cast<GLsizeiptr>(indices.size() * sizeof(unsigned short)),
  1392. indices.data(), GL_STATIC_DRAW);
  1393. m_pineIndexCount = static_cast<GLsizei>(indices.size());
  1394. glEnableVertexAttribArray(3);
  1395. glVertexAttribDivisor(3, 1);
  1396. glEnableVertexAttribArray(4);
  1397. glVertexAttribDivisor(4, 1);
  1398. glEnableVertexAttribArray(5);
  1399. glVertexAttribDivisor(5, 1);
  1400. glBindVertexArray(0);
  1401. glBindBuffer(GL_ARRAY_BUFFER, 0);
  1402. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
  1403. }
  1404. void Backend::shutdownPinePipeline() {
  1405. initializeOpenGLFunctions();
  1406. if (m_pineIndexBuffer) {
  1407. glDeleteBuffers(1, &m_pineIndexBuffer);
  1408. m_pineIndexBuffer = 0;
  1409. }
  1410. if (m_pineVertexBuffer) {
  1411. glDeleteBuffers(1, &m_pineVertexBuffer);
  1412. m_pineVertexBuffer = 0;
  1413. }
  1414. if (m_pineVao) {
  1415. glDeleteVertexArrays(1, &m_pineVao);
  1416. m_pineVao = 0;
  1417. }
  1418. m_pineVertexCount = 0;
  1419. m_pineIndexCount = 0;
  1420. }
  1421. } // namespace Render::GL