From 87bc31636e5878dc72caeaed33c448ddf3542989 Mon Sep 17 00:00:00 2001 From: Ed_ Date: Fri, 14 Jun 2024 17:00:06 -0400 Subject: [PATCH] lots of corrections to VEFontCache, still no letters on screen Something is either wrong with the sokol_gfx rendering setup or its a really dumb checkbox/uv value --- code/font/VEFontCache/VEFontCache.odin | 35 ++++++++++-------- code/font/VEFontCache/atlas.odin | 10 +++--- code/font/VEFontCache/draw.odin | 44 +++++++++++------------ code/sectr/engine/render_vefc.odin | 14 ++++++-- code/sectr/font/provider_VEFontCache.odin | 37 +++++++++++-------- 5 files changed, 80 insertions(+), 60 deletions(-) diff --git a/code/font/VEFontCache/VEFontCache.odin b/code/font/VEFontCache/VEFontCache.odin index cfd4468..2aff1eb 100644 --- a/code/font/VEFontCache/VEFontCache.odin +++ b/code/font/VEFontCache/VEFontCache.odin @@ -179,8 +179,8 @@ InitAtlasParams :: struct { } InitAtlasParams_Default :: InitAtlasParams { - width = 4 * Kilobyte, - height = 2 * Kilobyte, + width = 4096, + height = 2048, glyph_padding = 1, region_a = { @@ -265,38 +265,43 @@ init :: proc( ctx : ^Context, parser_kind : ParserKind, draw_list.calls, error = make( Array(DrawCall), 512 ) assert(error == .None, "VEFontCache.init : Failed to allocate draw_list.calls") - init_atlas_region :: proc( region : ^AtlasRegion, params : InitAtlasParams, region_params : InitAtlasRegionParams ) { + init_atlas_region :: proc( region : ^AtlasRegion, params : InitAtlasParams, region_params : InitAtlasRegionParams, factor : Vec2i, expected_cap : u32 ) { using region next_idx = 0; width = region_params.width height = region_params.height size = { - params.width / 4, - params.height / 2, + params.width / factor.x, + params.height / factor.y, } capacity = { size.x / width, size.y / height, } + assert( capacity.x * capacity.y == expected_cap ) error : AllocatorError // state.cache, error = make( HMapChained(LRU_Link), uint(capacity.x * capacity.y) ) // assert( error == .None, "VEFontCache.init_atlas_region : Failed to allocate state.cache") LRU_init( & state, capacity.x * capacity.y ) } - init_atlas_region( & atlas.region_a, atlas_params, atlas_params.region_a ) - init_atlas_region( & atlas.region_b, atlas_params, atlas_params.region_b ) - init_atlas_region( & atlas.region_c, atlas_params, atlas_params.region_c ) - init_atlas_region( & atlas.region_d, atlas_params, atlas_params.region_d ) + init_atlas_region( & atlas.region_a, atlas_params, atlas_params.region_a, { 4, 2}, 1024 ) + init_atlas_region( & atlas.region_b, atlas_params, atlas_params.region_b, { 4, 2}, 512 ) + init_atlas_region( & atlas.region_c, atlas_params, atlas_params.region_c, { 4, 1}, 512 ) + init_atlas_region( & atlas.region_d, atlas_params, atlas_params.region_d, { 2, 1}, 256 ) atlas.width = atlas_params.width atlas.height = atlas_params.height atlas.glyph_padding = atlas_params.glyph_padding + atlas.region_a.offset = {0, 0} + atlas.region_b.offset.x = 0 atlas.region_b.offset.y = atlas.region_a.size.y atlas.region_c.offset.x = atlas.region_a.size.x + atlas.region_c.offset.y = 0 atlas.region_d.offset.x = atlas.width / 2 + atlas.region_d.offset.y = 0 LRU_init( & shape_cache.state, shape_cache_params.capacity ) @@ -476,7 +481,7 @@ cache_glyph :: proc( ctx : ^Context, font : FontID, glyph_index : Glyph, scale, f32(bounds_0.x) - 21, f32(bounds_0.y) - 33, } - + // Note(Original Author): Figure out scaling so it fits within our box. draw := DrawCall_Default draw.pass = FrameBufferPass.Glyph @@ -601,7 +606,7 @@ cache_glyph_to_atlas :: proc( ctx : ^Context, font : FontID, glyph_index : Glyph // Draw oversized glyph to update FBO glyph_draw_scale := over_sample * entry.size_scale - glyph_draw_translate := Vec2 { f32(bounds_0.x), f32(bounds_0.y) } * glyph_draw_scale + Vec2{ glyph_padding, glyph_padding } + glyph_draw_translate := Vec2 { f32(-bounds_0.x), f32(-bounds_0.y) } * glyph_draw_scale + Vec2{ glyph_padding, glyph_padding } glyph_draw_translate.x = cast(f32) (i32(glyph_draw_translate.x + 0.9999999)) glyph_draw_translate.y = cast(f32) (i32(glyph_draw_translate.y + 0.9999999)) @@ -613,16 +618,16 @@ cache_glyph_to_atlas :: proc( ctx : ^Context, font : FontID, glyph_index : Glyph // Calculate the src and destination regions dst_position, dst_width, dst_height := atlas_bbox( atlas, region_kind, u32(atlas_index) ) - dst_glyph_position := dst_position //+ { glyph_padding, glyph_padding } + dst_glyph_position := dst_position + { glyph_padding, glyph_padding } dst_glyph_width := f32(bounds_width) * entry.size_scale dst_glyph_height := f32(bounds_height) * entry.size_scale - // dst_glyph_position -= { glyph_padding, glyph_padding } + dst_glyph_position -= { glyph_padding, glyph_padding } dst_glyph_width += 2 * glyph_padding dst_glyph_height += 2 * glyph_padding dst_size := Vec2 { dst_width, dst_height } dst_glyph_size := Vec2 { dst_glyph_width, dst_glyph_height } - screenspace_x_form( & dst_glyph_position, & dst_glyph_size, f32(atlas.width), f32(atlas.height) ) + screenspace_x_form( & dst_glyph_position, & dst_glyph_size, f32(atlas.width), f32(atlas.height) ) screenspace_x_form( & dst_position, & dst_size, f32(atlas.width), f32(atlas.height) ) src_position := Vec2 { f32(atlas.update_batch_x), 0 } @@ -652,7 +657,7 @@ cache_glyph_to_atlas :: proc( ctx : ^Context, font : FontID, glyph_index : Glyph // Queue up a blit from glyph_update_FBO to the atlas region = .None start_index = u32(atlas.draw_list.indices.num) - blit_quad( & atlas.draw_list, dst_glyph_position, dst_glyph_position + dst_glyph_size, src_position, src_position + src_size ) + blit_quad( & atlas.draw_list, dst_glyph_position, dst_position + dst_glyph_size, src_position, src_position + src_size ) end_index = u32(atlas.draw_list.indices.num) append( & atlas.draw_list.calls, call ) } diff --git a/code/font/VEFontCache/atlas.odin b/code/font/VEFontCache/atlas.odin index f6ec96c..a178b54 100644 --- a/code/font/VEFontCache/atlas.odin +++ b/code/font/VEFontCache/atlas.odin @@ -36,7 +36,7 @@ atlas_bbox :: proc( atlas : ^Atlas, region : AtlasRegionKind, local_idx : u32 ) height = f32(atlas.region_b.height) position.x = cast(f32) (( local_idx % atlas.region_a.capacity.x ) * atlas.region_a.width) - position.y = cast(f32) (( local_idx % atlas.region_a.capacity.x ) * atlas.region_a.height) + position.y = cast(f32) (( local_idx / atlas.region_a.capacity.x ) * atlas.region_a.height) position.x += f32(atlas.region_a.offset.x) position.y += f32(atlas.region_a.offset.y) @@ -46,7 +46,7 @@ atlas_bbox :: proc( atlas : ^Atlas, region : AtlasRegionKind, local_idx : u32 ) height = f32(atlas.region_b.height) position.x = cast(f32) (( local_idx % atlas.region_b.capacity.x ) * atlas.region_b.width) - position.y = cast(f32) (( local_idx % atlas.region_b.capacity.x ) * atlas.region_b.height) + position.y = cast(f32) (( local_idx / atlas.region_b.capacity.x ) * atlas.region_b.height) position.x += f32(atlas.region_b.offset.x) position.y += f32(atlas.region_b.offset.y) @@ -56,7 +56,7 @@ atlas_bbox :: proc( atlas : ^Atlas, region : AtlasRegionKind, local_idx : u32 ) height = f32(atlas.region_c.height) position.x = cast(f32) (( local_idx % atlas.region_c.capacity.x ) * atlas.region_c.width) - position.y = cast(f32) (( local_idx % atlas.region_c.capacity.x ) * atlas.region_c.height) + position.y = cast(f32) (( local_idx / atlas.region_c.capacity.x ) * atlas.region_c.height) position.x += f32(atlas.region_c.offset.x) position.y += f32(atlas.region_c.offset.y) @@ -66,7 +66,7 @@ atlas_bbox :: proc( atlas : ^Atlas, region : AtlasRegionKind, local_idx : u32 ) height = f32(atlas.region_d.height) position.x = cast(f32) (( local_idx % atlas.region_d.capacity.x ) * atlas.region_d.width) - position.y = cast(f32) (( local_idx % atlas.region_d.capacity.x ) * atlas.region_d.height) + position.y = cast(f32) (( local_idx / atlas.region_d.capacity.x ) * atlas.region_d.height) position.x += f32(atlas.region_d.offset.x) position.y += f32(atlas.region_d.offset.y) @@ -140,7 +140,7 @@ decide_codepoint_region :: proc( ctx : ^Context, entry : ^Entry, glyph_index : G region_kind = .A region = & atlas.region_a } - else if bounds_width_scaled <= atlas.region_b.width && bounds_height_scaled <= atlas.region_b.height + else if bounds_width_scaled <= atlas.region_a.width && bounds_height_scaled <= atlas.region_a.height { // Region B for tall glyphs. These are good for things such as european alphabets. region_kind = .B diff --git a/code/font/VEFontCache/draw.odin b/code/font/VEFontCache/draw.odin index b025fd8..6b4e2aa 100644 --- a/code/font/VEFontCache/draw.odin +++ b/code/font/VEFontCache/draw.odin @@ -44,32 +44,33 @@ GlyphDrawBuffer :: struct { draw_list : DrawList, } -blit_quad :: proc( draw_list : ^DrawList, p0, p1 : Vec2, uv0, uv1 : Vec2 ) +blit_quad :: proc( draw_list : ^DrawList, p0 : Vec2 = {0, 0}, p1 : Vec2 = {1, 1}, uv0 : Vec2 = {0, 0}, uv1 : Vec2 = {1, 1} ) { + // logf("Blitting: xy0: %0.2f, %0.2f xy1: %0.2f, %0.2f uv0: %0.2f, %0.2f uv1: %0.2f, %0.2f", + // p0.x, p0.y, p1.x, p1.y, uv0.x, uv0.y, uv1.x, uv1.y); v_offset := cast(u32) draw_list.vertices.num vertex := Vertex { {p0.x, p0.y}, - uv0.x, - uv0.y + uv0.x, uv0.y } append( & draw_list.vertices, vertex ) + vertex = Vertex { {p0.x, p1.y}, - uv0.x, - uv1.y + uv0.x, uv1.y } append( & draw_list.vertices, vertex ) + vertex = Vertex { {p1.x, p0.y}, - uv1.x, - uv0.y + uv1.x, uv0.y } append( & draw_list.vertices, vertex ) + vertex = Vertex { {p1.x, p1.y}, - uv1.x, - uv1.y + uv1.x, uv1.y } append( & draw_list.vertices, vertex ) @@ -112,6 +113,8 @@ directly_draw_massive_glyph :: proc( ctx : ^Context, entry : ^Entry, glyph : Gly glyph_dst_height := f32(bounds_height) * entry.size_scale glyph_width += f32(2 * ctx.atlas.glyph_padding) glyph_height += f32(2 * ctx.atlas.glyph_padding) + glyph_dst_width += f32(2 * ctx.atlas.glyph_padding) + glyph_dst_height += f32(2 * ctx.atlas.glyph_padding) // Figure out the destination rect. bounds_scaled := Vec2 { @@ -150,7 +153,7 @@ directly_draw_massive_glyph :: proc( ctx : ^Context, entry : ^Entry, glyph : Gly draw_cached_glyph :: proc( ctx : ^Context, entry : ^Entry, glyph_index : Glyph, position, scale : Vec2 ) -> b32 { // Glyph not in current font - if glyph_index == 0 do return true + if glyph_index == 0 do return true if parser_is_glyph_empty( & entry.parser_info, glyph_index ) do return true bounds_0, bounds_1 := parser_get_glyph_box( & entry.parser_info, glyph_index ) @@ -190,7 +193,7 @@ draw_cached_glyph :: proc( ctx : ^Context, entry : ^Entry, glyph_index : Glyph, glyph_scale := Vec2 { glyph_width, glyph_height } bounds_0_scaled := Vec2{ f32(bounds_0.x), f32(bounds_0.y) } * entry.size_scale - { 0.5, 0.5 } - bounds_0_scaled = { + bounds_0_scaled = { cast(f32) cast(i32) bounds_0_scaled.x, cast(f32) cast(i32) bounds_0_scaled.y, } @@ -208,7 +211,7 @@ draw_cached_glyph :: proc( ctx : ^Context, entry : ^Entry, glyph_index : Glyph, call := DrawCall_Default { using call - pass = .Target_Uncached + pass = .Target colour = ctx.colour start_index = cast(u32) ctx.draw_list.indices.num @@ -305,7 +308,6 @@ draw_text :: proc( ctx : ^Context, font : FontID, text_utf8 : string, position : cache_glyph_to_atlas( ctx, font, glyph_index ) - // lru_code := u64(glyph_index) + ( ( 0x100000000 * u64(font) ) & 0xFFFFFFFF00000000 ) lru_code := font_glyph_lru_code(font, glyph_index) set( ctx.temp_codepoint_seen, lru_code, true ) ctx.temp_codepoint_seen_num += 1 @@ -315,8 +317,7 @@ draw_text :: proc( ctx : ^Context, font : FontID, text_utf8 : string, position : draw_text_batch( ctx, entry, shaped, batch_start_idx, i32(shaped.glyphs.num), position, scale ) reset_batch_codepoint_state( ctx ) - ctx.cursor_pos.x = position.x + shaped.end_cursor_pos.x * scale.x - ctx.cursor_pos.y = position.y + shaped.end_cursor_pos.y * scale.y + ctx.cursor_pos = position + shaped.end_cursor_pos * scale return true } @@ -328,7 +329,6 @@ draw_text_batch :: proc( ctx : ^Context, entry : ^Entry, shaped : ^ShapedText, b { glyph_index := shaped.glyphs.data[ index ] shaped_position := shaped.positions.data[index] - // glyph_translate_x := position.x + shaped_position.x * scale.x glyph_translate := position + shaped_position * scale glyph_cached := draw_cached_glyph( ctx, entry, glyph_index, glyph_translate, scale) assert( glyph_cached == true ) @@ -375,12 +375,12 @@ merge_draw_list :: proc( dst, src : ^DrawList ) error : AllocatorError v_offset := cast(u32) dst.vertices.num - // for index : u32 = 0; index < cast(u32) src.vertices.num; index += 1 { - // error = append( & dst.vertices, src.vertices.data[index] ) - // assert( error == .None ) - // } - error = append( & dst.vertices, src.vertices ) - assert( error == .None ) + for index : u32 = 0; index < cast(u32) src.vertices.num; index += 1 { + error = append( & dst.vertices, src.vertices.data[index] ) + assert( error == .None ) + } + // error = append( & dst.vertices, src.vertices ) + // assert( error == .None ) i_offset := cast(u32) dst.indices.num for index : u32 = 0; index < cast(u32) src.indices.num; index += 1 { diff --git a/code/sectr/engine/render_vefc.odin b/code/sectr/engine/render_vefc.odin index 48bc593..9bb7448 100644 --- a/code/sectr/engine/render_vefc.odin +++ b/code/sectr/engine/render_vefc.odin @@ -210,10 +210,18 @@ render :: proc() sokol_gfx.apply_pipeline( screen_pipeline ) - fs_uniform := Ve_Draw_Text_Fs_Params { down_sample = 0, colour = {1, 1, 1, 1} } - sokol_gfx.apply_uniforms( ShaderStage.FS, SLOT_ve_blit_atlas_fs_params, Range { & fs_uniform, size_of(fs_uniform) }) + src_rt := atlas_rt_color - src_rt := draw_call.pass == .Target_Uncached ? glyph_rt_color : atlas_rt_color + fs_uniform := Ve_Draw_Text_Fs_Params { + // down_sample = draw_call.pass == .Target_Uncached ? 1 : 0, + colour = {1, 1, 1, 1}, + } + + if draw_call.pass == .Target_Uncached { + fs_uniform.down_sample = 1 + src_rt = glyph_rt_color + } + sokol_gfx.apply_uniforms( ShaderStage.FS, SLOT_ve_blit_atlas_fs_params, Range { & fs_uniform, size_of(fs_uniform) }) sokol_gfx.apply_bindings(Bindings { vertex_buffers = { diff --git a/code/sectr/font/provider_VEFontCache.odin b/code/sectr/font/provider_VEFontCache.odin index 2efd944..93191c5 100644 --- a/code/sectr/font/provider_VEFontCache.odin +++ b/code/sectr/font/provider_VEFontCache.odin @@ -183,6 +183,7 @@ font_provider_startup :: proc() pixel_format = .DEPTH, // compare = .ALWAYS, }, + cull_mode = .NONE, // sample_count = 1, // label = }) @@ -200,7 +201,7 @@ font_provider_startup :: proc() num_mipmaps = 1, usage = .IMMUTABLE, pixel_format = .R8, - sample_count = app_env.defaults.sample_count, + sample_count = 1, // TODO(Ed): Setup labels for debug tracing/logging // label = }) @@ -215,7 +216,7 @@ font_provider_startup :: proc() num_mipmaps = 1, usage = .IMMUTABLE, pixel_format = .DEPTH, - sample_count = app_env.defaults.sample_count, + sample_count = 1, }) color_attach := AttachmentDesc { @@ -236,10 +237,10 @@ font_provider_startup :: proc() glyph_action := PassAction { colors = { 0 = { - load_action = .CLEAR, + load_action = .LOAD, store_action = .STORE, - clear_value = {0.01,0.01,0.01,1}, - // clear_value = {0.00, 0.00, 0.00, 0.00}, + // clear_value = {0.01,0.01,0.01,1}, + clear_value = {0.00, 0.00, 0.00, 0.00}, } } } @@ -298,6 +299,7 @@ font_provider_startup :: proc() pixel_format = .DEPTH, compare = .ALWAYS, }, + cull_mode = .NONE, // sample_count = 1, }) } @@ -307,13 +309,13 @@ font_provider_startup :: proc() atlas_rt_color = sokol_gfx.make_image( ImageDesc { type = ._2D, render_target = true, - width = i32(ve_font_cache.atlas.buffer_width), - height = i32(ve_font_cache.atlas.buffer_height), + width = i32(ve_font_cache.atlas.width), + height = i32(ve_font_cache.atlas.height), num_slices = 1, num_mipmaps = 1, usage = .IMMUTABLE, pixel_format = .R8, - sample_count = app_env.defaults.sample_count, + sample_count = 1, // TODO(Ed): Setup labels for debug tracing/logging // label = }) @@ -322,13 +324,13 @@ font_provider_startup :: proc() atlas_rt_depth = sokol_gfx.make_image( ImageDesc { type = ._2D, render_target = true, - width = i32(ve_font_cache.atlas.buffer_width), - height = i32(ve_font_cache.atlas.buffer_height), + width = i32(ve_font_cache.atlas.width), + height = i32(ve_font_cache.atlas.height), num_slices = 1, num_mipmaps = 1, usage = .IMMUTABLE, pixel_format = .DEPTH, - sample_count = app_env.defaults.sample_count, + sample_count = 1, }) verify( sokol_gfx.query_image_state(atlas_rt_depth) < ResourceState.FAILED, "Failed to make atlas_rt_depth") @@ -352,7 +354,7 @@ font_provider_startup :: proc() 0 = { load_action = .LOAD, store_action = .STORE, - clear_value = {0,0,0,1.0}, + clear_value = {0, 0, 0, 0.0}, } } } @@ -386,7 +388,7 @@ font_provider_startup :: proc() } color_target := ColorTargetState { - // pixel_format = .R8, + pixel_format = app_env.defaults.color_format, // write_mask = blend = BlendState { enabled = true, @@ -408,6 +410,11 @@ font_provider_startup :: proc() }, color_count = 1, sample_count = 1, + depth = { + pixel_format = app_env.defaults.depth_format, + compare = .ALWAYS, + }, + cull_mode = .NONE, }) verify( sokol_gfx.query_pipeline_state(screen_pipeline) < ResourceState.FAILED, "Failed to make screen_pipeline" ) } @@ -417,9 +424,9 @@ font_provider_startup :: proc() screen_action := PassAction { colors = { 0 = { - load_action = .CLEAR, + load_action = .LOAD, store_action = .STORE, - clear_value = {1.0,0.0,0.0,1.0}, + clear_value = {0.0,0.0,0.0,0.0}, } } }