Want more features on Pastebin? Sign Up, it's FREE!
Guest

SpriteBatch.cpp

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