diff options
| -rw-r--r-- | Fonts/Bitmaps/font-0.png.meta | 2 | ||||
| -rw-r--r-- | Fonts/Bitmaps/font-ascii.png | bin | 0 -> 543838 bytes | |||
| -rw-r--r-- | Fonts/Bitmaps/font-ascii.png.meta (renamed from Fonts/Bitmaps/emotes.png.meta) | 22 | ||||
| -rw-r--r-- | GUI/GUI/GUI/PythonWrapper.cpp | 52 | ||||
| -rw-r--r-- | Scripts/generate_fonts.py | 79 | ||||
| -rw-r--r-- | Scripts/generate_shader.py | 36 | ||||
| -rw-r--r-- | Shaders/TaSTT_lighting_template.cginc | 10 |
7 files changed, 144 insertions, 57 deletions
diff --git a/Fonts/Bitmaps/font-0.png.meta b/Fonts/Bitmaps/font-0.png.meta index c0e5ef9..b70fd04 100644 --- a/Fonts/Bitmaps/font-0.png.meta +++ b/Fonts/Bitmaps/font-0.png.meta @@ -28,7 +28,7 @@ TextureImporter: cubemapConvolution: 0 seamlessCubemap: 0 textureFormat: 1 - maxTextureSize: 2048 + maxTextureSize: 4096 textureSettings: serializedVersion: 2 filterMode: 1 diff --git a/Fonts/Bitmaps/font-ascii.png b/Fonts/Bitmaps/font-ascii.png Binary files differnew file mode 100644 index 0000000..1a8ba99 --- /dev/null +++ b/Fonts/Bitmaps/font-ascii.png diff --git a/Fonts/Bitmaps/emotes.png.meta b/Fonts/Bitmaps/font-ascii.png.meta index 1e794cb..c6d24ff 100644 --- a/Fonts/Bitmaps/emotes.png.meta +++ b/Fonts/Bitmaps/font-ascii.png.meta @@ -1,18 +1,18 @@ fileFormatVersion: 2 -guid: 054057c5bf512e842854e6746e754159 +guid: 0417deb9fee97e24e9099569bed34c6c TextureImporter: internalIDToNameTable: [] externalObjects: {} serializedVersion: 11 mipmaps: mipMapMode: 1 - enableMipMap: 0 + enableMipMap: 1 sRGBTexture: 1 linearTexture: 0 fadeOut: 0 borderMipMap: 0 mipMapsPreserveCoverage: 1 - alphaTestReferenceValue: 0.5 + alphaTestReferenceValue: 0 mipMapFadeDistanceStart: 1 mipMapFadeDistanceEnd: 3 bumpmap: @@ -21,22 +21,22 @@ TextureImporter: heightScale: 0.25 normalMapFilter: 0 isReadable: 0 - streamingMipmaps: 0 + streamingMipmaps: 1 streamingMipmapsPriority: 0 grayScaleToAlpha: 0 generateCubemap: 6 cubemapConvolution: 0 seamlessCubemap: 0 textureFormat: 1 - maxTextureSize: 2048 + maxTextureSize: 512 textureSettings: serializedVersion: 2 filterMode: 1 aniso: 1 mipBias: 0 - wrapU: 1 - wrapV: 1 - wrapW: 1 + wrapU: 0 + wrapV: 0 + wrapW: 0 nPOTScale: 1 lightmap: 0 compressionQuality: 100 @@ -61,7 +61,7 @@ TextureImporter: platformSettings: - serializedVersion: 3 buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 + maxTextureSize: 512 resizeAlgorithm: 1 textureFormat: -1 textureCompression: 2 @@ -73,7 +73,7 @@ TextureImporter: forceMaximumCompressionQuality_BC6H_BC7: 0 - serializedVersion: 3 buildTarget: Standalone - maxTextureSize: 2048 + maxTextureSize: 512 resizeAlgorithm: 1 textureFormat: -1 textureCompression: 2 @@ -85,7 +85,7 @@ TextureImporter: forceMaximumCompressionQuality_BC6H_BC7: 0 - serializedVersion: 3 buildTarget: Android - maxTextureSize: 2048 + maxTextureSize: 512 resizeAlgorithm: 1 textureFormat: -1 textureCompression: 2 diff --git a/GUI/GUI/GUI/PythonWrapper.cpp b/GUI/GUI/GUI/PythonWrapper.cpp index 0337072..f920a43 100644 --- a/GUI/GUI/GUI/PythonWrapper.cpp +++ b/GUI/GUI/GUI/PythonWrapper.cpp @@ -567,12 +567,16 @@ bool PythonWrapper::GenerateAnimator( std::filesystem::path tastt_animator_path = tastt_generated_dir_path / unity_animator_generated_name; + const int texture_rows = (config.bytes_per_char == 1 ? 8 : 64); + const int texture_cols = (config.bytes_per_char == 1 ? 16 : 128); { Log(out, "Generating shader for {}x{} board (pass 0)...", config.rows, config.cols); if (!InvokeWithArgs({ generate_shader_path, "--bytes_per_char", std::to_string(config.bytes_per_char), - "--rows", std::to_string(config.rows), - "--cols", std::to_string(config.cols), + "--board_rows", std::to_string(config.rows), + "--board_cols", std::to_string(config.cols), + "--texture_rows", std::to_string(texture_rows), + "--texture_cols", std::to_string(texture_cols), "--shader_template", shader_template_path, "--shader_path", shader_path }, "Failed to generate shader", out)) { @@ -585,14 +589,17 @@ bool PythonWrapper::GenerateAnimator( std::string py_stdout, py_stderr; if (!InvokeWithArgs({ generate_shader_path, "--bytes_per_char", std::to_string(config.bytes_per_char), - "--rows", std::to_string(config.rows), - "--cols", std::to_string(config.cols), + "--board_rows", std::to_string(config.rows), + "--board_cols", std::to_string(config.cols), + "--texture_rows", std::to_string(texture_rows), + "--texture_cols", std::to_string(texture_cols), "--shader_template", shader_lighting_template_path, "--shader_path", shader_lighting_path }, "Failed to generate shader", out)) { return false; } } +#if 0 { Log(out, "Generating emotes... "); @@ -622,6 +629,7 @@ bool PythonWrapper::GenerateAnimator( return false; } } +#endif { Log(out, "Creating {}\n", tastt_generated_dir_path.string()); std::filesystem::create_directories(tastt_generated_dir_path); @@ -682,6 +690,42 @@ bool PythonWrapper::GenerateAnimator( } Log(out, "success!\n"); } + if (config.bytes_per_char == 1) { + Log(out, "Applying texture memory optimization for English speakers... "); + std::error_code err; + for (int i = 0; i < 8; i++) { + std::filesystem::remove(tastt_fonts_path / ("Bitmaps/font-" + std::to_string(i) + ".png"), err); + if (err.value()) { + Log(out, "failed!\n"); + Log(out, "Error removing unicode texture: {} ({})\n", err.message(), err.value()); + return false; + } + if (i != 0) { + std::filesystem::remove(tastt_fonts_path / ("Bitmaps/font-" + std::to_string(i) + ".png.meta"), err); + if (err.value()) { + Log(out, "failed!\n"); + Log(out, "Error removing unicode texture metadata: {} ({})\n", err.message(), err.value()); + return false; + } + } + } + std::filesystem::remove(tastt_fonts_path / "Bitmaps/emotes.png", err); + if (err.value()) { + Log(out, "failed!\n"); + Log(out, "Error removing emotes texture: {} ({})\n", err.message(), err.value()); + return false; + } + + Log(out, "success!\n"); + } else { + std::error_code err; + if (!std::filesystem::remove(tastt_fonts_path / "Bitmaps/font-ascii.png.meta", err)) { + Log(out, "failed!\n"); + Log(out, "Error: {} ({})\n", err.message(), err.value()); + return false; + } + Log(out, "success!\n"); + } { Log(out, "Generating guid.map... "); if (!InvokeWithArgs({ libunity_path, "guid_map", diff --git a/Scripts/generate_fonts.py b/Scripts/generate_fonts.py index 931abfe..cf73e6a 100644 --- a/Scripts/generate_fonts.py +++ b/Scripts/generate_fonts.py @@ -114,36 +114,71 @@ def in_range(x, range_pair) -> bool: max_char = max(allowlist) print("max char: {}".format(max_char)) print("num chars: {}".format(len(allowlist))) -total_rows = math.ceil(max_char / n_cols) -print("total rows {}".format(total_rows)) -total_textures = math.ceil(total_rows / n_rows) -print("total textures {}".format(total_textures)) - -for nth_texture in range(0, total_textures): - # Create an 8K grayscale ("L") or black and white ("1") image - image = Image.new(mode="1", size=(8192,8192), color=0) + +def genUnicode(): + total_rows = math.ceil(max_char / n_cols) + print("total rows {}".format(total_rows)) + total_textures = math.ceil(total_rows / n_rows) + print("total textures {}".format(total_textures)) + + for nth_texture in range(0, total_textures): + # Create an 8K grayscale ("L") or black and white ("1") image + # Unity will re-encode b&w to grayscale, so using b&w just helps keep + # the package size low (we vendor these, we don't generate them + # client-side). + image = Image.new(mode="1", size=(8192,8192), color=0) + draw = ImageDraw.Draw(image) + + row_begin = nth_texture * n_rows + + for row in range(row_begin, row_begin + n_rows): + line = "" + for col in range(0, n_cols): + # Generate the unicode character for this spot. + n = row * n_cols + col + char = None + font_info = None + if n in allowlist.keys(): + char = chr(n) + font_info = allowlist[n] + else: + char = " " + font_info = FontInfo(unifont, 0) + # Hack: Chinese, Japanese, and Korean characters are all double + # width and are all on textures [1,6]. To fit them in the same + # grid, we use a half-size font. + draw.text((col * font_pixels / 2, (row - row_begin) * font_pixels + + font_info.dy), char, font=font_info.font, fill=255) + + image.save("Fonts/Bitmaps/font-%01d.png" % nth_texture) + +def genASCII(): + # Create an 8k grayscale image. 16 glyphs wide, 8 glyphs tall. + # Only characters on the range [0, 128). + image = Image.new(mode="L", size=(8192,8192), color=0) draw = ImageDraw.Draw(image) + n_rows = 8 + n_cols = 16 - row_begin = nth_texture * n_rows + font = ImageFont.truetype( + "Fonts/Noto_Sans_Mono/static/NotoSansMono/NotoSansMono-Bold.ttf", + int((8192 / 8) * 0.75), index=0, layout_engine=layout_engine) - for row in range(row_begin, row_begin + n_rows): - line = "" + for row in range(0, n_rows): for col in range(0, n_cols): - # Generate the unicode character for this spot. n = row * n_cols + col char = None font_info = None if n in allowlist.keys(): char = chr(n) - font_info = allowlist[n] else: char = " " - font_info = FontInfo(unifont, 0) - # Hack: Chinese, Japanese, and Korean characters are all double - # width and are all on textures [1,6]. To fit them in the same - # grid, we use a half-size font. - draw.text((col * font_pixels / 2, (row - row_begin) * font_pixels + - font_info.dy), char, font=font_info.font, fill=255) - - image.save("Fonts/Bitmaps/font-%01d.png" % nth_texture) - + draw.text((col * font_pixels * 8 / 2, row * font_pixels * 8 - 20), + char, font=font, fill=255) + image.save("Fonts/Bitmaps/font-ascii.png") + +if __name__ == "__main__": + print("Generating unicode fonts") + genUnicode() + print("Generating ASCII fonts") + genASCII() diff --git a/Scripts/generate_shader.py b/Scripts/generate_shader.py index cf46533..2348141 100644 --- a/Scripts/generate_shader.py +++ b/Scripts/generate_shader.py @@ -37,12 +37,15 @@ def generateCgParams(nbytes: int, nrows: int, ncols: int, prefix: str = "") -> s # uniform int BYTES_PER_CHAR = $nbytes; # uniform int NROWS = $nrows; # uniform int NCOLS = $ncols; -def generateCgConstants(nbytes: int, nrows: int, ncols: int, prefix: str = "") -> str: +def generateCgConstants(nbytes: int, board_nrows: int, board_ncols: int, + texture_nrows: int, texture_ncols: int, prefix: str = "") -> str: lines = [] lines.append(prefix + "// BEGIN GENERATED CODE BLOCK") lines.append(prefix + "#define BYTES_PER_CHAR {}".format(nbytes)) - lines.append(prefix + "#define NROWS {}".format(nrows)) - lines.append(prefix + "#define NCOLS {}".format(ncols)) + lines.append(prefix + "#define BOARD_NROWS {}".format(board_nrows)) + lines.append(prefix + "#define BOARD_NCOLS {}".format(board_ncols)) + lines.append(prefix + "#define TEXTURE_NROWS {}".format(texture_nrows)) + lines.append(prefix + "#define TEXTURE_NCOLS {}".format(texture_ncols)) lines.append(prefix + "// END GENERATED CODE BLOCK") return '\n'.join(lines) @@ -117,37 +120,44 @@ if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument("--bytes_per_char", type=str, help="The number of bytes to use to represent each character") - parser.add_argument("--rows", type=str, help="The number of rows on the board") - parser.add_argument("--cols", type=str, help="The number of columns on the board") + parser.add_argument("--board_rows", type=str, help="The number of rows on the board") + parser.add_argument("--board_cols", type=str, help="The number of columns on the board") + parser.add_argument("--texture_rows", type=str, help="The number of rows on the font textures") + parser.add_argument("--texture_cols", type=str, help="The number of columns on the font textures") parser.add_argument("--shader_template", type=str, help="The path to the shader template") parser.add_argument("--shader_path", type=str, help="The path where the generated shader will be written") args = parser.parse_args() - if not args.bytes_per_char or not args.rows or not args.cols \ + if not args.bytes_per_char or not args.board_rows or not args.board_cols \ + or not args.texture_rows or not args.texture_cols \ or not args.shader_template or not args.shader_path: - print("--bytes_per_char, --rows, --cols, --shader_template, --shader_path required", file=sys.stderr) + print(("--bytes_per_char, --board_rows, --board_cols, --texture_rows, " + "--texture_cols, --shader_template, --shader_path required"), file=sys.stderr) sys.exit(1) nbytes = int(args.bytes_per_char) - nrows = int(args.rows) - ncols = int(args.cols) + board_nrows = int(args.board_rows) + board_ncols = int(args.board_cols) + texture_nrows = int(args.texture_rows) + texture_ncols = int(args.texture_cols) - replacement = generateUnityParams(nbytes, nrows, ncols, prefix = "") + replacement = generateUnityParams(nbytes, board_nrows, board_ncols, prefix = "") #print(replacement) macro = "// %TEMPLATE__UNITY_ROW_COL_PARAMS%" applyLineMacro(args.shader_template, args.shader_path, macro, replacement) - replacement = generateCgParams(nbytes, nrows, ncols, prefix = " ") + replacement = generateCgParams(nbytes, board_nrows, board_ncols, prefix = " ") #print(replacement) macro = "// %TEMPLATE__CG_ROW_COL_PARAMS%" applyLineMacro(args.shader_path, args.shader_path, macro, replacement) - replacement = generateCgConstants(nbytes, nrows, ncols, prefix = " ") + replacement = generateCgConstants(nbytes, board_nrows, board_ncols, + texture_nrows, texture_ncols, prefix = " ") #print(replacement) macro = "// %TEMPLATE__CG_ROW_COL_CONSTANTS%" applyLineMacro(args.shader_path, args.shader_path, macro, replacement) - replacement = generateLetterAccessor(nbytes, nrows, ncols, prefix = " ") + replacement = generateLetterAccessor(nbytes, board_nrows, board_ncols, prefix = " ") #print(replacement) macro = "// %TEMPLATE__CG_LETTER_ACCESSOR%" applyLineMacro(args.shader_path, args.shader_path, macro, replacement) diff --git a/Shaders/TaSTT_lighting_template.cginc b/Shaders/TaSTT_lighting_template.cginc index 48d776d..da3a2ec 100644 --- a/Shaders/TaSTT_lighting_template.cginc +++ b/Shaders/TaSTT_lighting_template.cginc @@ -275,8 +275,8 @@ float2 GetLetter(float2 uv, int nth_letter, // Get the value of the parameter for the cell we're in. uint GetLetterParameter(float2 uv) { - float CHAR_COL = floor(uv.x * NCOLS); - float CHAR_ROW = floor(uv.y * NROWS); + float CHAR_COL = floor(uv.x * BOARD_NCOLS); + float CHAR_ROW = floor(uv.y * BOARD_NROWS); int res = 0; // %TEMPLATE__CG_LETTER_ACCESSOR% @@ -582,15 +582,13 @@ fixed4 frag(v2f i) : SV_Target float2 letter_uv; bool is_emote = false; if (letter < 0xE000) { - texture_cols = 128.0; - texture_rows = 64.0; - letter_uv = GetLetter(uv_with_margin, letter % 0x2000, texture_cols, texture_rows, NCOLS, NROWS, /*margin=*/0.02); + letter_uv = GetLetter(uv_with_margin, letter % 0x2000, TEXTURE_NCOLS, TEXTURE_NROWS, BOARD_NCOLS, BOARD_NROWS, /*margin=*/0.02); } else { is_emote = true; texture_cols = 16.0; texture_rows = 8.0; // This will need to be updated if we create multiple emote textures. - letter_uv = GetLetter(uv_with_margin, letter % 0x2000, texture_cols, texture_rows, NCOLS, NROWS, /*margin=*/0); + letter_uv = GetLetter(uv_with_margin, letter % 0x2000, texture_cols, texture_rows, BOARD_NCOLS, BOARD_NROWS, /*margin=*/0); } if (letter_uv.x == -1 && letter_uv.y == -1) { |
