diff options
| author | skal <pascal.massimino@gmail.com> | 2026-03-08 11:48:31 +0100 |
|---|---|---|
| committer | skal <pascal.massimino@gmail.com> | 2026-03-08 11:48:31 +0100 |
| commit | c43addd93191db1ed3e79af7e065004f7c52bf48 (patch) | |
| tree | 21b3eca6e37536ef8bd55d1b61f07d1d6bd1b58a | |
| parent | ba7ea27ddee4398afa98a0e45b9e227bbcfae906 (diff) | |
feat: extend debug_print with full ASCII and debug_str()
- Replace _dbg_pixel() with _dbg_char(ascii, r, c) covering
printable ASCII 0x20-0x7E (95 glyphs, C64-style 8x8 bitmaps)
- Update debug_f32() to use ASCII codes directly
- Add debug_str(col, pos, origin, s: vec4u, len) for rendering
up to 16 chars packed 4-per-u32 big-endian
handoff(Claude): debug_print now supports full ASCII strings.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
| -rw-r--r-- | src/shaders/debug/debug_print.wgsl | 284 |
1 files changed, 250 insertions, 34 deletions
diff --git a/src/shaders/debug/debug_print.wgsl b/src/shaders/debug/debug_print.wgsl index ee9b107..22b5838 100644 --- a/src/shaders/debug/debug_print.wgsl +++ b/src/shaders/debug/debug_print.wgsl @@ -1,41 +1,222 @@ -// Debug print utility: renders a f32 value at a pixel position using 8×8 C64 font. +// Debug print utility: renders f32 values and ASCII strings using an 8×8 C64-style font. // Include: #include "debug/debug_print" // // Usage: // col = debug_f32(col, pos.xy, vec2f(10.0, 10.0), my_value); +// col = debug_str(col, pos.xy, vec2f(10.0, 20.0), vec4u(0x48454C4Cu, 0x4F000000u, 0u, 0u), 5u); // -// Format: [-]DDD.DDD (8 chars × 8px wide = 64×8 pixel area) -// Range: -999.999 to 999.999 +// debug_f32 format : [-]DDD.DDD (8 chars × 8px wide = 64×8 pixel area) +// range -999.999 to 999.999 +// debug_str format : up to 16 printable ASCII chars packed in a vec4u +// each component holds 4 chars (MSB = leftmost char) +// e.g. "Hi!" -> vec4u(0x48692100u, 0u, 0u, 0u), 3u -// Returns the lit pixel (0 or 1) for glyph g, pixel row r [0-7], column c [0-7]. -// Glyphs: 0-9 = digits, 10 = '-', 11 = '.', 12 = ' ' +// Returns lit pixel (0 or 1) for ASCII code [0x20-0x7E], row r [0-7], col c [0-7]. // Encoding: 2 u32s per glyph; hi covers rows 0-3, lo covers rows 4-7. -// Within each u32, row r occupies bits [(3-r%4)*8 + 7 : (3-r%4)*8]. -fn _dbg_pixel(g: u32, r: u32, c: u32) -> u32 { - let data = array<u32, 26>( - 0x3C666E76u, 0x66663C00u, // '0' - 0x18381818u, 0x18187E00u, // '1' - 0x3C66060Cu, 0x18307E00u, // '2' - 0x3C66061Cu, 0x06663C00u, // '3' - 0x0C1C2C4Cu, 0x7E0C0C00u, // '4' - 0x7E607C06u, 0x06663C00u, // '5' - 0x1C30607Cu, 0x66663C00u, // '6' - 0x7E060C18u, 0x18181800u, // '7' - 0x3C66663Cu, 0x66663C00u, // '8' - 0x3C66663Eu, 0x060C3800u, // '9' - 0x0000007Eu, 0x00000000u, // '-' - 0x00000000u, 0x00181800u, // '.' - 0x00000000u, 0x00000000u, // ' ' +// Within each u32, row r occupies bits [(3-r%4)*8+7 : (3-r%4)*8]. +fn _dbg_char(ascii: u32, r: u32, c: u32) -> u32 { + let idx = (clamp(ascii, 0x20u, 0x7Eu) - 0x20u) * 2u; + let data = array<u32, 190>( + // 0x20 ' ' + 0x00000000u, 0x00000000u, + // 0x21 '!' + 0x18181818u, 0x00180000u, + // 0x22 '"' + 0x66660000u, 0x00000000u, + // 0x23 '#' + 0x36367F36u, 0x7F363600u, + // 0x24 '$' + 0x183E603Cu, 0x067C1800u, + // 0x25 '%' + 0x62660C18u, 0x30664600u, + // 0x26 '&' + 0x386C6876u, 0xDCCC7600u, + // 0x27 "'" + 0x18183000u, 0x00000000u, + // 0x28 '(' + 0x0C183030u, 0x30180C00u, + // 0x29 ')' + 0x30180C0Cu, 0x0C183000u, + // 0x2A '*' + 0x00663CFFu, 0x3C660000u, + // 0x2B '+' + 0x0018187Eu, 0x18180000u, + // 0x2C ',' + 0x00000000u, 0x00181830u, + // 0x2D '-' + 0x0000007Eu, 0x00000000u, + // 0x2E '.' + 0x00000000u, 0x00181800u, + // 0x2F '/' + 0x00060C18u, 0x30600000u, + // 0x30 '0' + 0x3C666E76u, 0x66663C00u, + // 0x31 '1' + 0x18381818u, 0x18187E00u, + // 0x32 '2' + 0x3C66060Cu, 0x18307E00u, + // 0x33 '3' + 0x3C66061Cu, 0x06663C00u, + // 0x34 '4' + 0x0C1C2C4Cu, 0x7E0C0C00u, + // 0x35 '5' + 0x7E607C06u, 0x06663C00u, + // 0x36 '6' + 0x1C30607Cu, 0x66663C00u, + // 0x37 '7' + 0x7E060C18u, 0x18181800u, + // 0x38 '8' + 0x3C66663Cu, 0x66663C00u, + // 0x39 '9' + 0x3C66663Eu, 0x060C3800u, + // 0x3A ':' + 0x00181800u, 0x00181800u, + // 0x3B ';' + 0x00181800u, 0x00181830u, + // 0x3C '<' + 0x0E183060u, 0x30180E00u, + // 0x3D '=' + 0x00007E00u, 0x007E0000u, + // 0x3E '>' + 0x70180C06u, 0x0C187000u, + // 0x3F '?' + 0x3C66060Cu, 0x18001800u, + // 0x40 '@' + 0x3C666E6Au, 0x6E603C00u, + // 0x41 'A' + 0x183C6666u, 0x7E666600u, + // 0x42 'B' + 0x7C66667Cu, 0x66667C00u, + // 0x43 'C' + 0x3C666060u, 0x60663C00u, + // 0x44 'D' + 0x786C6666u, 0x666C7800u, + // 0x45 'E' + 0x7E60607Cu, 0x60607E00u, + // 0x46 'F' + 0x7E60607Cu, 0x60606000u, + // 0x47 'G' + 0x3C66606Eu, 0x66663C00u, + // 0x48 'H' + 0x6666667Eu, 0x66666600u, + // 0x49 'I' + 0x3C181818u, 0x18183C00u, + // 0x4A 'J' + 0x1E0C0C0Cu, 0x0C6C3800u, + // 0x4B 'K' + 0x666C7870u, 0x786C6600u, + // 0x4C 'L' + 0x60606060u, 0x60607E00u, + // 0x4D 'M' + 0xC6EEFED6u, 0xC6C6C600u, + // 0x4E 'N' + 0x66767E6Eu, 0x66666600u, + // 0x4F 'O' + 0x3C666666u, 0x66663C00u, + // 0x50 'P' + 0x7C66667Cu, 0x60606000u, + // 0x51 'Q' + 0x3C666666u, 0x663C0E00u, + // 0x52 'R' + 0x7C66667Cu, 0x786C6600u, + // 0x53 'S' + 0x3C66603Cu, 0x06663C00u, + // 0x54 'T' + 0x7E181818u, 0x18181800u, + // 0x55 'U' + 0x66666666u, 0x66663C00u, + // 0x56 'V' + 0x66666666u, 0x663C1800u, + // 0x57 'W' + 0xC6C6C6D6u, 0xFEEEC600u, + // 0x58 'X' + 0x66663C18u, 0x3C666600u, + // 0x59 'Y' + 0x6666663Cu, 0x18181800u, + // 0x5A 'Z' + 0x7E060C18u, 0x30607E00u, + // 0x5B '[' + 0x3C303030u, 0x30303C00u, + // 0x5C '\' + 0x00603018u, 0x0C060000u, + // 0x5D ']' + 0x3C0C0C0Cu, 0x0C0C3C00u, + // 0x5E '^' + 0x10386CC6u, 0x00000000u, + // 0x5F '_' + 0x00000000u, 0x000000FFu, + // 0x60 '`' + 0x30180C00u, 0x00000000u, + // 0x61 'a' + 0x00003C06u, 0x3E663E00u, + // 0x62 'b' + 0x60607C66u, 0x66667C00u, + // 0x63 'c' + 0x00003C66u, 0x60663C00u, + // 0x64 'd' + 0x06063E66u, 0x66663E00u, + // 0x65 'e' + 0x00003C66u, 0x7E603C00u, + // 0x66 'f' + 0x0E18187Cu, 0x18181800u, + // 0x67 'g' + 0x00003E66u, 0x663E063Cu, + // 0x68 'h' + 0x60607C66u, 0x66666600u, + // 0x69 'i' + 0x18003818u, 0x18183C00u, + // 0x6A 'j' + 0x06000606u, 0x0606663Cu, + // 0x6B 'k' + 0x6060666Cu, 0x786C6600u, + // 0x6C 'l' + 0x38181818u, 0x18183C00u, + // 0x6D 'm' + 0x0000C6EEu, 0xFED6C600u, + // 0x6E 'n' + 0x00007C66u, 0x66666600u, + // 0x6F 'o' + 0x00003C66u, 0x66663C00u, + // 0x70 'p' + 0x00007C66u, 0x667C6060u, + // 0x71 'q' + 0x00003E66u, 0x663E0606u, + // 0x72 'r' + 0x00007C66u, 0x60606000u, + // 0x73 's' + 0x00003C60u, 0x3C063C00u, + // 0x74 't' + 0x18187E18u, 0x18180E00u, + // 0x75 'u' + 0x00006666u, 0x66663E00u, + // 0x76 'v' + 0x00006666u, 0x663C1800u, + // 0x77 'w' + 0x0000C6C6u, 0xD6FE6C00u, + // 0x78 'x' + 0x0000663Cu, 0x183C6600u, + // 0x79 'y' + 0x00006666u, 0x663E063Cu, + // 0x7A 'z' + 0x00007E0Cu, 0x18307E00u, + // 0x7B '{' + 0x0E181870u, 0x18180E00u, + // 0x7C '|' + 0x18181818u, 0x18181800u, + // 0x7D '}' + 0x7018180Eu, 0x18187000u, + // 0x7E '~' + 0x76DC0000u, 0x00000000u, ); - let word = data[g * 2u + (r / 4u)]; + let word = data[idx + (r / 4u)]; let shift = (3u - (r % 4u)) * 8u + (7u - c); return (word >> shift) & 1u; } -// Overlays printed value onto col, returning updated RGB. +// Overlays a f32 value onto col, returning updated RGB. // pixel_pos : @builtin(position).xy // origin : top-left corner of text in screen pixels -// value : f32 to display +// value : f32 to display (format: [-]DDD.DDD, 64×8 px) fn debug_f32(col: vec3f, pixel_pos: vec2f, origin: vec2f, value: f32) -> vec3f { let ink_color = vec3f(1.0, 1.0, 0.0); // yellow let lp = pixel_pos - origin; @@ -52,16 +233,51 @@ fn debug_f32(col: vec3f, pixel_pos: vec2f, origin: vec2f, value: f32) -> vec3f { let int_part = u32(abs_val); let frac_s = min(u32((abs_val - f32(int_part)) * 1000.0 + 0.5), 999u); - var g: u32; + var ascii: u32; switch char_col { - case 0u: { g = select(12u, 10u, neg); } // sign - case 1u: { g = (int_part / 100u) % 10u; } // hundreds - case 2u: { g = (int_part / 10u) % 10u; } // tens - case 3u: { g = int_part % 10u; } // ones - case 4u: { g = 11u; } // '.' - case 5u: { g = (frac_s / 100u) % 10u; } // tenths - case 6u: { g = (frac_s / 10u) % 10u; } // hundredths - default: { g = frac_s % 10u; } // thousandths + case 0u: { ascii = select(0x20u, 0x2Du, neg); } // ' ' or '-' + case 1u: { ascii = 0x30u + (int_part / 100u) % 10u; } // hundreds + case 2u: { ascii = 0x30u + (int_part / 10u) % 10u; } // tens + case 3u: { ascii = 0x30u + int_part % 10u; } // ones + case 4u: { ascii = 0x2Eu; } // '.' + case 5u: { ascii = 0x30u + (frac_s / 100u) % 10u; } // tenths + case 6u: { ascii = 0x30u + (frac_s / 10u) % 10u; } // hundredths + default: { ascii = 0x30u + frac_s % 10u; } // thousandths } - return mix(col, ink_color, f32(_dbg_pixel(g, iy, bit_col))); + return mix(col, ink_color, f32(_dbg_char(ascii, iy, bit_col))); +} + +// Overlays an ASCII string onto col, returning updated RGB. +// pixel_pos : @builtin(position).xy +// origin : top-left corner of text in screen pixels +// s : up to 16 chars packed as 4 bytes per u32, big-endian +// s.x = chars 0-3, s.y = chars 4-7, s.z = chars 8-11, s.w = chars 12-15 +// len : number of characters to render (1-16) +// +// Example — "Hello" (5 chars, ASCII 0x48 0x65 0x6C 0x6C 0x6F): +// debug_str(col, pos.xy, origin, vec4u(0x48656C6Cu, 0x6F000000u, 0u, 0u), 5u) +fn debug_str(col: vec3f, pixel_pos: vec2f, origin: vec2f, s: vec4u, len: u32) -> vec3f { + let ink_color = vec3f(1.0, 1.0, 0.0); // yellow + let lp = pixel_pos - origin; + let max_w = f32(len * 8u); + if (lp.x < 0.0 || lp.x >= max_w || lp.y < 0.0 || lp.y >= 8.0) { + return col; + } + let ix = u32(lp.x); + let iy = u32(lp.y); + let char_idx = ix / 8u; + let bit_col = ix % 8u; + + // Extract byte from packed vec4u (big-endian: MSB = leftmost char) + let word_idx = char_idx / 4u; + let byte_pos = 3u - (char_idx % 4u); // shift in bytes within the u32 + var packed: u32; + switch word_idx { + case 0u: { packed = s.x; } + case 1u: { packed = s.y; } + case 2u: { packed = s.z; } + default: { packed = s.w; } + } + let ascii = (packed >> (byte_pos * 8u)) & 0xFFu; + return mix(col, ink_color, f32(_dbg_char(ascii, iy, bit_col))); } |
