jubilant-funicular
SpriteBatch.cpp
1 #include <algorithm>
2 
3 #include "nta/SpriteBatch.h"
4 #include "nta/Vertex.h"
5 
6 namespace nta {
8  }
9  SpriteBatch::~SpriteBatch() {
10  if (m_vbo != 0) {
11  glDeleteBuffers(1, &m_vbo);
12  }
13  if (m_vao != 0) {
14  glDeleteVertexArrays(1, &m_vao);
15  }
16  m_glyphs.clear();
17  m_glyphPointers.clear();
18  m_renderBatches.clear();
19  }
22  }
24  if (m_vbo == 0) {
25  glGenBuffers(1, &m_vbo);
26  }
27  if (m_vao == 0) {
28  glGenVertexArrays(1, &m_vao);
29  }
30  glBindVertexArray(m_vao);
31  glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
32  for (int i = 0; i < NUM_VERTEX_ATTRIBS; i++) {
33  glEnableVertexAttribArray(i);
34  Vertex2D::attribs[i].setup();
35  }
36  glBindVertexArray(0);
37  }
39  m_glyphs.clear();
40  m_renderBatches.clear();
41  }
43  m_glyphPointers.resize(m_glyphs.size());
44  for (int i = 0; i < m_glyphs.size(); i++) {
45  m_glyphPointers[i] = &m_glyphs[i];
46  }
47  sortGlyphs();
49  }
51  std::stable_sort(m_glyphPointers.begin(), m_glyphPointers.end(), compareDepth);
52  int begin = 0;
53  for (int i = 1; i < m_glyphPointers.size(); i++) {
54  if (m_glyphPointers[i]->depth != m_glyphPointers[i-1]->depth) {
55  std::stable_sort(m_glyphPointers.begin()+begin, m_glyphPointers.begin()+i, compareTexture);
56  begin = i;
57  }
58  }
59  }
60  bool SpriteBatch::compareDepth(Glyph* lhs, Glyph* rhs) {
61  return (lhs->depth < rhs->depth);
62  }
64  return (lhs->textureID < rhs->textureID);
65  }
67  if (m_glyphPointers.empty()) {
68  return;
69  }
70 
71  std::vector<Vertex2D> vertexData(6*m_glyphPointers.size());
72  m_renderBatches.emplace_back(m_glyphPointers[0]->textureID, 0, 6);
73  int cv = 0; // current vertex
74  vertexData[cv++] = m_glyphPointers[0]->topLeft;
75  vertexData[cv++] = m_glyphPointers[0]->topRight;
76  vertexData[cv++] = m_glyphPointers[0]->botLeft;
77  vertexData[cv++] = m_glyphPointers[0]->topRight;
78  vertexData[cv++] = m_glyphPointers[0]->botLeft;
79  vertexData[cv++] = m_glyphPointers[0]->botRight;
80  int offset = 6;
81  for (int cg = 1; cg < m_glyphPointers.size(); cg++) { // current glyph
82  if (m_glyphPointers[cg]->textureID != m_glyphPointers[cg-1]->textureID) {
83  m_renderBatches.emplace_back(m_glyphPointers[cg]->textureID, offset, 6);
84  } else {
85  m_renderBatches.back().numVertices += 6;
86  }
87  vertexData[cv++] = m_glyphPointers[cg]->topLeft;
88  vertexData[cv++] = m_glyphPointers[cg]->topRight;
89  vertexData[cv++] = m_glyphPointers[cg]->botLeft;
90  vertexData[cv++] = m_glyphPointers[cg]->topRight;
91  vertexData[cv++] = m_glyphPointers[cg]->botLeft;
92  vertexData[cv++] = m_glyphPointers[cg]->botRight;
93  offset += 6;
94  }
95  glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
96  glBufferData(GL_ARRAY_BUFFER, vertexData.size()*sizeof(Vertex2D), nullptr, GL_DYNAMIC_DRAW);
97  glBufferSubData(GL_ARRAY_BUFFER, 0, vertexData.size()*sizeof(Vertex2D), vertexData.data());
98  glBindBuffer(GL_ARRAY_BUFFER, 0);
99  }
100  void SpriteBatch::addGlyph(crvec4 posRect, GLuint texture, crvec4 uvRect,
101  crvec4 color, float depth) {
102  m_glyphs.emplace_back(posRect, uvRect, texture, depth, color);
103  }
104  void SpriteBatch::addGlyph(crvec4 posRect, crvec4 uvRect, GLuint texture, float depth,
105  crvec4 color) {
106  addGlyph(posRect, uvRect, texture, color, 0, depth);
107  }
108  void SpriteBatch::addGlyph(crvec2 corner1, crvec2 corner2, crvec4 uvRect, GLuint texture,
109  float depth, crvec4 color) {
110  addGlyph(corner1, corner2, uvRect, texture, color, 0, depth);
111  }
112  void SpriteBatch::addGlyph(crvec4 posRect, crvec4 uvRect, GLuint texture, crvec4 color,
113  float angle, float depth) {
114  m_glyphs.emplace_back(posRect, uvRect, texture, depth, color, angle);
115  }
116  void SpriteBatch::addGlyph(crvec2 corner1, crvec2 corner2, crvec4 uvRect, GLuint texture,
117  crvec4 color, float angle, float depth) {
118  glm::vec4 posRect(glm::min(corner1.x, corner2.x), glm::max(corner1.y, corner2.y),
119  glm::abs(corner1-corner2));
120  addGlyph(posRect, uvRect, texture, color, angle, depth);
121  }
122  void SpriteBatch::render() const {
123  glBindVertexArray(m_vao);
124  for (int i = 0; i < m_renderBatches.size(); i++) {
125  glBindTexture(GL_TEXTURE_2D, m_renderBatches[i].textureID);
126  glDrawArrays(m_renderBatches[i].mode, m_renderBatches[i].offset,
127  m_renderBatches[i].numVertices);
128  }
129  glBindVertexArray(0);
130  }
131 }
nta::SpriteBatch::init
void init()
initializes the batch
Definition: SpriteBatch.cpp:20
nta::SpriteBatch::end
void end()
ends collection of glyphs and prepares to render
Definition: SpriteBatch.cpp:42
nta::SpriteBatch::m_renderBatches
std::vector< RenderBatch > m_renderBatches
the render batches used for rendering the glyphs
Definition: SpriteBatch.h:103
nta::Glyph::depth
float depth
the depth of the glyph
Definition: SpriteBatch.h:60
nta::SpriteBatch::createRenderBatches
void createRenderBatches()
creates the render batches
Definition: SpriteBatch.cpp:66
nta::SpriteBatch::compareTexture
static bool compareTexture(Glyph *lhs, Glyph *rhs)
comparers used to sort
Definition: SpriteBatch.cpp:63
nta::SpriteBatch::addGlyph
void addGlyph(crvec4 posRect, GLuint texture=0, crvec4 uvRect=glm::vec4(0, 0, 1, 1), crvec4 color=glm::vec4(1), float depth=0.5)
Definition: SpriteBatch.cpp:100
nta
Definition: Animation2D.h:6
nta::SpriteBatch::createVertexArrayObject
void createVertexArrayObject()
creates the vertex array object
Definition: SpriteBatch.cpp:23
nta::Glyph
represents what is essentially a sprite
Definition: SpriteBatch.h:13
nta::SpriteBatch::sortGlyphs
void sortGlyphs()
sorts the glyphs
Definition: SpriteBatch.cpp:50
nta::Glyph::textureID
GLuint textureID
the texture used by the glyph
Definition: SpriteBatch.h:58
nta::SpriteBatch::m_glyphPointers
std::vector< Glyph * > m_glyphPointers
pointers to the glyphs to be rendered (used for sorting)
Definition: SpriteBatch.h:99
nta::Vertex2D
represents a vertex in 2 dimensions
Definition: Vertex.h:26
nta::SpriteBatch::m_glyphs
std::vector< Glyph > m_glyphs
the glyphs to be rendered (used for fast vector operations)
Definition: SpriteBatch.h:101
nta::SpriteBatch::begin
void begin()
begins collection of glyphs for the batch
Definition: SpriteBatch.cpp:38
nta::SpriteBatch::SpriteBatch
SpriteBatch()
constructor and destructor
Definition: SpriteBatch.cpp:7
nta::SpriteBatch::m_vao
GLuint m_vao
ids of the vertex buffer object and vertex array object used to render the glyphs
Definition: SpriteBatch.h:105
nta::SpriteBatch::render
void render() const
renders the batch
Definition: SpriteBatch.cpp:122