summaryrefslogtreecommitdiff
path: root/source/renderer/renderer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/renderer/renderer.cpp')
-rw-r--r--source/renderer/renderer.cpp246
1 files changed, 246 insertions, 0 deletions
diff --git a/source/renderer/renderer.cpp b/source/renderer/renderer.cpp
index ad75eca..14a7d56 100644
--- a/source/renderer/renderer.cpp
+++ b/source/renderer/renderer.cpp
@@ -366,3 +366,249 @@ void gl_line_flush(GLRenderer *renderer) {
array_clear(&renderer->line_color_batch);
renderer->line_batch_count = 0;
}
+
+void gl_setup_text(TextState *uistate) {
+ uistate->scale = stbtt_ScaleForPixelHeight(&uistate->font, uistate->pixel_size);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+
+ glGenTextures(1, &(uistate->texture_atlas_id));
+ glBindTexture(GL_TEXTURE_2D_ARRAY, uistate->texture_atlas_id);
+
+ // generate texture
+ glTexImage3D(
+ GL_TEXTURE_2D_ARRAY,
+ 0,
+ GL_R8,
+ uistate->pixel_size,
+ uistate->pixel_size,
+ 128,
+ 0,
+ GL_RED,
+ GL_UNSIGNED_BYTE,
+ 0);
+
+ // font vmetrics
+ s32 ascent, descent, linegap = 0;
+ stbtt_GetFontVMetrics(&uistate->font, &ascent, &descent, &linegap);
+ uistate->ascent = ascent;
+ uistate->descent = descent;
+ uistate->linegap = linegap;
+
+ // font bounding box
+ s32 x0, y0, x1, y1 = 0;
+ stbtt_GetFontBoundingBox(&uistate->font, &x0, &y0, &x1, &y1);
+ uistate->bbox0 = IVec2{x0, y0};
+ uistate->bbox1 = IVec2{x1, y1};
+
+ // generate bitmaps
+ u32 pixel_size = uistate->pixel_size;
+ unsigned char *bitmap_buffer = (unsigned char*)calloc(pixel_size * pixel_size, sizeof(unsigned char));
+ for (u32 c = 0; c < 128; c++)
+ {
+ s32 advance, lsb = 0;
+ stbtt_GetCodepointHMetrics(&uistate->font, c, &advance, &lsb);
+ s32 bx0, bx1, by0, by1 = 0;
+ stbtt_GetCodepointBitmapBox(
+ &uistate->font, c,
+ uistate->scale, uistate->scale,
+ &bx0, &by0,
+ &bx1, &by1
+ );
+
+ s32 width = bx1 - bx0;
+ s32 height = by1 - by0;
+
+ stbtt_MakeCodepointBitmap(
+ &uistate->font,
+ bitmap_buffer,
+ width,
+ height,
+ width,
+ uistate->scale,
+ uistate->scale,
+ c);
+
+ glTexSubImage3D(
+ GL_TEXTURE_2D_ARRAY,
+ 0,
+ 0, 0, // x, y offset
+ int(c),
+ width,
+ height,
+ 1,
+ GL_RED,
+ GL_UNSIGNED_BYTE,
+ bitmap_buffer
+ );
+ // set texture options
+ glTexParameteri(
+ GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE
+ );
+ glTexParameteri(
+ GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE
+ );
+ glTexParameteri(
+ GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR
+ );
+ glTexParameteri(
+ GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR
+ );
+
+ TextChar tc;
+ tc.size = Vec2{
+ (r32)width, (r32)height
+ };
+ tc.bbox0 = Vec2{
+ (r32)bx0, (r32)by0
+ };
+ tc.bbox1 = Vec2{
+ (r32)bx1, (r32)by1
+ };
+ tc.advance = advance;
+ tc.lsb = (s32)lsb;
+ uistate->char_map[c] = tc;
+ }
+
+ glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
+
+ r32 vertices[] = {
+ 0.0f, 1.0f,
+ 0.0f, 0.0f,
+ 1.0f, 1.0f,
+ 1.0f, 0.0f
+ };
+
+ glGenVertexArrays(1, &(uistate->vao));
+ glGenBuffers(1, &(uistate->vbo));
+
+ glBindVertexArray(uistate->vao);
+ glBindBuffer(GL_ARRAY_BUFFER, uistate->vbo);
+ glBufferData(
+ GL_ARRAY_BUFFER,
+ sizeof(vertices),
+ vertices,
+ GL_STATIC_DRAW);
+
+ glEnableVertexAttribArray(0);
+ glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glBindVertexArray(0);
+}
+
+void gl_render_text(
+ GLRenderer *renderer,
+ char *text,
+ Vec2 position,
+ Vec3 color,
+ r32 font_size) {
+ // render_text
+ glDisable(GL_DEPTH_TEST);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ glUseProgram(renderer->ui_text.sp);
+ if (renderer->ui_cam_update) {
+
+ glUniformMatrix4fv(
+ glGetUniformLocation(
+ renderer->ui_text.sp, "View"),
+ 1, GL_FALSE, renderer->ui_cam_view.buffer);
+
+ glUniformMatrix4fv(
+ glGetUniformLocation(
+ renderer->ui_text.sp, "Projection"),
+ 1, GL_FALSE, renderer->cam_proj.buffer);
+
+ renderer->ui_cam_update = 0;
+ }
+ glUniform3fv(
+ glGetUniformLocation(
+ renderer->ui_text.sp, "TextColor"),
+ 1, color.data);
+ glBindVertexArray(renderer->ui_text.vao);
+ glBindTexture(
+ GL_TEXTURE_2D_ARRAY,
+ renderer->ui_text.texture_atlas_id);
+ glBindBuffer(GL_ARRAY_BUFFER, renderer->ui_text.vbo);
+ glActiveTexture(GL_TEXTURE0);
+
+ u32 running_index = 0;
+ r32 startx = position.x;
+ r32 starty = position.y;
+ r32 linex = startx;
+ r32 liney = starty;
+ r32 render_scale = font_size/(r32)renderer->ui_text.pixel_size;
+ r32 font_scale = renderer->ui_text.scale*render_scale;
+ memset(renderer->ui_text.transforms, 0, renderer->ui_text.chunk_size);
+ memset(renderer->ui_text.char_indexes, 0, renderer->ui_text.chunk_size);
+
+ char *char_iter = text;
+ r32 baseline = -renderer->ui_text.bbox0.y*font_scale - font_size;
+ while (*char_iter != '\0') {
+ TextChar render_char = renderer->ui_text.char_map[*char_iter];
+ if (*char_iter == ' ') {
+ linex += (font_scale * render_char.advance);
+ char_iter++;
+ continue;
+ }
+ if (*char_iter == '\t') {
+ linex += (font_scale * render_char.advance);
+ char_iter++;
+ continue;
+ }
+ if (*char_iter == '\n') {
+ linex = startx;
+ liney = liney - font_scale * (renderer->ui_text.ascent - renderer->ui_text.descent + renderer->ui_text.linegap);
+ char_iter++;
+ continue;
+ }
+ r32 xpos = linex + (font_scale * render_char.lsb);
+ r32 ypos = liney + (baseline - render_scale*render_char.bbox0.y);
+
+ Mat4 sc = scaling_matrix4m(font_size, font_size, 1.0f);
+ Mat4 tr = translation_matrix4m(xpos, ypos, 0);
+ Mat4 model = multiply4m(tr, sc);
+ renderer->ui_text.transforms[running_index] = model;
+ renderer->ui_text.char_indexes[running_index] =
+ int(*char_iter);
+
+ linex += (font_scale * render_char.advance);
+ char prev_char = *char_iter;
+ char_iter++;
+ char curr_char = *char_iter;
+
+ if (curr_char) {
+ s32 kern = font_scale * stbtt_GetCodepointKernAdvance(&renderer->ui_text.font, prev_char, curr_char);
+ linex += kern;
+ }
+ running_index++;
+ if (running_index >= renderer->ui_text.chunk_size) {
+ gl_text_flush(renderer, running_index);
+ running_index = 0;
+ }
+ }
+ gl_text_flush(renderer, running_index);
+}
+
+void gl_text_flush(GLRenderer *renderer, u32 render_count) {
+ s32 transform_loc = glGetUniformLocation(
+ renderer->ui_text.sp, "LetterTransforms");
+ glUniformMatrix4fv(
+ transform_loc,
+ render_count,
+ GL_FALSE,
+ &(renderer->ui_text.transforms[0].buffer[0])
+ );
+
+ s32 texture_map_loc = glGetUniformLocation(
+ renderer->ui_text.sp, "TextureMap");
+ glUniform1iv(
+ texture_map_loc,
+ render_count,
+ renderer->ui_text.char_indexes);
+
+ glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, render_count);
+
+ memset(renderer->ui_text.transforms, 0, render_count);
+ memset(renderer->ui_text.char_indexes, 0, render_count);
+}