SceneNodes.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646
  1. //========================================================================
  2. // SceneNodes.cpp - defines the base class for the 3D graphics scene graph, and
  3. // derived classes like RootNode, Alpha scene nodes, Camera, Grids, etc.
  4. //
  5. // Part of the GameCode4 Application
  6. //
  7. // GameCode4 is the sample application that encapsulates much of the source code
  8. // discussed in "Game Coding Complete - 4th Edition" by Mike McShaffry and David
  9. // "Rez" Graham, published by Charles River Media.
  10. // ISBN-10: 1133776574 | ISBN-13: 978-1133776574
  11. //
  12. // If this source code has found it's way to you, and you think it has helped you
  13. // in any way, do the authors a favor and buy a new copy of the book - there are
  14. // detailed explanations in it that compliment this code well. Buy a copy at Amazon.com
  15. // by clicking here:
  16. // http://www.amazon.com/gp/product/1133776574/ref=olp_product_details?ie=UTF8&me=&seller=
  17. //
  18. // There's a companion web site at http://www.mcshaffry.com/GameCode/
  19. //
  20. // The source code is managed and maintained through Google Code:
  21. // http://code.google.com/p/gamecode4/
  22. //
  23. // (c) Copyright 2012 Michael L. McShaffry and David Graham
  24. //
  25. // This program is free software; you can redistribute it and/or
  26. // modify it under the terms of the GNU Lesser GPL v3
  27. // as published by the Free Software Foundation.
  28. //
  29. // This program is distributed in the hope that it will be useful,
  30. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  31. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
  32. // http://www.gnu.org/licenses/lgpl-3.0.txt for more details.
  33. //
  34. // You should have received a copy of the GNU Lesser GPL v3
  35. // along with this program; if not, write to the Free Software
  36. // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  37. //
  38. //========================================================================
  39. #include "../Unix/GameCodeStd.h"
  40. #include "../Actors/RenderComponent.h"
  41. #include "../Actors/TransformComponent.h"
  42. #include "SceneNodes.h"
  43. #include "Scene.h"
  44. #include <glm/gtx/string_cast.hpp>
  45. ////////////////////////////////////////////////////
  46. // SceneNodeProperties Implementation
  47. ////////////////////////////////////////////////////
  48. SceneNodeProperties::SceneNodeProperties(void)
  49. {
  50. m_ActorId = INVALID_ACTOR_ID;
  51. m_Radius = 0;
  52. m_RenderPass = RenderPass_0;
  53. m_AlphaType = AlphaOpaque;
  54. }
  55. //
  56. // SceneNodeProperties::Transform - Chapter 16, page 528
  57. //
  58. void SceneNodeProperties::Transform(glm::mat4 *toWorld, glm::mat4 *fromWorld) const
  59. {
  60. if (toWorld)
  61. *toWorld = m_ToWorld;
  62. if (fromWorld)
  63. *fromWorld = m_FromWorld;
  64. }
  65. ////////////////////////////////////////////////////
  66. // SceneNode Implementation
  67. ////////////////////////////////////////////////////
  68. SceneNode::SceneNode(
  69. ActorId actorId,
  70. WeakBaseRenderComponentPtr renderComponent,
  71. RenderPass renderPass,
  72. const glm::mat4 to,
  73. std::optional<const glm::mat4> from
  74. ) {
  75. m_pParent= NULL;
  76. m_Props.m_ActorId = actorId;
  77. m_Props.m_Name = (renderComponent) ? renderComponent->VGetName() : "SceneNode";
  78. m_Props.m_RenderPass = renderPass;
  79. m_Props.m_AlphaType = AlphaOpaque;
  80. m_RenderComponent = renderComponent;
  81. VSetTransform(to, from);
  82. SetRadius(0);
  83. // [mrmike] - these lines were moved to VOnRestore() post press
  84. //Color color = (renderComponent) ? renderComponent->GetColor() : g_White;
  85. //m_Props.m_Material.SetDiffuse(color);
  86. }
  87. SceneNode::~SceneNode()
  88. {
  89. }
  90. //
  91. // SceneNode::VOnRestore - Chapter 16, page 532
  92. //
  93. int SceneNode::VOnRestore(Scene *pScene)
  94. {
  95. Color color = (m_RenderComponent) ? m_RenderComponent->GetColor() : g_White;
  96. m_Props.m_Material.SetDiffuse(color);
  97. // This is meant to be called from any class
  98. // that inherits from SceneNode and overloads
  99. // VOnRestore()
  100. SceneNodeList::iterator i = m_Children.begin();
  101. SceneNodeList::iterator end = m_Children.end();
  102. while (i != end)
  103. {
  104. (*i)->VOnRestore(pScene);
  105. ++i;
  106. }
  107. return 0;
  108. }
  109. //
  110. // SceneNode::VSetTransform - Chapter 16, page 531
  111. //
  112. void SceneNode::VSetTransform(
  113. const glm::mat4 toWorld,
  114. std::optional<const glm::mat4> fromWorld
  115. ) {
  116. m_Props.m_ToWorld = toWorld;
  117. if (!fromWorld)
  118. {
  119. m_Props.m_FromWorld = glm::inverse(m_Props.m_ToWorld);
  120. }
  121. else
  122. {
  123. m_Props.m_FromWorld = *fromWorld;
  124. }
  125. }
  126. //
  127. // SceneNode::VPostRender - Chapter 16, page 532
  128. //
  129. int SceneNode::VPreRender(Scene *pScene)
  130. {
  131. StrongActorPtr pActor = MakeStrongPtr(g_pApp->GetGameLogic()->VGetActor(m_Props.m_ActorId));
  132. if (pActor)
  133. {
  134. std::shared_ptr<TransformComponent> pTc = MakeStrongPtr(pActor->GetComponent<TransformComponent>(TransformComponent::g_Name));
  135. if (pTc)
  136. {
  137. m_Props.m_ToWorld = pTc->GetTransform();
  138. }
  139. }
  140. pScene->PushAndSetMatrix(m_Props.m_ToWorld);
  141. return 0;
  142. }
  143. //
  144. // SceneNode::VIsVisible - Chapter 16, page 533
  145. //
  146. bool SceneNode::VIsVisible(Scene *pScene) const
  147. {
  148. // transform the location of this node into the camera space
  149. // of the camera attached to the scene
  150. // glm::mat4 toWorld, fromWorld;
  151. // pScene->GetCamera()->VGet()->Transform(&toWorld, &fromWorld);
  152. // glm::vec3 pos = GetWorldPosition();
  153. // glm::vec3 fromWorldPos = fromWorld.Xform(pos);
  154. // Frustum const &frustum = pScene->GetCamera()->GetFrustum();
  155. // bool isVisible = frustum.Inside(fromWorldPos, VGet()->Radius());
  156. // return isVisible;
  157. return true;
  158. }
  159. //
  160. // SceneNode::VPostRender - Chapter 16, page 532
  161. //
  162. int SceneNode::VPostRender(Scene *pScene)
  163. {
  164. pScene->PopMatrix();
  165. return 0;
  166. }
  167. //
  168. // SceneNode::VOnUpdate - Chapter 16, page 532
  169. //
  170. int SceneNode::VOnUpdate(Scene *pScene, uint64_t const elapsedMs)
  171. {
  172. // This is meant to be called from any class
  173. // that inherits from SceneNode and overloads
  174. // VOnUpdate()
  175. SceneNodeList::iterator i = m_Children.begin();
  176. SceneNodeList::iterator end = m_Children.end();
  177. while (i != end)
  178. {
  179. (*i)->VOnUpdate(pScene, elapsedMs);
  180. ++i;
  181. }
  182. return 0;
  183. }
  184. //
  185. // SceneNode::VRenderChildren - Chapter 16, page 533
  186. //
  187. int SceneNode::VRenderChildren(Scene *pScene)
  188. {
  189. // Iterate through the children
  190. SceneNodeList::iterator i = m_Children.begin();
  191. SceneNodeList::iterator end = m_Children.end();
  192. while (i != end)
  193. {
  194. if ((*i)->VPreRender(pScene) == 0)
  195. {
  196. // You could short-circuit rendering
  197. // if an object returns E_FAIL from
  198. // VPreRender()
  199. // Don't render this node if you can't see it
  200. if ((*i)->VIsVisible(pScene))
  201. {
  202. float alpha = (*i)->VGet()->m_Material.GetAlpha();
  203. if (alpha==fOPAQUE)
  204. {
  205. (*i)->VRender(pScene);
  206. }
  207. // else if (alpha!=fTRANSPARENT)
  208. // {
  209. // // The object isn't totally transparent
  210. // AlphaSceneNode *asn = GCC_NEW AlphaSceneNode;
  211. // }
  212. (*i)->VRenderChildren(pScene);
  213. }
  214. // [mrmike] post-press fix - if the parent is not visible, the childrend
  215. // shouldn't be visible either.
  216. // (*i)->VRenderChildren(pScene);
  217. }
  218. (*i)->VPostRender(pScene);
  219. ++i;
  220. }
  221. return 0;
  222. }
  223. //
  224. // SceneNode::VAddChild - Chapter 16, page 535
  225. //
  226. bool SceneNode::VAddChild(std::shared_ptr<ISceneNode> ikid)
  227. {
  228. m_Children.push_back(ikid);
  229. std::shared_ptr<SceneNode> kid = static_pointer_cast<SceneNode>(ikid);
  230. kid->m_pParent = this; // [mrmike] Post-press fix - the parent was never set!
  231. // The radius of the sphere should be fixed right here
  232. glm::vec3 kidPos = geometry::GetPosition(kid->VGet()->ToWorld());
  233. // [mrmike] - Post-press fix. This was not correct! subtracting the parents's position from the kidPos
  234. // created a HUGE radius, depending on the location of the parent, which could be anywhere
  235. // in the game world.
  236. //Vec3 dir = kidPos - m_Props.ToWorld().GetPosition();
  237. //float newRadius = dir.Length() + kid->VGet()->Radius();
  238. float newRadius = glm::length(kidPos) + kid->VGet()->Radius();
  239. if (newRadius > m_Props.m_Radius)
  240. m_Props.m_Radius = newRadius;
  241. return true;
  242. }
  243. //
  244. // SceneNode::VRemoveChild - not in the book
  245. //
  246. // If an actor is destroyed it should be removed from the scene graph.
  247. // Generally the HumanView will recieve a message saying the actor has been
  248. // destroyed, and it will then call Scene::RemoveChild which will traverse
  249. // the scene graph to find the child that needs removing.
  250. //
  251. bool SceneNode::VRemoveChild(ActorId id)
  252. {
  253. for(SceneNodeList::iterator i=m_Children.begin(); i!=m_Children.end(); ++i)
  254. {
  255. const SceneNodeProperties* pProps = (*i)->VGet();
  256. if(pProps->GetActorId() != INVALID_ACTOR_ID && id == pProps->GetActorId())
  257. {
  258. i = m_Children.erase(i); //this can be expensive for vectors
  259. return true;
  260. }
  261. }
  262. return false;
  263. }
  264. ////////////////////////////////////////////////////
  265. // RootNode Implementation
  266. ////////////////////////////////////////////////////
  267. //
  268. // RootNode::RootNode - Chapter 16, page 545
  269. //
  270. RootNode::RootNode()
  271. : SceneNode(INVALID_ACTOR_ID, WeakBaseRenderComponentPtr(), RenderPass_0, glm::mat4(1.0f))
  272. {
  273. m_Children.reserve(RenderPass_Last);
  274. std::shared_ptr<SceneNode> staticGroup(GCC_NEW SceneNode(INVALID_ACTOR_ID, WeakBaseRenderComponentPtr(), RenderPass_Static, glm::mat4(1.0f)));
  275. m_Children.push_back(staticGroup); // RenderPass_Static = 0
  276. std::shared_ptr<SceneNode> actorGroup(GCC_NEW SceneNode(INVALID_ACTOR_ID, WeakBaseRenderComponentPtr(), RenderPass_Actor, glm::mat4(1.0f)));
  277. m_Children.push_back(actorGroup); // RenderPass_Actor = 1
  278. std::shared_ptr<SceneNode> skyGroup(GCC_NEW SceneNode(INVALID_ACTOR_ID, WeakBaseRenderComponentPtr(), RenderPass_Sky, glm::mat4(1.0f)));
  279. m_Children.push_back(skyGroup); // RenderPass_Sky = 2
  280. std::shared_ptr<SceneNode> invisibleGroup(GCC_NEW SceneNode(INVALID_ACTOR_ID, WeakBaseRenderComponentPtr(), RenderPass_NotRendered, glm::mat4(1.0f)));
  281. m_Children.push_back(invisibleGroup); // RenderPass_NotRendered = 3
  282. }
  283. //
  284. // RootNode::VAddChild - Chapter 16, page 546
  285. //
  286. bool RootNode::VAddChild(std::shared_ptr<ISceneNode> kid)
  287. {
  288. // The Root node has children that divide the scene graph into render passes.
  289. // Scene nodes will get added to these children based on the value of the
  290. // render pass member variable.
  291. RenderPass pass = kid->VGet()->GetRenderPass();
  292. if ((unsigned)pass >= m_Children.size() || !m_Children[pass])
  293. {
  294. GCC_ASSERT(0 && "There is no such render pass");
  295. return false;
  296. }
  297. return m_Children[pass]->VAddChild(kid);
  298. }
  299. //
  300. // RootNode::VRemoveChild - not described in the book
  301. //
  302. // Returns false if nothing was removed
  303. //
  304. bool RootNode::VRemoveChild(ActorId id)
  305. {
  306. bool anythingRemoved = false;
  307. for(int i=RenderPass_0; i<RenderPass_Last; ++i)
  308. {
  309. if(m_Children[i]->VRemoveChild(id))
  310. {
  311. anythingRemoved = true;
  312. }
  313. }
  314. return anythingRemoved;
  315. }
  316. //
  317. // RootNode::VRenderChildren - Chapter 16, page 547
  318. //
  319. int RootNode::VRenderChildren(Scene *pScene)
  320. {
  321. // This code creates fine control of the render passes.
  322. for (int pass = RenderPass_0; pass < RenderPass_Last; ++pass)
  323. {
  324. switch(pass)
  325. {
  326. case RenderPass_Static:
  327. case RenderPass_Actor:
  328. m_Children[pass]->VRenderChildren(pScene);
  329. break;
  330. case RenderPass_Sky:
  331. {
  332. std::shared_ptr<IRenderState> skyPass = pScene->GetRenderer()->VPrepareSkyBoxPass();
  333. m_Children[pass]->VRenderChildren(pScene);
  334. break;
  335. }
  336. }
  337. }
  338. return 0;
  339. }
  340. ////////////////////////////////////////////////////
  341. // CameraNode Implementation
  342. ////////////////////////////////////////////////////
  343. //
  344. // CameraNode::VRender - Chapter 16, page 550
  345. //
  346. int CameraNode::VRender(Scene *pScene)
  347. {
  348. if (m_DebugCamera)
  349. {
  350. // m_Frustum.Render();
  351. }
  352. return 1;
  353. }
  354. //
  355. // CameraNode::VOnRestore - Chapter 16, page 550
  356. //
  357. int CameraNode::VOnRestore(Scene *pScene)
  358. {
  359. Point p = g_pApp->GetScreenSize();
  360. m_Frustum.SetAspect((float) p.x / (float) p.y);
  361. m_Projection = glm::perspective(
  362. m_Frustum.m_Fov,
  363. m_Frustum.m_Aspect,
  364. m_Frustum.m_Near,
  365. m_Frustum.m_Far
  366. );
  367. // [munnellg] this isn't necessary, but we'll do it to
  368. // preserve book code
  369. pScene->GetRenderer()->VSetProjectionTransform(m_Projection);
  370. return 0;
  371. }
  372. //
  373. // CameraNode::SetView - Chapter 16, page 550
  374. //
  375. // Note: this is incorrectly called CameraNode::SetView in the book
  376. //
  377. int CameraNode::SetViewTransform(Scene *pScene)
  378. {
  379. // TODO(munnellg) - implement
  380. // If there is a target, make sure the camera is
  381. // rigidly attached right behind the target
  382. if(m_pTarget)
  383. {
  384. glm::mat4 mat = m_pTarget->VGet()->ToWorld();
  385. glm::vec4 at = m_CamOffsetVector;
  386. glm::vec4 atWorld = mat * at;
  387. glm::vec3 pos = geometry::GetPosition(mat) + glm::vec3(atWorld);
  388. geometry::SetPosition(mat, pos);
  389. VSetTransform(mat);
  390. }
  391. m_View = VGet()->FromWorld();
  392. // [munnellg] this isn't necessary, but we'll do it to
  393. // preserve book code
  394. pScene->GetRenderer()->VSetViewTransform(m_View);
  395. return 0;
  396. }
  397. //
  398. // CameraNode::GetWorldViewProjection - not described in the book
  399. //
  400. // Returns the concatenation of the world and view projection, which is generally sent into vertex shaders
  401. //
  402. glm::mat4 CameraNode::GetWorldViewProjection(Scene *pScene)
  403. {
  404. glm::mat4 world = pScene->GetTopMatrix();
  405. glm::mat4 view = VGet()->FromWorld();
  406. return m_Projection * view * world;
  407. }
  408. ////////////////////////////////////////////////////
  409. // D3DGrid9 Implementation
  410. //
  411. // D3D9 classes are not covered in the 4th edition. They are included here for those
  412. // people that don't have D3D11 compatible video cards.
  413. //
  414. // The code is somewhat similar to the D3DGrid11 class, which IS discussed in Chapter 16
  415. // of the 4th edition.
  416. //
  417. ////////////////////////////////////////////////////
  418. OpenGLGrid::OpenGLGrid(ActorId actorId, WeakBaseRenderComponentPtr renderComponent, const glm::mat4 pMatrix)
  419. : SceneNode(actorId, renderComponent, RenderPass_0, pMatrix)
  420. {
  421. m_bTextureHasAlpha = false;
  422. m_numIndices = 0;
  423. m_vbo = 0;
  424. m_vao = 0;
  425. m_ebo = 0;
  426. }
  427. OpenGLGrid::~OpenGLGrid()
  428. {
  429. glDeleteVertexArrays(1, &m_vao);
  430. glDeleteBuffers(1, &m_vbo);
  431. glDeleteBuffers(1, &m_ebo);
  432. }
  433. int OpenGLGrid::VOnRestore(Scene *pScene)
  434. {
  435. // clear out any existing buffers
  436. glDeleteVertexArrays(1, &m_vao);
  437. glDeleteBuffers(1, &m_vbo);
  438. glDeleteBuffers(1, &m_ebo);
  439. // TODO(munnellg) - these VOnRestore calls need to have their results checked
  440. SceneNode::VOnRestore(pScene);
  441. // TODO(munnellg) - release shaders if allocating before creating shader so we don't leak memory
  442. m_ShaderProgram.OnRestore(pScene);
  443. GridRenderComponent* grc = static_cast<GridRenderComponent*>(m_RenderComponent);
  444. int squares = grc->GetDivision();
  445. SetRadius(sqrt(squares * squares / 2.0f) );
  446. // Create the vertex buffer - we'll need enough verts
  447. // to populate the grid. If we want a 2x2 grid, we'll
  448. // need 3x3 set of verts.
  449. m_numVerts = (squares+1)*(squares+1); // Create vertex buffer
  450. // Fill the vertex buffer. We are setting the tu and tv texture
  451. // coordinates, which range from 0.0 to 1.0
  452. VertexUnlitTextured *pVerts = GCC_NEW VertexUnlitTextured[m_numVerts];
  453. GCC_ASSERT(pVerts && "Out of memory in OpenGLGrid::VOnRestore");
  454. if (!pVerts)
  455. return 1;
  456. for( int j=0; j<(squares+1); j++ )
  457. {
  458. for (int i=0; i<(squares+1); i++)
  459. {
  460. // Which vertex are we setting?
  461. int index = i + (j * (squares+1) );
  462. VertexUnlitTextured *vert = &pVerts[index];
  463. // Default position of the grid is centered on the origin flat on
  464. // the XZ plane
  465. float x = (float)i - (squares/2.0f);
  466. float y = (float)j - (squares/2.0f);
  467. vert->Pos = glm::vec3(x,0.f,y);
  468. vert->Normal = glm::vec3(0.0f, 1.0f, 0.0f);
  469. // The texture coordinates are set to x,y to make the
  470. // texture tile along with units - 1.0, 2.0, 3.0, etc
  471. vert->Uv.x = x;
  472. vert->Uv.y = y;
  473. }
  474. }
  475. // The number of indicies equals the number of polygons times 3
  476. // since there are 3 indicies per polygon. Each grid square contains
  477. // two polygons. The indicies are 16 bit, since our grids won't
  478. // be that big!
  479. m_numPolys = squares * squares * 2;
  480. m_numIndices = m_numPolys * 3;
  481. GLuint *pIndices = GCC_NEW GLuint[m_numIndices];
  482. GCC_ASSERT(pIndices && "Out of memory in OpenGLGrid::VOnRestore");
  483. if (!pIndices)
  484. {
  485. delete[] pVerts;
  486. return 1;
  487. }
  488. // Loop through the grid squares and calc the values
  489. // of each index. Each grid square has two triangles:
  490. //
  491. // A - B
  492. // | / |
  493. // C - D
  494. GLuint *current = pIndices;
  495. for( int j=0; j<squares; j++ )
  496. {
  497. for (int i=0; i<squares; i++)
  498. {
  499. // Triangle #1 ACB
  500. *(current) = GLuint(i + (j*(squares+1)));
  501. *(current+1) = GLuint(i + ((j+1)*(squares+1)));
  502. *(current+2) = GLuint((i+1) + (j*(squares+1)));
  503. *(current+3) = GLuint((i+1) + (j*(squares+1)));
  504. *(current+4) = GLuint(i + ((j+1)*(squares+1)));
  505. *(current+5) = GLuint((i+1) + ((j+1)*(squares+1)));
  506. current += 6;
  507. }
  508. }
  509. glCreateVertexArrays(1, &m_vao);
  510. glCreateBuffers(1, &m_vbo);
  511. glNamedBufferStorage(m_vbo, sizeof(VertexUnlitTextured) * m_numVerts, pVerts, 0);
  512. glVertexArrayVertexBuffer(m_vao, 0, m_vbo, 0, sizeof(VertexUnlitTextured));
  513. glEnableVertexArrayAttrib(m_vao, 0);
  514. glVertexArrayAttribFormat(m_vao, 0, 3, GL_FLOAT, GL_FALSE, 0);
  515. glVertexArrayAttribBinding(m_vao, 0, 0);
  516. glEnableVertexArrayAttrib(m_vao, 1);
  517. glVertexArrayAttribFormat(m_vao, 1, 3, GL_FLOAT, GL_FALSE, offsetof(VertexUnlitTextured, Normal));
  518. glVertexArrayAttribBinding(m_vao, 1, 0);
  519. glEnableVertexArrayAttrib(m_vao, 2);
  520. glVertexArrayAttribFormat(m_vao, 2, 2, GL_FLOAT, GL_FALSE, offsetof(VertexUnlitTextured, Uv));
  521. glVertexArrayAttribBinding(m_vao, 2, 0);
  522. delete[] pVerts;
  523. glCreateBuffers(1, &m_ebo);
  524. glNamedBufferStorage(m_ebo, sizeof(GLuint) * m_numIndices, pIndices, 0);
  525. glVertexArrayElementBuffer(m_vao, m_ebo);
  526. delete[] pIndices;
  527. return 0;
  528. }
  529. int OpenGLGrid::VRender(Scene *pScene)
  530. {
  531. GridRenderComponent* grc = static_cast<GridRenderComponent*>(m_RenderComponent);
  532. m_ShaderProgram.SetTexture(grc->GetTextureResource());
  533. m_ShaderProgram.SetupRender(pScene, this);
  534. glBindVertexArray(m_vao);
  535. glDrawElements(GL_TRIANGLES, m_numIndices, GL_UNSIGNED_INT, 0);
  536. glBindVertexArray(0);
  537. return 0;
  538. }