Guest User

Batching

a guest
Dec 31st, 2014
233
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 12.53 KB | None | 0 0
  1. // Batcher.h
  2. #pragma once
  3.  
  4. #include "glew.h"
  5.  
  6. #include "Shader.h"
  7. #include "VertexArray.h"
  8.  
  9. /*
  10. Stores basic information about an batch.
  11. */
  12. struct SBatchItem
  13. {
  14.     // Stores the draw primitive to use.
  15.     GLenum m_Primitive;
  16.  
  17.     /*
  18.     Every child struct should implement it's own compartion method,
  19.     as this defines if a new item fits an existing batch or if it
  20.     needs a new one.
  21.     */
  22.     bool operator ==(SBatchItem other)
  23.     {
  24.         return m_Primitive == other.m_Primitive;
  25.     }
  26. };
  27.  
  28. /*
  29. Base class for batcher classes that batch a bunch
  30. of draw calls to one or more draw calls.
  31. */
  32. template<typename T> class CBatcher
  33. {
  34. public:
  35.     CBatcher();
  36.     ~CBatcher();
  37.  
  38.     // Prepares the batcher for batching.
  39.     void BeginBatch();
  40.     // Ends the batching process. This will automatically call RenderBatch() on all batches.
  41.     void EndBatch();
  42.  
  43.     // Renders the batch with the given key (batch set description).
  44.     void RenderBatch(T batchKey);
  45. protected:
  46.     // Called before rendering happens, allows shader manipulation etc.
  47.     virtual void PreRender(CVertexArray* vertexArray, T batchSet);
  48.     // Called after rendering happens, allows unbinding data etc.
  49.     virtual void PostRender(CVertexArray* vertexArray, T batchSet);
  50.  
  51.     // Adds an item to the batch.
  52.     virtual T AddBatchItem(CVertex* vertices[], size_t vertexCount, T batchItemDescription, bool connectorVertices = true, bool disableBatch = false);
  53. private:
  54.     // Creates a new pair to m_BatchData with the vertices given.
  55.     void CreateNewBatchSet(CVertex* vertices[], size_t vertexCount, T batchItemDescription);
  56.  
  57.     // Stores the batch data.
  58.     std::map<T, CVertexArray*> m_BatchData;
  59. };
  60.  
  61. #include "BatcherDef.h"
  62. // BatcherDef.h
  63.  
  64. template<typename T> CBatcher<T>::CBatcher()
  65. {
  66. }
  67.  
  68. template<typename T> CBatcher<T>::~CBatcher()
  69. {
  70.     for (auto pair : m_BatchData)
  71.     {
  72.         // TODO: This doesn't work on non-pointers either.
  73.         delete pair.first;
  74.         delete pair.second;
  75.     }
  76.     m_BatchData.clear();
  77. }
  78.  
  79. /*
  80. Prepares the batch for batching.
  81. */
  82. template<typename T> void CBatcher<T>::BeginBatch()
  83. {
  84. }
  85.  
  86. /*
  87. Ends the batching process. This will actually render the batch data.
  88. */
  89. template<typename T> void CBatcher<T>::EndBatch()
  90. {
  91.     // Loops over the different batches.
  92.     for (auto batchItem : m_BatchData)
  93.     {
  94.         RenderBatch(batchItem.first);
  95.     }
  96. }
  97.  
  98. /*
  99. Renders the batch with the given key.
  100. */
  101. template<typename T> void CBatcher<T>::RenderBatch(T batchKey)
  102. {
  103.     CVertexArray* batchArray = m_BatchData[batchKey];
  104.     if (batchArray->GetVertexData().size() == 0) return;
  105.     // Updates the batch data; passes the vertex data to GPU.
  106.     batchArray->UpdateVertexData();
  107.  
  108.     // Prepares the rendering.
  109.     PreRender(batchArray, batchKey);
  110.  
  111.     // Renders the vertex array.
  112.     batchArray->BindVertexArray();
  113.     batchArray->DrawVertexArray(batchKey->m_Primitive);
  114.     batchArray->UnBindVertexArray();
  115.  
  116.     // Finishes the rendering.
  117.     PostRender(batchArray, batchKey);
  118.  
  119.     // Clears the vertex array.
  120.     batchArray->ClearVertexArray();
  121. }
  122.  
  123. /*
  124. Called before rendering happens, allows shader manipulation etc.
  125. */
  126. template<typename T> void CBatcher<T>::PreRender(CVertexArray* vertexArray, T batchSet)
  127. {
  128. }
  129.  
  130. /*
  131. Called after rendering happens, allows unbinding data etc.
  132. */
  133. template<typename T> void CBatcher<T>::PostRender(CVertexArray* vertexArray, T batchSet)
  134. {
  135. }
  136.  
  137. /*
  138. Adds an item to the batch.
  139. */
  140. template<typename T> T CBatcher<T>::AddBatchItem(CVertex* vertices[], size_t vertexCount, T batchItemDescription, bool connectorVertices, bool disableBatch)
  141. {
  142.     // Checks if there is nothing in the batch, and it needs a new batch data set.
  143.     if (m_BatchData.size() == 0 || disableBatch)
  144.     {
  145.         CreateNewBatchSet(vertices, vertexCount, batchItemDescription);
  146.     }
  147.     // There is already batch sets available, check if they meet the requirements.
  148.     else
  149.     {
  150.         bool batchFound = false;
  151.  
  152.         // Checks if there is a batch that matches the data.
  153.         for (auto item : m_BatchData)
  154.         {
  155.             // TODO: Doesn't work on non-pointer data. Doesn't probably need though.
  156.             if (*item.first == *batchItemDescription)
  157.             {
  158.                 batchFound = true;
  159.  
  160.                 // Gets the vertex array of the set.
  161.                 CVertexArray* batchArray = item.second;
  162.  
  163.                 // Adds connector vertices between the batch items.
  164.                 std::vector<CVertex*>& vertexData = batchArray->GetVertexData();
  165.                 if (vertexData.size() > 0 && connectorVertices)
  166.                 {
  167.                     batchArray->AddVertex(new CVertex(vertexData[vertexData.size() - 1]));
  168.                     batchArray->AddVertex(new CVertex(vertices[0]));
  169.                 }
  170.  
  171.                 // Adds the vertices to the batch array.
  172.                 for (unsigned int i = 0; i < vertexCount; i++)
  173.                 {
  174.                     batchArray->AddVertex(vertices[i]);
  175.                 }
  176.  
  177.                 delete batchItemDescription;
  178.                 batchItemDescription = item.first;
  179.  
  180.                 break;
  181.             }
  182.         }
  183.  
  184.         // A batch wasn't found, a new one needs to be created.
  185.         if (!batchFound)
  186.         {
  187.             CreateNewBatchSet(vertices, vertexCount, batchItemDescription);
  188.         }
  189.     }
  190.  
  191.     return batchItemDescription;
  192. }
  193.  
  194. /*
  195. Creates a new pair to m_BatchData with the vertices given.
  196. */
  197. template<typename T> void CBatcher<T>::CreateNewBatchSet(CVertex* vertices[], size_t vertexCount, T batchItemDescription)
  198. {
  199.     // Creates a new vertex array.
  200.     CVertexArray* batchArray = new CVertexArray();
  201.     // Passes the vertices to the vertex array.
  202.     for (unsigned int i = 0; i < vertexCount; i++)
  203.     {
  204.         batchArray->AddVertex(vertices[i]);
  205.     }
  206.  
  207.     // Adds the set to the batch data.
  208.     m_BatchData[batchItemDescription] = batchArray;
  209. }
  210. // cpp files, a hack like this is needed. This file is then included
  211. // in Batcher.h to move the definitions in that file.
  212.  
  213. template<typename T> CBatcher<T>::CBatcher()
  214. {
  215. }
  216.  
  217. template<typename T> CBatcher<T>::~CBatcher()
  218. {
  219.     for (auto pair : m_BatchData)
  220.     {
  221.         // TODO: This doesn't work on non-pointers either.
  222.         delete pair.first;
  223.         delete pair.second;
  224.     }
  225.     m_BatchData.clear();
  226. }
  227.  
  228. /*
  229. Prepares the batch for batching.
  230. */
  231. template<typename T> void CBatcher<T>::BeginBatch()
  232. {
  233. }
  234.  
  235. /*
  236. Ends the batching process. This will actually render the batch data.
  237. */
  238. template<typename T> void CBatcher<T>::EndBatch()
  239. {
  240.     // Loops over the different batches.
  241.     for (auto batchItem : m_BatchData)
  242.     {
  243.         RenderBatch(batchItem.first);
  244.     }
  245. }
  246.  
  247. /*
  248. Renders the batch with the given key.
  249. */
  250. template<typename T> void CBatcher<T>::RenderBatch(T batchKey)
  251. {
  252.     CVertexArray* batchArray = m_BatchData[batchKey];
  253.     if (batchArray->GetVertexData().size() == 0) return;
  254.     // Updates the batch data; passes the vertex data to GPU.
  255.     batchArray->UpdateVertexData();
  256.  
  257.     // Prepares the rendering.
  258.     PreRender(batchArray, batchKey);
  259.  
  260.     // Renders the vertex array.
  261.     batchArray->BindVertexArray();
  262.     batchArray->DrawVertexArray(batchKey->m_Primitive);
  263.     batchArray->UnBindVertexArray();
  264.  
  265.     // Finishes the rendering.
  266.     PostRender(batchArray, batchKey);
  267.  
  268.     // Clears the vertex array.
  269.     batchArray->ClearVertexArray();
  270. }
  271.  
  272. /*
  273. Called before rendering happens, allows shader manipulation etc.
  274. */
  275. template<typename T> void CBatcher<T>::PreRender(CVertexArray* vertexArray, T batchSet)
  276. {
  277. }
  278.  
  279. /*
  280. Called after rendering happens, allows unbinding data etc.
  281. */
  282. template<typename T> void CBatcher<T>::PostRender(CVertexArray* vertexArray, T batchSet)
  283. {
  284. }
  285.  
  286. /*
  287. Adds an item to the batch.
  288. */
  289. template<typename T> T CBatcher<T>::AddBatchItem(CVertex* vertices[], size_t vertexCount, T batchItemDescription, bool connectorVertices, bool disableBatch)
  290. {
  291.     // Checks if there is nothing in the batch, and it needs a new batch data set.
  292.     if (m_BatchData.size() == 0 || disableBatch)
  293.     {
  294.         CreateNewBatchSet(vertices, vertexCount, batchItemDescription);
  295.     }
  296.     // There is already batch sets available, check if they meet the requirements.
  297.     else
  298.     {
  299.         bool batchFound = false;
  300.  
  301.         // Checks if there is a batch that matches the data.
  302.         for (auto item : m_BatchData)
  303.         {
  304.             // TODO: Doesn't work on non-pointer data. Doesn't probably need though.
  305.             if (*item.first == *batchItemDescription)
  306.             {
  307.                 batchFound = true;
  308.  
  309.                 // Gets the vertex array of the set.
  310.                 CVertexArray* batchArray = item.second;
  311.  
  312.                 // Adds connector vertices between the batch items.
  313.                 std::vector<CVertex*>& vertexData = batchArray->GetVertexData();
  314.                 if (vertexData.size() > 0 && connectorVertices)
  315.                 {
  316.                     batchArray->AddVertex(new CVertex(vertexData[vertexData.size() - 1]));
  317.                     batchArray->AddVertex(new CVertex(vertices[0]));
  318.                 }
  319.  
  320.                 // Adds the vertices to the batch array.
  321.                 for (unsigned int i = 0; i < vertexCount; i++)
  322.                 {
  323.                     batchArray->AddVertex(vertices[i]);
  324.                 }
  325.  
  326.                 delete batchItemDescription;
  327.                 batchItemDescription = item.first;
  328.  
  329.                 break;
  330.             }
  331.         }
  332.  
  333.         // A batch wasn't found, a new one needs to be created.
  334.         if (!batchFound)
  335.         {
  336.             CreateNewBatchSet(vertices, vertexCount, batchItemDescription);
  337.         }
  338.     }
  339.  
  340.     return batchItemDescription;
  341. }
  342.  
  343. /*
  344. Creates a new pair to m_BatchData with the vertices given.
  345. */
  346. template<typename T> void CBatcher<T>::CreateNewBatchSet(CVertex* vertices[], size_t vertexCount, T batchItemDescription)
  347. {
  348.     // Creates a new vertex array.
  349.     CVertexArray* batchArray = new CVertexArray();
  350.     // Passes the vertices to the vertex array.
  351.     for (unsigned int i = 0; i < vertexCount; i++)
  352.     {
  353.         batchArray->AddVertex(vertices[i]);
  354.     }
  355.  
  356.     // Adds the set to the batch data.
  357.     m_BatchData[batchItemDescription] = batchArray;
  358. }
  359.  
  360. // SpriteBatcher.h
  361. #pragma once
  362.  
  363. #include "glew.h"
  364.  
  365. #include "Batcher.h"
  366. #include "Color.h"
  367. #include "Vector2.h"
  368. #include "Shader.h"
  369. #include "Vertex.h"
  370. #include "VertexArray.h"
  371.  
  372. #include <vector>
  373.  
  374. /*
  375. Stores information about the batched sprites, used for
  376. determing if a sprite fits into an existing batch or
  377. if it needs a new one.
  378. */
  379. struct SBatchItemSprite : public SBatchItem
  380. {
  381.     // Stores the main texture of the sprite.
  382.     CTexture* m_SpriteTexture;
  383.     // Stores the normal map of the sprite.
  384.     CTexture* m_NormalTexture;
  385.  
  386.     /*
  387.     Implements equals checking.
  388.     */
  389.     bool operator==(SBatchItemSprite other)
  390.     {
  391.         return other.m_SpriteTexture == m_SpriteTexture && other.m_NormalTexture == m_NormalTexture && other.m_Primitive == m_Primitive;
  392.     }
  393. };
  394.  
  395. /*
  396. Batching for sprites that can be rendered in one (or more depending on
  397. the texture usage) render call.
  398. */
  399. class CSpriteBatcher : public CBatcher<SBatchItemSprite*>
  400. {
  401. public:
  402.     CSpriteBatcher();
  403.     ~CSpriteBatcher();
  404.  
  405.     // Adds a sprite to the batch.
  406.     SBatchItemSprite* RenderSprite(CVertex* vertices[], size_t vertexCount, GLenum mode, CTexture* spriteTexture, CTexture* normalTexture);
  407. protected:
  408.     // Called before rendering happens, allows shader manipulation etc.
  409.     void PreRender(CVertexArray* vertexArray, SBatchItemSprite* batchSet);
  410.     // Called after rendering happens, allows unbinding data etc.
  411.     void PostRender(CVertexArray* vertexArray, SBatchItemSprite* batchSet);
  412. private:
  413.     // Stores the sprite shader.
  414.     CShader* m_SpriteShader;
  415. };
  416.  
  417. // SpriteBatcher.cpp
  418. #include "SpriteBatcher.h"
  419. #include "Renderer.h"
  420.  
  421. CSpriteBatcher::CSpriteBatcher() : CBatcher<SBatchItemSprite*>()
  422. {
  423.     m_SpriteShader = new CShader("Resource/SpriteShader");
  424.  
  425.     SGameWindowViewport* viewPort = CGameWindow::GetWindowViewport();
  426.     m_SpriteShader->SetUniform("u_Projection", TMatrix4::OrthoProjection(0.0f, 0.0f, (float)viewPort->H, (float)viewPort->W));
  427. }
  428.  
  429. CSpriteBatcher::~CSpriteBatcher()
  430. {
  431. }
  432.  
  433. /*
  434. Called before rendering happens, allows shader manipulation etc.
  435. */
  436. void CSpriteBatcher::PreRender(CVertexArray* vertexArray, SBatchItemSprite* batchSet)
  437. {
  438.     // Binds the shader.
  439.     m_SpriteShader->SetUniform("u_Texture", batchSet->m_SpriteTexture);
  440.     m_SpriteShader->SetUniform("u_NormalTexture", batchSet->m_NormalTexture);
  441.     m_SpriteShader->SetUniform("u_LightPos", TVector2(1.0f, 1.0f));
  442.     m_SpriteShader->SetUniform("u_ResolutionScale", CRenderer::GetResolutionScale());
  443.     m_SpriteShader->BindShader();
  444. }
  445.  
  446. /*
  447. Called after rendering happens, allows unbinding data etc.
  448. */
  449. void CSpriteBatcher::PostRender(CVertexArray* vertexArray, SBatchItemSprite* batchSet)
  450. {
  451.     glUseProgram(0);
  452. }
  453.  
  454. /*
  455. Renders a box (adds it to the batch).
  456. */
  457. SBatchItemSprite* CSpriteBatcher::RenderSprite(CVertex* vertices[], size_t vertexCount, GLenum mode, CTexture* spriteTexture, CTexture* normalTexture)
  458. {
  459.     // Creates the item description for the batch item.
  460.     SBatchItemSprite* itemDescription = new SBatchItemSprite();
  461.     itemDescription->m_SpriteTexture = spriteTexture;
  462.     itemDescription->m_NormalTexture = normalTexture;
  463.     itemDescription->m_Primitive = mode;
  464.  
  465.     /*
  466.     for (unsigned int i = 0; i < vertexCount; i++)
  467.     {
  468.         TVector2 position = vertices[i]->GetVertexPosition(); position.Z = -9.0f;
  469.         vertices[i]->SetVertexPosition(position);
  470.     }
  471.     */
  472.  
  473.     // Adds the item.
  474.     return AddBatchItem(vertices, vertexCount, itemDescription);
  475. }
Advertisement
Add Comment
Please, Sign In to add comment