converted font to instanced rendering (much better now)
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 28 Oct 2020 22:06:44 +0000 (17:06 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 28 Oct 2020 22:06:44 +0000 (17:06 -0500)
res/shaders/font_frag.glsl
res/shaders/font_vert.glsl
src/ui.cpp

index 1738c0cb066e9d9787ef758d6b16822fa4609791..60f1fb008cfc951851ae275d17a8c26dfeb409b6 100644 (file)
@@ -2,13 +2,13 @@
 
 precision mediump float;
 
-in vec4 v_color;
 in vec2 v_texcoord;
 
+uniform vec4 u_color;
 uniform sampler2D u_texture;
 
 out vec4 fragColor;
 
 void main() {
-       fragColor = vec4(v_color.rgb, texture(u_texture, v_texcoord).a);
+       fragColor = vec4(u_color.rgb, u_color.a * texture(u_texture, v_texcoord).a);
 }
\ No newline at end of file
index a47319ec73f3c68bf7f62aaefc66a75e19700c63..4fa125a2c8d73e059aed75622e2785b9c5c06960 100644 (file)
@@ -2,18 +2,18 @@
 
 precision mediump float;
 
-layout(location = 0) in vec2 a_pos;
-layout(location = 1) in vec2 a_texcoord;
-layout(location = 2) in vec4 a_color;
+layout(location = 0) in vec2 a_interp;
+layout(location = 1) in vec2 a_pos_top_left;
+layout(location = 2) in vec2 a_pos_bottom_right;
+layout(location = 3) in vec2 a_texcoord_top_left;
+layout(location = 4) in vec2 a_texcoord_bottom_right;
 
-out vec4 v_color;
 out vec2 v_texcoord;
 
 uniform mat4 u_proj;
 
 void main() {
-       gl_Position = u_proj * vec4(a_pos, 0, 1);
+       gl_Position = u_proj * vec4(a_pos_top_left * a_interp + a_pos_bottom_right * (vec2(1.0, 1.0) - a_interp), 0, 1);
 
-       v_color = a_color;
-       v_texcoord = a_texcoord;
+       v_texcoord = a_texcoord_top_left * a_interp + a_texcoord_bottom_right * (vec2(1.0, 1.0) - a_interp);
 }
\ No newline at end of file
index 999134304b2e12da19c927ccd6e766e3caecf1a5..761ac011cffd2842f9ff9a88f6a57fbff07600fc 100644 (file)
@@ -10,8 +10,8 @@
 #define FONT_FIRST_CHAR ' '
 #define FONT_CHAR_COUNT 96
 
-// NOTE(Brendan): This limits the maximum string length of a message to be 128 chars.
-#define FONT_BUFFER_SIZE 4 * 8 * 6 * 128
+// NOTE(Brendan): This limits the maximum string length of a message to be 256 chars.
+#define FONT_BUFFER_SIZE sizeof(FontQuadVertex) * 256
 
 internal stbtt_packedchar *font_char_data;
 internal GLuint font_tex;
@@ -19,12 +19,14 @@ internal GLuint font_program;
 internal GLuint font_vao;
 internal GLuint font_buffer_data;
 internal GLuint font_proj_mat_loc;
+internal GLuint font_color_loc;
 
 struct FontQuadVertex
 {
-    V2f pos;
-    V2f tex;
-    struct { f32 r, g, b, a; } color;
+    V2f pos_top_left;
+    V2f pos_bottom_right;
+    V2f tex_top_left;
+    V2f tex_bottom_right;
 };
 
 void
@@ -58,7 +60,6 @@ init_font(const char* font_loc)
     glBindTexture(GL_TEXTURE_2D, font_tex);
     glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, FONT_INTERNAL_IMAGE_SIZE, FONT_INTERNAL_IMAGE_SIZE, 0, GL_ALPHA, GL_UNSIGNED_BYTE, font_pixels);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    // glBindTexture(GL_TEXTURE_2D, -1);
     
     free(font_pixels);
     
@@ -70,22 +71,48 @@ init_font(const char* font_loc)
     glUseProgram(font_program);
     
     font_proj_mat_loc = glGetUniformLocation(font_program, "u_proj");
+    font_color_loc = glGetUniformLocation(font_program, "u_color");
+    
     auto font_texture_loc = glGetUniformLocation(font_program, "u_texture");
     glUniform1i(font_texture_loc, 0);
     
     glGenVertexArrays(1, &font_vao);
     glBindVertexArray(font_vao);
     
+    GLuint font_interp_buffer;
+    glGenBuffers(1, &font_interp_buffer);
+    glBindBuffer(GL_ARRAY_BUFFER, font_interp_buffer);
+    V2f font_interp_data[4] =
+    {
+        V2f { 0.0, 0.0 },
+        V2f { 1.0, 0.0 },
+        V2f { 1.0, 1.0 },
+        V2f { 0.0, 1.0 },
+    };
+    glBufferData(GL_ARRAY_BUFFER, sizeof(font_interp_data), font_interp_data, GL_STATIC_DRAW);
+    glEnableVertexAttribArray(0);
+    glVertexAttribPointer(0, 2, GL_FLOAT, false, sizeof(V2f), (void *) 0);
+    
+    GLuint font_index_buffer;
+    glGenBuffers(1, &font_index_buffer);
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, font_index_buffer);
+    u8 font_index_data[6] = { 0, 1, 2, 0, 2, 3 };
+    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(font_index_data), font_index_data, GL_STATIC_DRAW);
+    
     glGenBuffers(1, &font_buffer_data);
     glBindBuffer(GL_ARRAY_BUFFER, font_buffer_data);
     glBufferData(GL_ARRAY_BUFFER, FONT_BUFFER_SIZE, nullptr, GL_STREAM_DRAW);
     
-    glEnableVertexAttribArray(0);
-    glEnableVertexAttribArray(1);
-    glEnableVertexAttribArray(2);
-    glVertexAttribPointer(0, 2, GL_FLOAT, false, sizeof(FontQuadVertex), (void *) offsetof(FontQuadVertex, pos));
-    glVertexAttribPointer(1, 2, GL_FLOAT, false, sizeof(FontQuadVertex), (void *) offsetof(FontQuadVertex, tex));
-    glVertexAttribPointer(2, 4, GL_FLOAT, false, sizeof(FontQuadVertex), (void *) offsetof(FontQuadVertex, color));
+    foreach (i, 1, 5)
+    {
+        glEnableVertexAttribArray(i);
+        glVertexAttribDivisor(i, 1);
+    }
+    glVertexAttribPointer(1, 2, GL_FLOAT, false, sizeof(FontQuadVertex), (void *) offsetof(FontQuadVertex, pos_top_left));
+    glVertexAttribPointer(2, 2, GL_FLOAT, false, sizeof(FontQuadVertex), (void *) offsetof(FontQuadVertex, pos_bottom_right));
+    glVertexAttribPointer(3, 2, GL_FLOAT, false, sizeof(FontQuadVertex), (void *) offsetof(FontQuadVertex, tex_top_left));
+    glVertexAttribPointer(4, 2, GL_FLOAT, false, sizeof(FontQuadVertex), (void *) offsetof(FontQuadVertex, tex_bottom_right));
+    
     glBindBuffer(GL_ARRAY_BUFFER, -1);
     
     glBindVertexArray(-1);
@@ -112,77 +139,24 @@ font_print(f32 x, f32 y, char* msg, f32 r, f32 g, f32 b, f32 a)
                             FONT_INTERNAL_IMAGE_SIZE, FONT_INTERNAL_IMAGE_SIZE,
                             *msg - FONT_FIRST_CHAR,
                             &x, &y, &quad, 0);
-        /* TOP LEFT */
-        quads[quad_num * 6 + 0].pos.x = quad.x0;
-        quads[quad_num * 6 + 0].pos.y = quad.y0;
-        quads[quad_num * 6 + 0].tex.x = quad.s0;
-        quads[quad_num * 6 + 0].tex.y = quad.t0;
-        quads[quad_num * 6 + 0].color.r = r;
-        quads[quad_num * 6 + 0].color.g = g;
-        quads[quad_num * 6 + 0].color.b = b;
-        quads[quad_num * 6 + 0].color.a = a;
-        
-        /* TOP RIGHT */
-        quads[quad_num * 6 + 1].pos.x = quad.x1;
-        quads[quad_num * 6 + 1].pos.y = quad.y0;
-        quads[quad_num * 6 + 1].tex.x = quad.s1;
-        quads[quad_num * 6 + 1].tex.y = quad.t0;
-        quads[quad_num * 6 + 1].color.r = r;
-        quads[quad_num * 6 + 1].color.g = g;
-        quads[quad_num * 6 + 1].color.b = b;
-        quads[quad_num * 6 + 1].color.a = a;
-        
-        /* BOTTOM RIGHT */
-        quads[quad_num * 6 + 2].pos.x = quad.x1;
-        quads[quad_num * 6 + 2].pos.y = quad.y1;
-        quads[quad_num * 6 + 2].tex.x = quad.s1;
-        quads[quad_num * 6 + 2].tex.y = quad.t1;
-        quads[quad_num * 6 + 2].color.r = r;
-        quads[quad_num * 6 + 2].color.g = g;
-        quads[quad_num * 6 + 2].color.b = b;
-        quads[quad_num * 6 + 2].color.a = a;
-        
-        /* TOP LEFT */
-        quads[quad_num * 6 + 3].pos.x = quad.x0;
-        quads[quad_num * 6 + 3].pos.y = quad.y0;
-        quads[quad_num * 6 + 3].tex.x = quad.s0;
-        quads[quad_num * 6 + 3].tex.y = quad.t0;
-        quads[quad_num * 6 + 3].color.r = r;
-        quads[quad_num * 6 + 3].color.g = g;
-        quads[quad_num * 6 + 3].color.b = b;
-        quads[quad_num * 6 + 3].color.a = a;
-        
-        /* BOTTOM RIGHT */
-        quads[quad_num * 6 + 4].pos.x = quad.x1;
-        quads[quad_num * 6 + 4].pos.y = quad.y1;
-        quads[quad_num * 6 + 4].tex.x = quad.s1;
-        quads[quad_num * 6 + 4].tex.y = quad.t1;
-        quads[quad_num * 6 + 4].color.r = r;
-        quads[quad_num * 6 + 4].color.g = g;
-        quads[quad_num * 6 + 4].color.b = b;
-        quads[quad_num * 6 + 4].color.a = a;
         
-        /* BOTTOM LEFT */
-        quads[quad_num * 6 + 5].pos.x = quad.x0;
-        quads[quad_num * 6 + 5].pos.y = quad.y1;
-        quads[quad_num * 6 + 5].tex.x = quad.s0;
-        quads[quad_num * 6 + 5].tex.y = quad.t1;
-        quads[quad_num * 6 + 5].color.r = r;
-        quads[quad_num * 6 + 5].color.g = g;
-        quads[quad_num * 6 + 5].color.b = b;
-        quads[quad_num * 6 + 5].color.a = a;
+        quads[quad_num].pos_top_left     = V2f { quad.x0, quad.y0 };
+        quads[quad_num].pos_bottom_right = V2f { quad.x1, quad.y1 };
+        quads[quad_num].tex_top_left     = V2f { quad.s0, quad.t0 };
+        quads[quad_num].tex_bottom_right = V2f { quad.s1, quad.t1 };
         
         msg++;
         quad_num++;
     }
     
     glBindBuffer(GL_ARRAY_BUFFER, font_buffer_data);
-    glBufferSubData(GL_ARRAY_BUFFER, 0, msg_len * 6 * sizeof(FontQuadVertex), quads);
+    glBufferSubData(GL_ARRAY_BUFFER, 0, msg_len * sizeof(FontQuadVertex), quads);
     glBindBuffer(GL_ARRAY_BUFFER, -1);
     
     glBindTexture(GL_TEXTURE_2D, font_tex);
     glUseProgram(font_program);
+    glUniform4f(font_color_loc, r, g, b, a);
     glBindVertexArray(font_vao);
-    glDrawArrays(GL_TRIANGLES, 0, 6 * msg_len);
+    glDrawElementsInstanced(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, (void *) 0, msg_len);
     glBindVertexArray(-1);
 }
\ No newline at end of file