8
8
#include " growl/core/graphics/window.h"
9
9
#include " opengl_shader.h"
10
10
#include " opengl_texture.h"
11
+ #include < OpenGL/OpenGL.h>
11
12
#include < cmath>
12
13
#include < vector>
13
14
@@ -36,7 +37,8 @@ OpenGLBatch::OpenGLBatch(
36
37
glGenBuffers (1 , &ubo);
37
38
glBindBuffer (GL_UNIFORM_BUFFER, ubo);
38
39
glBufferData (
39
- GL_UNIFORM_BUFFER, 2 * sizeof (glm::mat4), NULL , GL_STATIC_DRAW);
40
+ GL_UNIFORM_BUFFER, (MAX_BATCH_SIZE + 1 ) * sizeof (glm::mat4), NULL ,
41
+ GL_STATIC_DRAW);
40
42
glBindBuffer (GL_UNIFORM_BUFFER, 0 );
41
43
}
42
44
@@ -68,9 +70,11 @@ void OpenGLBatch::begin() {
68
70
glBindBufferRange (GL_UNIFORM_BUFFER, 0 , ubo, 0 , sizeof (glm::mat4));
69
71
glBufferSubData (
70
72
GL_UNIFORM_BUFFER, 0 , sizeof (glm::mat4), glm::value_ptr (projection));
73
+ glBindBuffer (GL_UNIFORM_BUFFER, 0 );
71
74
}
72
75
73
76
void OpenGLBatch::end () {
77
+ flush ();
74
78
glBindVertexArray (0 );
75
79
if (fbo) {
76
80
glBindFramebuffer (GL_FRAMEBUFFER, 0 );
@@ -81,82 +85,106 @@ void OpenGLBatch::setColor(float r, float g, float b, float a) {
81
85
color = {r, g, b, a};
82
86
}
83
87
84
- void OpenGLBatch::setTransform (glm::mat4x4 transform) {
85
- glBindBuffer (GL_UNIFORM_BUFFER, ubo);
86
- glBufferSubData (
87
- GL_UNIFORM_BUFFER, sizeof (glm::mat4), sizeof (glm::mat4),
88
- glm::value_ptr (transform));
89
- glBindBuffer (GL_UNIFORM_BUFFER, 0 );
90
- }
91
-
92
88
void OpenGLBatch::draw (
93
89
const Texture& texture, float x, float y, float width, float height,
94
90
glm::mat4x4 transform) {
95
91
auto & tex = static_cast <const OpenGLTexture&>(texture);
96
- tex.bind ();
97
- setTransform (transform);
98
- glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
99
- glEnable (GL_BLEND);
92
+ if (&tex != bound_tex || default_shader != bound_shader) {
93
+ flush ();
94
+ }
95
+ uniforms.insert (uniforms.end (), SpriteBlock{transform});
96
+ bound_tex = &tex;
97
+ bound_shader = default_shader;
100
98
float right = x + width;
101
99
float bottom = y + height;
102
- float quad_vertex_data[] = {
103
- x, y, 0 .0f , 0 .0f , // Top-left
104
- right, y, 1 .0f , 0 .0f , // Top-right
105
- right, bottom, 1 .0f , 1 .0f , // Bottom-right
106
- x, bottom, 0 .0f , 1 .0f // Bottom-left
107
- };
108
- GLuint elements[] = {0 , 1 , 2 , 2 , 3 , 0 };
109
- glBindBuffer (GL_ARRAY_BUFFER, vbo);
110
- glBufferData (
111
- GL_ARRAY_BUFFER, sizeof (quad_vertex_data), quad_vertex_data,
112
- GL_STATIC_DRAW);
113
- glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, ebo);
114
- glBufferData (
115
- GL_ELEMENT_ARRAY_BUFFER, sizeof (elements), elements, GL_STATIC_DRAW);
116
- default_shader->bind (color);
117
- glDrawElements (GL_TRIANGLES, 6 , GL_UNSIGNED_INT, 0 );
100
+ vertices.insert (
101
+ vertices.end (), {
102
+ x,
103
+ y,
104
+ 0 .0f ,
105
+ 0 .0f ,
106
+ static_cast <GLfloat>(idx), // Top-left
107
+ right,
108
+ y,
109
+ 1 .0f ,
110
+ 0 .0f ,
111
+ static_cast <GLfloat>(idx), // Top-right
112
+ right,
113
+ bottom,
114
+ 1 .0f ,
115
+ 1 .0f ,
116
+ static_cast <GLfloat>(idx), // Bottom-right
117
+ x,
118
+ bottom,
119
+ 0 .0f ,
120
+ 1 .0f ,
121
+ static_cast <GLfloat>(idx) // Bottom-left
122
+ });
123
+ elements.insert (
124
+ elements.end (),
125
+ {verts, verts + 1 , verts + 2 , verts + 2 , verts + 3 , verts});
126
+ idx++;
127
+ verts += 4 ;
118
128
}
119
129
120
130
void OpenGLBatch::draw (
121
131
const TextureAtlasRegion& region, float x, float y, float width,
122
132
float height, glm::mat4x4 transform) {
123
133
auto & tex = static_cast <const OpenGLTexture&>(region.atlas ->getTexture ());
124
- tex.bind ();
125
- setTransform (transform);
126
- glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
127
- glEnable (GL_BLEND);
134
+ if (&tex != bound_tex || default_shader != bound_shader) {
135
+ flush ();
136
+ }
137
+ uniforms.insert (uniforms.end (), SpriteBlock{transform});
138
+ bound_tex = &tex;
139
+ bound_shader = default_shader;
128
140
float right = x + width;
129
141
float bottom = y + height;
130
- float quad_vertex_data[] = {
131
- x, y, region.region .u0 , region.region .v0 ,
132
- right, y, region.region .u1 , region.region .v0 ,
133
- right, bottom, region.region .u1 , region.region .v1 ,
134
- x, bottom, region.region .u0 , region.region .v1 };
135
- GLuint elements[] = {0 , 1 , 2 , 2 , 3 , 0 };
136
- glBindBuffer (GL_ARRAY_BUFFER, vbo);
137
- glBufferData (
138
- GL_ARRAY_BUFFER, sizeof (quad_vertex_data), quad_vertex_data,
139
- GL_STATIC_DRAW);
140
- glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, ebo);
141
- glBufferData (
142
- GL_ELEMENT_ARRAY_BUFFER, sizeof (elements), elements, GL_STATIC_DRAW);
143
- default_shader->bind (color);
144
- glDrawElements (GL_TRIANGLES, 6 , GL_UNSIGNED_INT, 0 );
142
+ vertices.insert (
143
+ vertices.end (), {
144
+ x,
145
+ y,
146
+ region.region .u0 ,
147
+ region.region .v0 ,
148
+ static_cast <GLfloat>(idx),
149
+ right,
150
+ y,
151
+ region.region .u1 ,
152
+ region.region .v0 ,
153
+ static_cast <GLfloat>(idx),
154
+ right,
155
+ bottom,
156
+ region.region .u1 ,
157
+ region.region .v1 ,
158
+ static_cast <GLfloat>(idx),
159
+ x,
160
+ bottom,
161
+ region.region .u0 ,
162
+ region.region .v1 ,
163
+ static_cast <GLfloat>(idx),
164
+ });
165
+ elements.insert (
166
+ elements.end (),
167
+ {verts, verts + 1 , verts + 2 , verts + 2 , verts + 3 , verts});
168
+ idx++;
169
+ verts += 4 ;
145
170
}
146
171
147
172
void OpenGLBatch::draw (
148
173
const GlyphLayout& glyph_layout, const FontTextureAtlas& font_texture_atlas,
149
174
float x, float y, glm::mat4x4 transform) {
150
175
auto & tex =
151
176
static_cast <const OpenGLTexture&>(font_texture_atlas.getTexture ());
152
- tex.bind ();
153
- setTransform (transform);
154
- glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
155
- glEnable (GL_BLEND);
177
+ auto shader = font_texture_atlas.getType () == FontFaceType::MSDF
178
+ ? sdf_shader
179
+ : default_shader;
180
+ if (&tex != bound_tex || shader != bound_shader) {
181
+ flush ();
182
+ }
183
+ uniforms.insert (uniforms.end (), SpriteBlock{transform});
184
+ bound_tex = &tex;
185
+ bound_shader = shader;
156
186
157
- std::vector<float > vertices;
158
- std::vector<GLuint> indices;
159
- GLuint i = 0 ;
187
+ GLuint i = verts;
160
188
for (auto & glyph : glyph_layout.getLayout ()) {
161
189
float gx = std::round (x + glyph.x );
162
190
float gy = std::round (y + glyph.y );
@@ -172,28 +200,16 @@ void OpenGLBatch::draw(
172
200
auto & region = region_result.get ();
173
201
174
202
vertices.insert (
175
- vertices.end (), {gx, gy, region.u0 , region.v0 , right, gy, region.u1 ,
176
- region.v0 , right, bottom, region.u1 , region.v1 , gx,
177
- bottom, region.u0 , region.v1 });
178
- indices.insert (indices.end (), {i, i + 1 , i + 2 , i + 2 , i + 3 , i});
203
+ vertices.end (),
204
+ {gx, gy, region.u0 , region.v0 , static_cast <GLfloat>(idx),
205
+ right, gy, region.u1 , region.v0 , static_cast <GLfloat>(idx),
206
+ right, bottom, region.u1 , region.v1 , static_cast <GLfloat>(idx),
207
+ gx, bottom, region.u0 , region.v1 , static_cast <GLfloat>(idx)});
208
+ elements.insert (elements.end (), {i, i + 1 , i + 2 , i + 2 , i + 3 , i});
179
209
i += 4 ;
210
+ verts = i;
180
211
}
181
-
182
- glBindBuffer (GL_ARRAY_BUFFER, vbo);
183
- glBufferData (
184
- GL_ARRAY_BUFFER, vertices.size () * sizeof (float ), vertices.data (),
185
- GL_STATIC_DRAW);
186
- glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, ebo);
187
- glBufferData (
188
- GL_ELEMENT_ARRAY_BUFFER, indices.size () * sizeof (GLuint),
189
- indices.data (), GL_STATIC_DRAW);
190
- if (font_texture_atlas.getType () == FontFaceType::MSDF) {
191
- sdf_shader->bind (color);
192
- } else {
193
- default_shader->bind (color);
194
- }
195
- glDrawElements (
196
- GL_TRIANGLES, static_cast <GLsizei>(indices.size ()), GL_UNSIGNED_INT, 0 );
212
+ idx++;
197
213
}
198
214
199
215
void OpenGLBatch::drawRect (
@@ -204,28 +220,45 @@ void OpenGLBatch::drawRect(
204
220
void OpenGLBatch::drawRect (
205
221
float x, float y, float width, float height, Shader& shader,
206
222
glm::mat4x4 transform) {
207
- glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
208
- glEnable (GL_BLEND);
209
- setTransform (transform);
223
+
224
+ auto & gl_shader = static_cast <OpenGLShader&>(shader);
225
+ uniforms.insert (uniforms.end (), SpriteBlock{transform});
226
+
227
+ if (bound_tex || bound_shader != &gl_shader) {
228
+ flush ();
229
+ }
230
+ bound_shader = &gl_shader;
210
231
211
232
float right = x + width;
212
233
float bottom = y + height;
213
- float quad_vertex_data[] = {
214
- x, y, 0 .0f , 0 .0f , // Top-left
215
- right, y, 1 .0f , 0 .0f , // Top-right
216
- right, bottom, 1 .0f , 1 .0f , // Bottom-right
217
- x, bottom, 0 .0f , 1 .0f // Bottom-left
218
- };
219
- GLuint elements[] = {0 , 1 , 2 , 2 , 3 , 0 };
220
- glBindBuffer (GL_ARRAY_BUFFER, vbo);
221
- glBufferData (
222
- GL_ARRAY_BUFFER, sizeof (quad_vertex_data), quad_vertex_data,
223
- GL_STATIC_DRAW);
224
- glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, ebo);
225
- glBufferData (
226
- GL_ELEMENT_ARRAY_BUFFER, sizeof (elements), elements, GL_STATIC_DRAW);
227
- static_cast <OpenGLShader&>(shader).bind (color);
228
- glDrawElements (GL_TRIANGLES, 6 , GL_UNSIGNED_INT, 0 );
234
+ vertices.insert (
235
+ vertices.end (), {
236
+ x,
237
+ y,
238
+ 0 .0f ,
239
+ 0 .0f ,
240
+ static_cast <GLfloat>(idx), // Top-left
241
+ right,
242
+ y,
243
+ 1 .0f ,
244
+ 0 .0f ,
245
+ static_cast <GLfloat>(idx), // Top-right
246
+ right,
247
+ bottom,
248
+ 1 .0f ,
249
+ 1 .0f ,
250
+ static_cast <GLfloat>(idx), // Bottom-right
251
+ x,
252
+ bottom,
253
+ 0 .0f ,
254
+ 1 .0f ,
255
+ static_cast <GLfloat>(idx) // Bottom-left
256
+ });
257
+ elements.insert (
258
+ elements.end (),
259
+ {verts, verts + 1 , verts + 2 , verts + 2 , verts + 3 , verts});
260
+ verts += 4 ;
261
+ idx++;
229
262
}
230
263
231
264
int OpenGLBatch::getTargetWidth () {
@@ -235,3 +268,46 @@ int OpenGLBatch::getTargetWidth() {
235
268
int OpenGLBatch::getTargetHeight () {
236
269
return height;
237
270
}
271
+
272
+ void OpenGLBatch::flush () {
273
+ if (!idx) {
274
+ return ;
275
+ }
276
+
277
+ glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
278
+ glEnable (GL_BLEND);
279
+
280
+ glBindBuffer (GL_ARRAY_BUFFER, vbo);
281
+ glBufferData (
282
+ GL_ARRAY_BUFFER, vertices.size () * sizeof (GLfloat), vertices.data (),
283
+ GL_STATIC_DRAW);
284
+ glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, ebo);
285
+ glBufferData (
286
+ GL_ELEMENT_ARRAY_BUFFER, elements.size () * sizeof (GLuint),
287
+ elements.data (), GL_STATIC_DRAW);
288
+
289
+ if (uniforms.size ()) {
290
+ glBindBuffer (GL_UNIFORM_BUFFER, ubo);
291
+ glBufferSubData (
292
+ GL_UNIFORM_BUFFER, sizeof (glm::mat4),
293
+ sizeof (SpriteBlock) * uniforms.size (), uniforms.data ());
294
+ glBindBuffer (GL_UNIFORM_BUFFER, 0 );
295
+ }
296
+
297
+ if (bound_tex) {
298
+ bound_tex->bind ();
299
+ }
300
+ if (bound_shader) {
301
+ bound_shader->bind (color);
302
+ }
303
+
304
+ glDrawElements (GL_TRIANGLES, elements.size (), GL_UNSIGNED_INT, 0 );
305
+
306
+ idx = 0 ;
307
+ verts = 0 ;
308
+ vertices.clear ();
309
+ elements.clear ();
310
+ uniforms.clear ();
311
+ bound_tex = nullptr ;
312
+ bound_shader = nullptr ;
313
+ }
0 commit comments