hx3d  1
2D/3D Simple Game Framework
fast_batch.hpp
1 /*
2  Fast Batch.
3  Copyright (C) 2015 Denis BOURGE
4 
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Lesser General Public
7  License as published by the Free Software Foundation; either
8  version 2.1 of the License, or (at your option) any later version.
9 
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public
16  License along with this library; if not, write to the Free Software
17  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
18  USA
19 */
20 
21 #ifndef HX3D_GRAPHICS_FAST_BATCH
22 #define HX3D_GRAPHICS_FAST_BATCH
23 
24 namespace hx3d {
25 namespace graphics {
26 
30 class FastBatch {
31 public:
32  FastBatch(unsigned int size): size(size), vboId(0), vboIndicesId(0), current(0), currentIdx(0), maxIdx(0), drawing(false) {
33  vertices.resize(size * 36);
34  indices.resize(size * 6);
35 
36  // Buffers
37  glGenBuffers(1, &vboId);
38  glGenBuffers(1, &vboIndicesId);
39 
40  glBindBuffer(GL_ARRAY_BUFFER, vboId);
41  glBufferData(GL_ARRAY_BUFFER, size * 36 * sizeof(float), NULL, GL_STREAM_DRAW);
42  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndicesId);
43  glBufferData(GL_ELEMENT_ARRAY_BUFFER, size * 6 * sizeof(GLushort), NULL, GL_STREAM_DRAW);
44  }
45 
46  void setShader(const Ptr<Shader>& shader) {
47  this->shader = shader;
48  }
49 
50  void clear() {
51  current = 0;
52  currentIdx = 0;
53  maxIdx = 0;
54  }
55 
56  void begin() {
57  if (shader == nullptr) {
58  Log.Error("FastBatch: no shader.");
59  return;
60  }
61 
62  drawing = true;
63  drawCalls = 0;
64  }
65 
66  void end() {
67  flush();
68 
69  drawing = false;
70  }
71 
72  void draw(Sprite& sprite) {
73 
74  if (!drawing) {
75  Log.Error("FastBatch: not currently drawing !");
76  return;
77  }
78 
79  // Calcul des positions post-transform
80  AttributeArrayBuffer& positions = sprite.getGeometry()->getAttribute("Position");
81  unsigned int vertSize = positions.size() / 3;
82  unsigned int prevMaxIdx = maxIdx;
83  auto& ind = sprite.getGeometry()->getIndices();
84 
85  glm::mat4 model = sprite.transform.compute();
86  std::vector<float> newPositions;
87  newPositions.resize(vertSize * 3);
88 
89  if (current + vertSize * 3 > size * 36) {
90  Log.Error("FastBatch too small: force flush.");
91  flush();
92  }
93 
94  if (maxIdx >= USHRT_MAX) {
95  Log.Error("Too much indices ! (max: 65536): force flush.");
96  flush();
97  }
98 
99  for (unsigned int i = 0; i < vertSize*3; i += 3) {
100  glm::vec4 pos = {
101  positions.getValue(i),
102  positions.getValue(i+1),
103  positions.getValue(i+2),
104  1
105  };
106 
107  glm::vec4 npos = model * pos;
108 
109  newPositions[i] = npos.x;
110  newPositions[i+1] = npos.y;
111  newPositions[i+2] = npos.z;
112  }
113 
114  for (unsigned int i = 0; i < vertSize; ++i) {
115  for (unsigned int j = i * 3; j < (i+1) * 3; ++j) {
116  vertices[current++] = newPositions[j];
117  }
118  for (unsigned int j = i * 4; j < (i+1) * 4; ++j) {
119  vertices[current++] = sprite.getGeometry()->getAttribute("Color").getValue(j);
120  }
121  for (unsigned int j = i * 2; j < (i+1) * 2; ++j) {
122  vertices[current++] = sprite.getGeometry()->getAttribute("Texture").getValue(j);
123  }
124  }
125 
126  for (unsigned int i = 0; i < ind.size(); ++i) {
127  unsigned int val = ind.getValue(i) + prevMaxIdx;
128  maxIdx = std::max(maxIdx, val);
129  indices[currentIdx++] = val;
130  }
131  maxIdx += 1;
132  }
133 
134  void flush() {
135  glBindBuffer(GL_ARRAY_BUFFER, vboId);
136  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndicesId);
137 
138  glBufferSubData(GL_ARRAY_BUFFER, 0, current * sizeof(float), vertices.data());
139  glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, currentIdx * sizeof(GLushort), indices.data());
140 
141  glEnableVertexAttribArray(shader->getAttribute("a_position"));
142  glEnableVertexAttribArray(shader->getAttribute("a_color"));
143  glEnableVertexAttribArray(shader->getAttribute("a_texture"));
144 
145  glVertexAttribPointer(shader->getAttribute("a_position"), 3, GL_FLOAT, GL_FALSE, 9*sizeof(float), BUFFER_OFFSET(0));
146  glVertexAttribPointer(shader->getAttribute("a_color"), 4, GL_FLOAT, GL_FALSE, 9*sizeof(float), BUFFER_OFFSET(3*sizeof(float)));
147  glVertexAttribPointer(shader->getAttribute("a_texture"), 2, GL_FLOAT, GL_FALSE, 9*sizeof(float), BUFFER_OFFSET(7*sizeof(float)));
148 
149  glDrawElements(GL_TRIANGLES, currentIdx, GL_UNSIGNED_SHORT, BUFFER_OFFSET(0));
150 
151  glDisableVertexAttribArray(shader->getAttribute("a_position"));
152  glDisableVertexAttribArray(shader->getAttribute("a_color"));
153  glDisableVertexAttribArray(shader->getAttribute("a_texture"));
154 
155  ++drawCalls;
156 
157  clear();
158  }
159 
160  unsigned int size;
161 
162  unsigned int vboId;
163  unsigned int vboIndicesId;
164 
165  unsigned int current;
166  unsigned int currentIdx;
167  unsigned int maxIdx;
168 
169  unsigned int drawCalls;
170  bool drawing;
171 
172  Ptr<Shader> shader;
173  std::vector<float> vertices;
174  std::vector<GLushort> indices;
175 };
176 
177 } /* graphics */
178 } /* hx3d */
179 
180 #endif /* HX3D_GRAPHICS_FAST_BATCH */
Real batching using real-time VBO generation.
Definition: fast_batch.hpp:30
hx3d framework namespace
Definition: audio.hpp:26
glm::mat4 compute()
Build the model matrix using the position, scale, size and rotation.
Definition: transform.cpp:43
void Error(const std::string fmt,...)
Write an error message.
Definition: log.cpp:72
static hx3d::LogImpl Log
Current log implementation.
Definition: log.hpp:91
2D texture manipulation.
Definition: sprite.hpp:62
Transform transform
Mesh transformation.
Definition: mesh.hpp:90
Ptr< geom::BaseGeometry > & getGeometry()
Get the mesh geometry.
Definition: mesh.cpp:53
std::shared_ptr< T > Ptr
Quick-typing shared ptr.
Definition: ptr.hpp:34