Advertisement
Dekowta

SpriteBatchMod1.cpp

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