Advertisement
Dekowta

SB.cpp

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