Optimize glyph calculation
This commit is contained in:
+79
-87
@@ -3,11 +3,11 @@ package e2glyph
|
||||
/*
|
||||
Provides text rendering using glfw, stb_truetype for the engine
|
||||
|
||||
TODO:
|
||||
Optimize for only calculate when there's changes
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
import "core:math"
|
||||
import os "core:os"
|
||||
import "core:mem"
|
||||
@@ -52,16 +52,10 @@ GlyphState :: struct {
|
||||
}
|
||||
|
||||
|
||||
glyph_init :: proc(glyph: ^GlyphState) {
|
||||
glyph_init :: proc(glyph: ^GlyphState, filepath : string) {
|
||||
|
||||
ok : bool
|
||||
glyph.program_id, ok = gl.load_shaders_source(
|
||||
#load("./shaders/font_vert.glsl"),
|
||||
#load("./shaders/font_frag.glsl"),
|
||||
)
|
||||
|
||||
//gl.UseProgram(glyph.program_id)
|
||||
|
||||
glyph.program_id, ok = gl.load_shaders_source(#load("./shaders/font_vert.glsl"), #load("./shaders/font_frag.glsl"), )
|
||||
|
||||
gl.CreateBuffers(1, &glyph.rect_instances_vbo)
|
||||
gl.CreateVertexArrays(1, &glyph.vao)
|
||||
@@ -88,19 +82,7 @@ glyph_init :: proc(glyph: ^GlyphState) {
|
||||
gl.CreateTextures(gl.TEXTURE_RECTANGLE, 1, &glyph.atlas_texture)
|
||||
gl.TextureStorage2D(glyph.atlas_texture, 1, gl.RGB8, glyph.atlas_width, glyph.atlas_height)
|
||||
|
||||
|
||||
/*
|
||||
gl.BindVertexArray(0)
|
||||
gl.BindBuffer(gl.ARRAY_BUFFER, 0)
|
||||
gl.BindTexture(gl.TEXTURE_RECTANGLE, 0)
|
||||
gl.BindTexture(gl.TEXTURE_2D, 0)
|
||||
gl.DisableVertexArrayAttrib(glyph.vao, 0)
|
||||
gl.DisableVertexArrayAttrib(glyph.vao, 1)
|
||||
gl.DisableVertexArrayAttrib(glyph.vao, 2)
|
||||
gl.DisableVertexArrayAttrib(glyph.vao, 3)
|
||||
*/
|
||||
|
||||
font_data, _ := os.read_entire_file_from_path("./Ubuntu-Regular.ttf", context.allocator)
|
||||
font_data, _ := os.read_entire_file_from_path(filepath, context.allocator)
|
||||
|
||||
stbtt.InitFont(&glyph.font_info, &font_data[0], 0)
|
||||
|
||||
@@ -160,92 +142,103 @@ glyph_draw_font :: proc(glyph_state: ^GlyphState, text: string, pos : [2]f32, co
|
||||
glyph_state.curr.x += 2 * glyph_state.font_size_pt
|
||||
} else {
|
||||
|
||||
|
||||
horizontal_filter_padding, subpixel_positioning_left_padding: i32 = 1, 1
|
||||
assert(codepoint <= 127)
|
||||
glyph_atlas := glyph_state.atlas_items[codepoint]
|
||||
|
||||
glyph_index := stbtt.FindGlyphIndex(&glyph_state.font_info, c)
|
||||
|
||||
x0, y0, x1, y1: i32 = 0, 0, 0, 0
|
||||
|
||||
stbtt.GetGlyphBitmapBox(&glyph_state.font_info, glyph_index, font_scale, font_scale, &x0, &y0, &x1, &y1)
|
||||
|
||||
glyph_width_px : i32 = x1 - x0
|
||||
glyph_height_px: i32 = y1 - y0
|
||||
|
||||
distance_from_baseline_to_top_px: i32 = -y0
|
||||
|
||||
if glyph_width_px > 0 && glyph_height_px > 0
|
||||
if !glyph_atlas.filled
|
||||
{
|
||||
padded_glyph_width_px : i32 = subpixel_positioning_left_padding + horizontal_filter_padding + glyph_width_px + horizontal_filter_padding
|
||||
padded_glyph_height_px: i32 = glyph_height_px
|
||||
glyph_index := stbtt.FindGlyphIndex(&glyph_state.font_info, c)
|
||||
|
||||
atlas_item_width, atlas_item_height: i32 = 32, 32
|
||||
x0, y0, x1, y1: i32 = 0, 0, 0, 0
|
||||
|
||||
atlas_item_x: i32 = i32( codepoint % u32(glyph_state.atlas_width / atlas_item_width), ) * atlas_item_width
|
||||
atlas_item_y: i32 = i32( codepoint / u32(glyph_state.atlas_height / atlas_item_height), ) * atlas_item_height
|
||||
stbtt.GetGlyphBitmapBox(&glyph_state.font_info, glyph_index, font_scale, font_scale, &x0, &y0, &x1, &y1)
|
||||
|
||||
assert(padded_glyph_width_px <= atlas_item_width && padded_glyph_height_px <= atlas_item_height)
|
||||
glyph_width_px : i32 = x1 - x0
|
||||
glyph_height_px: i32 = y1 - y0
|
||||
|
||||
horizontal_resolution: i32 = 3
|
||||
bitmap_stride : i32 = atlas_item_width * horizontal_resolution
|
||||
bitmap_size : uint = uint(bitmap_stride * atlas_item_height)
|
||||
glyph_bitmap, _ := mem.alloc_bytes(int(bitmap_size))
|
||||
glyph_offset_x := (subpixel_positioning_left_padding + horizontal_filter_padding) * horizontal_resolution
|
||||
distance_from_baseline_to_top_px: i32 = -y0
|
||||
|
||||
stbtt.MakeGlyphBitmap(&glyph_state.font_info, &glyph_bitmap[glyph_offset_x], atlas_item_width * horizontal_resolution, atlas_item_height, bitmap_stride, font_scale * f32(horizontal_resolution), font_scale, glyph_index)
|
||||
|
||||
atlas_item_bitmap, _ := mem.alloc_bytes(int(bitmap_size))
|
||||
|
||||
filter_weights: [5]u8 = {0x08, 0x4D, 0x56, 0x4D, 0x08}
|
||||
|
||||
for y in 0 ..< padded_glyph_height_px
|
||||
if glyph_width_px > 0 && glyph_height_px > 0
|
||||
{
|
||||
padded_glyph_width_px : i32 = subpixel_positioning_left_padding + horizontal_filter_padding + glyph_width_px + horizontal_filter_padding
|
||||
padded_glyph_height_px: i32 = glyph_height_px
|
||||
|
||||
x_end: i32 = padded_glyph_width_px * horizontal_resolution - 1
|
||||
atlas_item_width, atlas_item_height: i32 = 32, 32
|
||||
|
||||
for x in 4 ..< x_end {
|
||||
filter_weight_index: i32 = 0
|
||||
sum: i32
|
||||
kernel_x_end: i32 = (x == x_end - 1) ? x + 1 : x + 2
|
||||
atlas_item_x: i32 = i32( codepoint % u32(glyph_state.atlas_width / atlas_item_width), ) * atlas_item_width
|
||||
atlas_item_y: i32 = i32( codepoint / u32(glyph_state.atlas_height / atlas_item_height), ) * atlas_item_height
|
||||
|
||||
for kernel_x in x - 2 ..= kernel_x_end
|
||||
{
|
||||
assert(kernel_x >= 0 && kernel_x < x_end + 1)
|
||||
assert(y >= 0 && y < padded_glyph_height_px)
|
||||
assert(padded_glyph_width_px <= atlas_item_width && padded_glyph_height_px <= atlas_item_height)
|
||||
|
||||
offset: i32 = kernel_x + y * bitmap_stride
|
||||
assert(offset >= 0 && uint(offset) < bitmap_size)
|
||||
horizontal_resolution: i32 = 3
|
||||
bitmap_stride : i32 = atlas_item_width * horizontal_resolution
|
||||
bitmap_size : uint = uint(bitmap_stride * atlas_item_height)
|
||||
glyph_bitmap, _ := mem.alloc_bytes(int(bitmap_size))
|
||||
glyph_offset_x := (subpixel_positioning_left_padding + horizontal_filter_padding) * horizontal_resolution
|
||||
|
||||
sum += i32(i32(glyph_bitmap[offset]) * i32(filter_weights[filter_weight_index]))
|
||||
stbtt.MakeGlyphBitmap(
|
||||
&glyph_state.font_info,
|
||||
&glyph_bitmap[glyph_offset_x],
|
||||
atlas_item_width * horizontal_resolution,
|
||||
atlas_item_height, bitmap_stride,
|
||||
font_scale * f32(horizontal_resolution),
|
||||
font_scale, glyph_index
|
||||
)
|
||||
|
||||
filter_weight_index += 1
|
||||
atlas_item_bitmap, _ := mem.alloc_bytes(int(bitmap_size))
|
||||
|
||||
filter_weights: [5]u8 = {0x08, 0x4D, 0x56, 0x4D, 0x08}
|
||||
|
||||
for y in 0 ..< padded_glyph_height_px
|
||||
{
|
||||
|
||||
x_end: i32 = padded_glyph_width_px * horizontal_resolution - 1
|
||||
|
||||
for x in 4 ..< x_end {
|
||||
filter_weight_index: i32 = 0
|
||||
sum: i32
|
||||
kernel_x_end: i32 = (x == x_end - 1) ? x + 1 : x + 2
|
||||
|
||||
for kernel_x in x - 2 ..= kernel_x_end
|
||||
{
|
||||
assert(kernel_x >= 0 && kernel_x < x_end + 1)
|
||||
assert(y >= 0 && y < padded_glyph_height_px)
|
||||
|
||||
offset: i32 = kernel_x + y * bitmap_stride
|
||||
assert(offset >= 0 && uint(offset) < bitmap_size)
|
||||
|
||||
sum += i32(i32(glyph_bitmap[offset]) * i32(filter_weights[filter_weight_index]))
|
||||
|
||||
filter_weight_index += 1
|
||||
}
|
||||
sum = sum / 255
|
||||
atlas_item_bitmap[x + y * bitmap_stride] = (sum > 255) ? 255 : u8(sum)
|
||||
}
|
||||
sum = sum / 255
|
||||
atlas_item_bitmap[x + y * bitmap_stride] = (sum > 255) ? 255 : u8(sum)
|
||||
}
|
||||
|
||||
mem.free_bytes(glyph_bitmap)
|
||||
gl.TextureSubImage2D(glyph_state.atlas_texture, 0, atlas_item_x, atlas_item_y, atlas_item_width, atlas_item_height, gl.RGB, gl.UNSIGNED_BYTE, rawptr(&atlas_item_bitmap[0]))
|
||||
|
||||
mem.free_bytes(atlas_item_bitmap)
|
||||
glyph_atlas.tex_coords.l = f32(atlas_item_x)
|
||||
glyph_atlas.tex_coords.t = f32(atlas_item_y)
|
||||
glyph_atlas.tex_coords.r = f32(atlas_item_x + padded_glyph_width_px)
|
||||
glyph_atlas.tex_coords.b = f32(atlas_item_y + padded_glyph_height_px)
|
||||
} else {
|
||||
glyph_atlas.tex_coords.l = -1
|
||||
glyph_atlas.tex_coords.t = -1
|
||||
glyph_atlas.tex_coords.r = -1
|
||||
glyph_atlas.tex_coords.b = -1
|
||||
}
|
||||
|
||||
mem.free_bytes(glyph_bitmap)
|
||||
gl.TextureSubImage2D(glyph_state.atlas_texture, 0, atlas_item_x, atlas_item_y, atlas_item_width, atlas_item_height, gl.RGB, gl.UNSIGNED_BYTE, rawptr(&atlas_item_bitmap[0]))
|
||||
|
||||
mem.free_bytes(atlas_item_bitmap)
|
||||
glyph_atlas.tex_coords.l = f32(atlas_item_x)
|
||||
glyph_atlas.tex_coords.t = f32(atlas_item_y)
|
||||
glyph_atlas.tex_coords.r = f32(atlas_item_x + padded_glyph_width_px)
|
||||
glyph_atlas.tex_coords.b = f32(atlas_item_y + padded_glyph_height_px)
|
||||
} else {
|
||||
glyph_atlas.tex_coords.l = -1
|
||||
glyph_atlas.tex_coords.t = -1
|
||||
glyph_atlas.tex_coords.r = -1
|
||||
glyph_atlas.tex_coords.b = -1
|
||||
glyph_atlas.index = glyph_index
|
||||
glyph_atlas.distance_b2t = distance_from_baseline_to_top_px
|
||||
glyph_atlas.filled = true
|
||||
glyph_state.atlas_items[codepoint] = glyph_atlas
|
||||
}
|
||||
|
||||
glyph_atlas.index = glyph_index
|
||||
glyph_atlas.distance_b2t = distance_from_baseline_to_top_px
|
||||
glyph_atlas.filled = true
|
||||
glyph_state.atlas_items[codepoint] = glyph_atlas
|
||||
|
||||
glyph_advance_width, glyph_left_side_bearing: i32 = 0, 0
|
||||
|
||||
stbtt.GetGlyphHMetrics(&glyph_state.font_info, glyph_atlas.index, &glyph_advance_width, &glyph_left_side_bearing)
|
||||
@@ -274,7 +267,6 @@ glyph_draw_font :: proc(glyph_state: ^GlyphState, text: string, pos : [2]f32, co
|
||||
r.color = text_color
|
||||
r.index = u32(i + 1)
|
||||
|
||||
|
||||
append(&glyph_state.rect_buffer, r)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user