Pastebin launched a little side project called VERYVIRAL.com, check it out ;-) Want more features on Pastebin? Sign Up, it's FREE!
Guest

SpriteBatchMod1.cpp

By: Dekowta on Sep 16th, 2012  |  syntax: C++  |  size: 7.59 KB  |  views: 71  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. #include "MLSpriteBatch.h"
  2.  
  3. using MLRenderer::MLSpriteBatch;
  4.  
  5.  
  6. MLSpriteBatch::MLSpriteBatch(int buffersize) : m_BufferSize(buffersize)
  7. {
  8.         m_shader = new MLShader();
  9.         //load the default sprite batch shaders
  10.         m_shader->LoadShaderFile("shaders/SBatch.vert", GL_VERTEX_SHADER);
  11.         m_shader->LoadShaderFile("shaders/SBatch.frag", GL_FRAGMENT_SHADER);
  12.         //lock the shader in place to add the attributes and link
  13.         m_shader->lock();
  14.         {
  15.                 m_shader->bindAtt(MLRenderer::ML_ATT_VERTEXPOS, "VertexPosition");
  16.                 m_shader->bindAtt(MLRenderer::ML_ATT_TEXTURE0"TextureCoord");
  17.                 m_shader->LinkShaders();
  18.         }
  19.         m_shader->unlock(); //unlock the shader
  20.         m_beginCall = false;
  21.  
  22.         MLError::ErrorHandler::ML_Printf(ML_SpriteBatch, "Creating batch with max %i sprites\n", ML_MAX_SPRITES);
  23.  
  24.         //initalise the batcher
  25.         Initalise();
  26.  
  27.         MLError::ErrorHandler::ML_Printf(ML_SpriteBatch, "Created Sprite Batch\n");
  28. }
  29.  
  30.  
  31. MLSpriteBatch::MLSpriteBatch(MLShader* inShader, int buffersize) : m_shader(inShader), m_BufferSize(buffersize)
  32. {
  33.         m_beginCall = false;
  34.         Initalise();
  35. }
  36.  
  37. MLSpriteBatch::~MLSpriteBatch(void)
  38. {
  39.         Release(this);
  40. }
  41.  
  42. void MLSpriteBatch::release()
  43. {
  44.  
  45. }
  46.  
  47. void MLSpriteBatch::releaseShader()
  48. {
  49.         if (m_shader)
  50.                 delete m_shader;
  51. }
  52.  
  53. void MLSpriteBatch::Initalise()
  54. {
  55.         m_BufferOffset = 0;
  56.  
  57.         glGenBuffers(1, &m_VertBuffer);
  58.  
  59.         glBindBuffer(GL_ARRAY_BUFFER, m_VertBuffer);
  60.         glBufferData(GL_ARRAY_BUFFER, m_BufferSize, NULL,  GL_STREAM_DRAW);
  61.  
  62.         //generate the VAO
  63.         glGenVertexArrays(1, &m_BatchVAO);
  64.         //bind VAO
  65.         glBindVertexArray(m_BatchVAO);
  66.         //enable the vertex attributes for the VAO in this case vertex pos and texture are needed
  67.         glEnableVertexAttribArray((GLuint)MLRenderer::ML_ATT_VERTEXPOS);  // Vertex position
  68.         glEnableVertexAttribArray((GLuint)MLRenderer::ML_ATT_TEXTURE0); //vertex texture coord
  69.  
  70.         //set the vertex attribute pointers
  71.         glBindBuffer(GL_ARRAY_BUFFER, m_VertBuffer);
  72.         glVertexAttribPointer(MLRenderer::ML_ATT_VERTEXPOS, 3, GL_FLOAT, GL_FALSE, sizeof(MLBatchItem::Vertex), (GLubyte *)NULL );
  73.        
  74.         glVertexAttribPointer(MLRenderer::ML_ATT_TEXTURE0, 2, GL_FLOAT, GL_FALSE, sizeof(MLBatchItem::Vertex), (GLubyte*)sizeof(Vector3f));
  75.        
  76.         //unbind buffers
  77.         glBindVertexArray(0);
  78.         glBindBuffer(GL_ARRAY_BUFFER, 0);
  79.        
  80.         //set the total sprite count to 0
  81.         totalSpriteCount = 0;
  82.  
  83. }
  84.  
  85. void MLSpriteBatch::setShader(MLShader* inShader)
  86. {
  87.         m_shader = inShader;
  88. }
  89.  
  90. void MLSpriteBatch::Begin(bool Alpha)
  91. {
  92.         //simple check for alpha. This is pre-set to true
  93.         if (Alpha)
  94.         {
  95.                 glEnable (GL_BLEND);
  96.                 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  97.         }
  98.         else
  99.                 glDisable(GL_BLEND);
  100.  
  101.         //set the begincall to true so now end can be called without error
  102.         m_beginCall = true;
  103. }
  104.  
  105. void MLSpriteBatch::Draw(MLSprite* Sprite)
  106. {
  107.         //check to see if the sprite is enabled or not
  108.         if (!Sprite->getEnabled())
  109.                 return;
  110.  
  111.         bool NewBatch = false;
  112.  
  113.         //a pointer for a batch item
  114.         MLBatchItem::batchInfo* tmpBatch;
  115.  
  116.         //iterate through the batched items and see if the texture has been called before
  117.         BatchMap::iterator it = m_BatchItems.find(Sprite->getTexture());
  118.         if (it != m_BatchItems.end()) //if it has then set the pointer to that batch
  119.                 tmpBatch = m_BatchItems[Sprite->getTexture()];
  120.         else // otherwise create a new batch
  121.         {
  122.                 tmpBatch = new MLBatchItem::batchInfo();
  123.                 tmpBatch->spriteCount = 0;
  124.                 NewBatch = true;
  125.         }
  126.  
  127.         //create the points of the source rectangle
  128.         Vector3f topLeft                = Vector3f(Sprite->getPos().x, Sprite->getPos().y , 0.0f);
  129.         Vector3f topRight               = Vector3f((Sprite->getPos().x + Sprite->getSize().x), Sprite->getPos().y, 0.0f);
  130.         Vector3f bottmLeft              = Vector3f(Sprite->getPos().x, (Sprite->getPos().y + Sprite->getSize().y), 0.0f);
  131.         Vector3f bottomRight    = Vector3f((Sprite->getPos().x + Sprite->getSize().x), (Sprite->getPos().y + Sprite->getSize().y), 0.0f);
  132.        
  133.         //add the points to the batch
  134.         tmpBatch->addPoint(topLeft, Vector2f(0.0f, 1.0f));
  135.         tmpBatch->addPoint(topRight, Vector2f(1.0f, 1.0f));
  136.         tmpBatch->addPoint(bottomRight, Vector2f(1.0f, 0.0f));
  137.         tmpBatch->addPoint(bottmLeft, Vector2f(0.0f, 0.0f));
  138.        
  139.         //increase the batch sprite and total sprite count
  140.         tmpBatch->spriteCount++;
  141.         totalSpriteCount++;
  142.  
  143.         //if it was a new batch created add it to the map
  144.         if (NewBatch)
  145.                 m_BatchItems[Sprite->getTexture()] = tmpBatch;
  146.        
  147.         //if the max sprite count is reached then render them all out
  148.         //if (totalSpriteCount >= ML_MAX_SPRITES)
  149.         //      Render();
  150.  
  151. }
  152.  
  153. void MLSpriteBatch::Draw(GLuint Texture, Vector2f Pos, Vector2f Size)
  154. {
  155.        
  156.         bool NewBatch = false;
  157.  
  158.         MLBatchItem::batchInfo* tmpBatch;
  159.  
  160.         BatchMap::iterator it = m_BatchItems.find(Texture);
  161.         if (it != m_BatchItems.end())
  162.                 tmpBatch = m_BatchItems[Texture];
  163.         else
  164.         {
  165.                 tmpBatch = new MLBatchItem::batchInfo();
  166.                 tmpBatch->spriteCount = 0;
  167.                 NewBatch = true;
  168.         }
  169.  
  170.         Vector3f topLeft                = Vector3f(Pos.x, Pos.y , 0.0f);
  171.         Vector3f topRight               = Vector3f((Pos.x + Size.x), Pos.y, 0.0f);
  172.         Vector3f bottmLeft              = Vector3f(Pos.x, (Pos.y + Size.y), 0.0f);
  173.         Vector3f bottomRight    = Vector3f((Pos.x + Size.x), (Pos.y + Size.y), 0.0f);
  174.  
  175.         tmpBatch->addPoint(topLeft, Vector2f(0.0f, 1.0f));
  176.         tmpBatch->addPoint(topRight, Vector2f(1.0f, 1.0f));
  177.         tmpBatch->addPoint(bottomRight, Vector2f(1.0f, 0.0f));
  178.         tmpBatch->addPoint(bottmLeft, Vector2f(0.0f, 0.0f));
  179.  
  180.         tmpBatch->spriteCount++;
  181.  
  182.         if (NewBatch)
  183.                 m_BatchItems[Texture] = tmpBatch;
  184. }
  185.  
  186. void MLSpriteBatch::End()
  187. {
  188.         //If begin has not been called then there is an error
  189.         if (!m_beginCall)
  190.         {
  191.                 MLError::ErrorHandler::printError("Begin must be called before end");
  192.                 return;
  193.         }
  194.         //if the sprite count is greater than 0 the something will need to be rendered still
  195.         if (totalSpriteCount > 0)
  196.                 Render();
  197.  
  198.         //clear the batch after done just in case
  199.         m_BatchItems.clear();
  200. }
  201.  
  202. void MLSpriteBatch::Render()
  203. {
  204.         //lock the shader
  205.         m_shader->lock();
  206.         //apply the uniforms
  207.         m_shader->addUniform("inMVP", (MLRenderer::MLCoreGL::getOrtho()));
  208.         m_shader->addUniform("Tex1", 0);
  209.  
  210.         //bind the vertex array
  211.         glBindVertexArray(m_BatchVAO);
  212.  
  213.         //start iterating through the batchs
  214.         BatchMap::iterator it = m_BatchItems.begin();
  215.         for(; it != m_BatchItems.end(); it++)
  216.         {
  217.                 //create a pointer to the current batch
  218.                 MLBatchItem::batchInfo* currentBatch = it->second;
  219.  
  220.                 //bind the current texture
  221.                 glBindTexture(GL_TEXTURE_2D, it->first);
  222.  
  223.                 glBindBuffer(GL_ARRAY_BUFFER, m_VertBuffer);
  224.                 if ((m_BufferOffset + currentBatch->spriteCount) >= m_BufferSize)
  225.                 {
  226.                         MLError::ErrorHandler::ML_Printf(ML_SpriteBatch, "new buffer\n");
  227.                         glBufferData(GL_ARRAY_BUFFER, m_BufferSize, NULL, GL_STREAM_DRAW);
  228.                         m_BufferOffset = 0;
  229.                 }
  230.  
  231.                 MLError::ErrorHandler::ML_Printf(ML_SpriteBatchError ,"GLError Code Before Map: %g\n");
  232.                 GLbitfield access = (GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_INVALIDATE_RANGE_BIT);
  233.                 void* mappedData = glMapBufferRange(GL_ARRAY_BUFFER, m_BufferOffset, m_BufferOffset +  currentBatch->spriteCount, access);
  234.                 MLError::ErrorHandler::ML_Printf(ML_SpriteBatchError ,"GLError Code After Map: %g\n");
  235.  
  236.                 if (mappedData)
  237.                 {
  238.                         memcpy(mappedData, it->second->Verts, it->second->spriteCount);
  239.                         glUnmapBuffer(GL_ARRAY_BUFFER);
  240.                         //draw using the indicies and vert count set when the batch was created
  241.                         glDrawArrays(GL_QUADS, 0, currentBatch->spriteCount);
  242.                         m_BufferOffset += currentBatch->spriteCount;
  243.                 }
  244.                
  245.                 //unbind the texture
  246.                 glBindTexture(GL_TEXTURE_2D, 0);
  247.  
  248.                 //delete the batch
  249.                 delete it->second;
  250.         }
  251.         //unbind the buffers
  252.         glBindVertexArray(0);
  253.         glBindBuffer(GL_ARRAY_BUFFER, 0);
  254.         //unlock the shader
  255.         m_shader->unlock();
  256.  
  257.         //set the total sprite count to 0
  258.         totalSpriteCount = 0;
  259.         //clear the batchs
  260.         m_BatchItems.clear();
  261. }