render3d/overlay: the font atlas kept as its coverage, one byte a texel
The atlas is white glyphs on alpha and the overlay reads only the coverage, but it was uploaded RGBA8: Maroon Lake's 3072 x 2688 atlas was 43 MB of Metal memory with its mips, the largest single thing in the launcher window. overlay_font now keeps the alpha alone as R8 (ov_font_tex; any other PNG shape is uploaded as before) and overlay.frag reads .r - the white fallback texture reads 1 there as it did from .a. Launcher window, graphics regions: the atlas 43.0 -> 11.5 MB; process footprint at 25 s 402 -> 378 MB. The headless launcher shot is identical to the unchanged build's (0 pixels differ; two unchanged runs differ from each other by 1.69%, and the new one by the same against them). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
2bb7ae1883
commit
db7c21e5d8
4 changed files with 26 additions and 3 deletions
|
|
@ -67,6 +67,29 @@ function overlay_init(render3d_st: mut Render3dState, font_dir: string) -> bool
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# The atlas is white glyphs on alpha, and the overlay reads only the coverage: it is kept as one
|
||||||
|
# byte a texel (R8). As RGBA a 3072 x 2688 atlas was 44 MB with its mips, the most of any UI texture.
|
||||||
|
@alloc_ok("loading a font: a load, not a frame")
|
||||||
|
function ov_font_tex(render3d_st: mut Render3dState, path: string) -> int {
|
||||||
|
let px = png_decode(render3d_st, path)
|
||||||
|
if px == null { return 0 }
|
||||||
|
if render3d_st.tex_channels != 4 or render3d_st.tex_depth != 8 {
|
||||||
|
let id0 = tex_upload(render3d_st, px, false, true)
|
||||||
|
free(px)
|
||||||
|
tex_note_size(render3d_st, id0)
|
||||||
|
return id0
|
||||||
|
}
|
||||||
|
let n = render3d_st.tex_w * render3d_st.tex_h
|
||||||
|
let a = bytes(n)
|
||||||
|
for i in 0 .. n { a[i] = px[i * 4 + 3] }
|
||||||
|
free(px)
|
||||||
|
render3d_st.tex_channels = 1
|
||||||
|
let id = tex_upload(render3d_st, a, false, true)
|
||||||
|
free(a)
|
||||||
|
tex_note_size(render3d_st, id)
|
||||||
|
return id
|
||||||
|
}
|
||||||
|
|
||||||
# Load (or swap to) the font atlas in `font_dir`: font.png and font.json. A game calls it
|
# Load (or swap to) the font atlas in `font_dir`: font.png and font.json. A game calls it
|
||||||
# again to change fonts at run time - a language whose script the default atlas does not
|
# again to change fonts at run time - a language whose script the default atlas does not
|
||||||
# carry brings its own. Returns false, and keeps the font it had, if there is none there.
|
# carry brings its own. Returns false, and keeps the font it had, if there is none there.
|
||||||
|
|
@ -74,7 +97,7 @@ function overlay_init(render3d_st: mut Render3dState, font_dir: string) -> bool
|
||||||
function overlay_font(render3d_st: mut Render3dState, font_dir: string) -> bool {
|
function overlay_font(render3d_st: mut Render3dState, font_dir: string) -> bool {
|
||||||
let meta = Fs.read_text(font_dir + "/font.json")
|
let meta = Fs.read_text(font_dir + "/font.json")
|
||||||
if meta == null { return false }
|
if meta == null { return false }
|
||||||
let tex = tex_load_ex(render3d_st, font_dir + "/font.png", false, 0)
|
let tex = ov_font_tex(render3d_st, font_dir + "/font.png")
|
||||||
if tex == 0 { return false }
|
if tex == 0 { return false }
|
||||||
let j = Json.parse(meta)
|
let j = Json.parse(meta)
|
||||||
render3d_st.ov_font_cols = jint(j, "cols", 16); render3d_st.ov_font_rows = jint(j, "rows", 6)
|
render3d_st.ov_font_cols = jint(j, "cols", 16); render3d_st.ov_font_rows = jint(j, "rows", 6)
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// 2D overlay: an image texture, the font atlas (white glyphs on alpha) or a flat colour, times a
|
// 2D overlay: an image texture, the font atlas (glyph coverage, R8) or a flat colour, times a
|
||||||
// colour. Which one is the vertex's own: v carries 4 x the mode (0 image, 1 font, 2 flat) on top of
|
// colour. Which one is the vertex's own: v carries 4 x the mode (0 image, 1 font, 2 flat) on top of
|
||||||
// its real coordinate, so text, panels and an image's quads share a draw (overlay.ludic, ov_use_tex).
|
// its real coordinate, so text, panels and an image's quads share a draw (overlay.ludic, ov_use_tex).
|
||||||
in vec2 v_uv;
|
in vec2 v_uv;
|
||||||
|
|
@ -27,7 +27,7 @@ void main() {
|
||||||
if (mode > 1.5) {
|
if (mode > 1.5) {
|
||||||
o_color = v_col;
|
o_color = v_col;
|
||||||
} else if (mode > 0.5) {
|
} else if (mode > 0.5) {
|
||||||
o_color = vec4(v_col.rgb, v_col.a * texture(u_font, uv).a);
|
o_color = vec4(v_col.rgb, v_col.a * texture(u_font, uv).r); // the atlas is its coverage alone (R8)
|
||||||
} else {
|
} else {
|
||||||
vec4 t = texture(u_tex, uv);
|
vec4 t = texture(u_tex, uv);
|
||||||
o_color = vec4(v_col.rgb * t.rgb, v_col.a * t.a);
|
o_color = vec4(v_col.rgb * t.rgb, v_col.a * t.a);
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue