Advertisement
Dekowta

SpriteBatch.cpp

Sep 13th, 2012
219
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.69 KB | None | 0 0
  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. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement