Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "MLSpriteBatch.h"
- using MLRenderer::MLSpriteBatch;
- MLSpriteBatch::MLSpriteBatch(void)
- {
- m_shader = new MLShader();
- //load the default sprite batch shaders
- m_shader->LoadShaderFile("shaders/SBatch.vert", GL_VERTEX_SHADER);
- m_shader->LoadShaderFile("shaders/SBatch.frag", GL_FRAGMENT_SHADER);
- //lock the shader in place to add the attributes and link
- m_shader->lock();
- {
- m_shader->bindAtt(MLRenderer::ML_ATT_VERTEXPOS, "VertexPosition");
- m_shader->bindAtt(MLRenderer::ML_ATT_TEXTURE0, "TextureCoord");
- m_shader->LinkShaders();
- }
- m_shader->unlock(); //unlock the shader
- m_beginCall = false;
- MLError::ErrorHandler::ML_Printf(ML_SpriteBatch, "Creating batch with max %i sprites\n", ML_MAX_SPRITES);
- //initalise the batcher
- Initalise();
- MLError::ErrorHandler::ML_Printf(ML_SpriteBatch, "Created Sprite Batch\n");
- }
- MLSpriteBatch::MLSpriteBatch(MLShader* inShader) : m_shader(inShader)
- {
- m_beginCall = false;
- Initalise();
- }
- MLSpriteBatch::~MLSpriteBatch(void)
- {
- Release(this);
- }
- void MLSpriteBatch::release()
- {
- if (indicies)
- delete [] indicies;
- if (Vcount)
- delete [] Vcount;
- }
- void MLSpriteBatch::releaseShader()
- {
- if (m_shader)
- delete m_shader;
- }
- void MLSpriteBatch::Initalise()
- {
- //generate 2 buffers for the vertex and UV VBO
- GLuint buffID[2];
- glGenBuffers(2, buffID);
- m_VposBuffer = buffID[0];
- m_UVBuffer = buffID[1];
- //set blank data to both and set them to the max amount of sprites
- glBindBuffer(GL_ARRAY_BUFFER, m_VposBuffer);
- glBufferData(GL_ARRAY_BUFFER, (ML_MAX_SPRITES * 4) * sizeof(Vector3f), 0, GL_DYNAMIC_DRAW);
- glBindBuffer(GL_ARRAY_BUFFER, m_UVBuffer);
- glBufferData(GL_ARRAY_BUFFER, (ML_MAX_SPRITES * 4) * sizeof(Vector3f), 0, GL_DYNAMIC_DRAW);
- //generate the VAO
- glGenVertexArrays(1, &m_BatchVAO);
- //bind VAO
- glBindVertexArray(m_BatchVAO);
- //enable the vertex attributes for the VAO in this case vertex pos and texture are needed
- glEnableVertexAttribArray((GLuint)MLRenderer::ML_ATT_VERTEXPOS); // Vertex position
- glEnableVertexAttribArray((GLuint)MLRenderer::ML_ATT_TEXTURE0); //vertex texture coord
- //set the vertex attribute pointers
- glBindBuffer(GL_ARRAY_BUFFER, m_VposBuffer);
- glVertexAttribPointer(MLRenderer::ML_ATT_VERTEXPOS, 3, GL_FLOAT, GL_FALSE, 0, (GLubyte *)NULL );
- glBindBuffer(GL_ARRAY_BUFFER, m_UVBuffer);
- glVertexAttribPointer(MLRenderer::ML_ATT_TEXTURE0, 2, GL_FLOAT, GL_FALSE, 0, (GLubyte *)NULL );
- //unbind buffers
- glBindVertexArray(0);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- //create an index array for the primitives
- indicies = new GLint[ML_MAX_SPRITES]();
- Vcount = new GLsizei[ML_MAX_SPRITES]();
- for(int i = 0; i < ML_MAX_SPRITES; i++)
- {
- indicies[i] = i * 4;
- Vcount[i] = 4;
- }
- //set the total sprite count to 0
- totalSpriteCount = 0;
- }
- void MLSpriteBatch::setShader(MLShader* inShader)
- {
- m_shader = inShader;
- }
- void MLSpriteBatch::Begin(bool Alpha)
- {
- //simple check for alpha. This is pre-set to true
- if (Alpha)
- {
- glEnable (GL_BLEND);
- glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- }
- else
- glDisable(GL_BLEND);
- //set the begincall to true so now end can be called without error
- m_beginCall = true;
- }
- void MLSpriteBatch::Draw(MLSprite* Sprite)
- {
- //check to see if the sprite is enabled or not
- if (!Sprite->getEnabled())
- return;
- bool NewBatch = false;
- //a pointer for a batch item
- MLBatchItem::batchInfo* tmpBatch;
- //iterate through the batched items and see if the texture has been called before
- BatchMap::iterator it = m_BatchItems.find(Sprite->getTexture());
- if (it != m_BatchItems.end()) //if it has then set the pointer to that batch
- tmpBatch = m_BatchItems[Sprite->getTexture()];
- else // otherwise create a new batch
- {
- tmpBatch = new MLBatchItem::batchInfo();
- tmpBatch->spriteCount = 0;
- NewBatch = true;
- }
- //create the points of the source rectangle
- Vector3f topLeft = Vector3f(Sprite->getPos().x, Sprite->getPos().y , 0.0f);
- Vector3f topRight = Vector3f((Sprite->getPos().x + Sprite->getSize().x), Sprite->getPos().y, 0.0f);
- Vector3f bottmLeft = Vector3f(Sprite->getPos().x, (Sprite->getPos().y + Sprite->getSize().y), 0.0f);
- Vector3f bottomRight = Vector3f((Sprite->getPos().x + Sprite->getSize().x), (Sprite->getPos().y + Sprite->getSize().y), 0.0f);
- //add the points to the batch
- tmpBatch->addPoint(topLeft, Vector2f(0.0f, 1.0f));
- tmpBatch->addPoint(topRight, Vector2f(1.0f, 1.0f));
- tmpBatch->addPoint(bottomRight, Vector2f(1.0f, 0.0f));
- tmpBatch->addPoint(bottmLeft, Vector2f(0.0f, 0.0f));
- //increase the batch sprite and total sprite count
- tmpBatch->spriteCount++;
- totalSpriteCount++;
- //if it was a new batch created add it to the map
- if (NewBatch)
- m_BatchItems[Sprite->getTexture()] = tmpBatch;
- //if the max sprite count is reached then render them all out
- if (totalSpriteCount >= ML_MAX_SPRITES)
- Render();
- }
- void MLSpriteBatch::Draw(GLuint Texture, Vector2f Pos, Vector2f Size)
- {
- bool NewBatch = false;
- MLBatchItem::batchInfo* tmpBatch;
- BatchMap::iterator it = m_BatchItems.find(Texture);
- if (it != m_BatchItems.end())
- tmpBatch = m_BatchItems[Texture];
- else
- {
- tmpBatch = new MLBatchItem::batchInfo();
- tmpBatch->spriteCount = 0;
- NewBatch = true;
- }
- Vector3f topLeft = Vector3f(Pos.x, Pos.y , 0.0f);
- Vector3f topRight = Vector3f((Pos.x + Size.x), Pos.y, 0.0f);
- Vector3f bottmLeft = Vector3f(Pos.x, (Pos.y + Size.y), 0.0f);
- Vector3f bottomRight = Vector3f((Pos.x + Size.x), (Pos.y + Size.y), 0.0f);
- tmpBatch->addPoint(topLeft, Vector2f(0.0f, 1.0f));
- tmpBatch->addPoint(topRight, Vector2f(1.0f, 1.0f));
- tmpBatch->addPoint(bottomRight, Vector2f(1.0f, 0.0f));
- tmpBatch->addPoint(bottmLeft, Vector2f(0.0f, 0.0f));
- tmpBatch->spriteCount++;
- if (NewBatch)
- m_BatchItems[Texture] = tmpBatch;
- }
- void MLSpriteBatch::End()
- {
- //If begin has not been called then there is an error
- if (!m_beginCall)
- {
- MLError::ErrorHandler::printError("Begin must be called before end");
- return;
- }
- //if the sprite count is greater than 0 the something will need to be rendered still
- if (totalSpriteCount > 0)
- Render();
- //clear the batch after done just in case
- m_BatchItems.clear();
- }
- void MLSpriteBatch::Render()
- {
- //lock the shader
- m_shader->lock();
- //apply the uniforms
- m_shader->addUniform("inMVP", (MLRenderer::MLCoreGL::getOrtho()));
- m_shader->addUniform("Tex1", 0);
- //bind the vertex array
- glBindVertexArray(m_BatchVAO);
- //start iterating through the batchs
- BatchMap::iterator it = m_BatchItems.begin();
- for(; it != m_BatchItems.end(); it++)
- {
- //create a pointer to the current batch
- MLBatchItem::batchInfo* currentBatch = it->second;
- //bind the current texture
- glBindTexture(GL_TEXTURE_2D, it->first);
- //bind the vertex buffer and set the data from the batch
- glBindBuffer(GL_ARRAY_BUFFER, m_VposBuffer);
- glBufferSubData(GL_ARRAY_BUFFER, 0, (currentBatch->spriteCount * 4) * sizeof(Vector3f), currentBatch->VPos);
- //bind the texture buffer and set the data from the batch
- glBindBuffer(GL_ARRAY_BUFFER, m_UVBuffer);
- glBufferSubData(GL_ARRAY_BUFFER, 0, (currentBatch->spriteCount * 4) * sizeof(Vector2f), currentBatch->UV);
- //draw using the indicies and vert count set when the batch was created
- glMultiDrawArrays(GL_QUADS, indicies, Vcount, currentBatch->spriteCount);
- //unbind the texture
- glBindTexture(GL_TEXTURE_2D, 0);
- //delete the batch
- delete it->second;
- }
- //unbind the buffers
- glBindVertexArray(0);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- //unlock the shader
- m_shader->unlock();
- //set the total sprite count to 0
- totalSpriteCount = 0;
- //clear the batchs
- m_BatchItems.clear();
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement