summaryrefslogtreecommitdiffstats
path: root/Scripts
diff options
context:
space:
mode:
authoryum <yum.food.vr@gmail.com>2022-12-29 18:47:57 -0800
committeryum <yum.food.vr@gmail.com>2022-12-29 18:49:24 -0800
commit7214653f9354ef885ef4131e455e0a63f12a17f2 (patch)
tree0eb5aac16401bf03fac2f3e8863d9c7a0bd274d5 /Scripts
parent06aece2ebade3d25c16fe1c143fba5cd472d004c (diff)
Add Scripts/generate_shader.py
Now it's possible to generate shaders with a custom number of rows, columns, and bytes per character. All edits to the shader should go through TaSTT_template.shader. To generate a new shader from the template: $ ./Scripts/generate_shader.py \ --bytes_per_char 2 \ --rows 1 \ --cols 12 --shader_template $(pwd)/Shaders/TaSTT_template.shader \ --shader_path $(pwd)/Shaders/TaSTT.shader
Diffstat (limited to 'Scripts')
-rw-r--r--Scripts/generate_shader.py158
1 files changed, 158 insertions, 0 deletions
diff --git a/Scripts/generate_shader.py b/Scripts/generate_shader.py
new file mode 100644
index 0000000..67f916d
--- /dev/null
+++ b/Scripts/generate_shader.py
@@ -0,0 +1,158 @@
+#!/usr/bin/env python3
+
+import argparse
+import generate_utils
+import os
+import sys
+
+# A single parameter looks like this:
+# _Letter_Row00_Col00_Byte0("_Letter_Row00_Col00_Byte0", float) = 0
+def generateUnityParams(nbytes: int, nrows: int, ncols: int, prefix: str = "") -> str:
+ lines = []
+ lines.append(prefix + "// BEGIN GENERATED CODE BLOCK")
+ for byte in range(0, nbytes):
+ for row in range(0, nrows):
+ for col in range(0, ncols):
+ param_name = generate_utils.getShaderParamByRowColByte(row, col, byte)
+ line = prefix + """{}("{}", float) = 0""".format(param_name, param_name)
+ lines.append(line)
+ lines.append(prefix + "// END GENERATED CODE BLOCK")
+ return '\n'.join(lines)
+
+# A single parameter looks like this:
+# float _Letter_Row00_Col00_Byte0;
+def generateCgParams(nbytes: int, nrows: int, ncols: int, prefix: str = "") -> str:
+ lines = []
+ lines.append(prefix + "// BEGIN GENERATED CODE BLOCK")
+ for byte in range(0, nbytes):
+ for row in range(0, nrows):
+ for col in range(0, ncols):
+ param_name = generate_utils.getShaderParamByRowColByte(row, col, byte)
+ line = prefix + """float {};""".format(param_name)
+ lines.append(line)
+ lines.append(prefix + "// END GENERATED CODE BLOCK")
+ return '\n'.join(lines)
+
+# Define 3 constants:
+# 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:
+ 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 + "// END GENERATED CODE BLOCK")
+ return '\n'.join(lines)
+
+# This is the basic idea of what we're generating:
+# // Get the value of the parameter for the cell we're in.
+# int GetLetterParameter(float2 uv)
+# {
+# float CHAR_COL = floor(uv.x * Cols);
+# float CHAR_ROW = floor(uv.y * Rows);
+# int res = 0;
+#
+# [forcecase] switch(CHAR_ROW) {
+# case n:
+# case n-1:
+# ...
+#
+# [forcecase] switch (CHAR_COL) {
+# case 0:
+# case 1:
+# ...
+#
+# res |= ((int) _Letter_Row00_Col00_Byte0) << (0 * 8);
+# res |= ((int) _Letter_Row00_Col00_Byte1) << (1 * 8);
+# continue;
+# }
+# }
+# return res;
+# }
+# In English, this provides an accessor to the many (possibly thousands)
+# float parameters which hold the text on the board.
+def generateLetterAccessor(nbytes: int, nrows: int, ncols: int, prefix: str = "") -> str:
+ lines = []
+ lines.append(prefix + "// BEGIN GENERATED CODE BLOCK")
+ lines.append(prefix + "[forcecase] switch (CHAR_ROW) {")
+ for row in range(0, nrows):
+ lines.append(prefix + " case {}:".format(nrows - (row + 1)))
+ lines.append(prefix + " [forcecase] switch (CHAR_COL) {")
+ for col in range(0, ncols):
+ lines.append(prefix + " case {}:".format(col))
+ for byte in range(0, nbytes):
+ param_name = generate_utils.getShaderParamByRowColByte(row, col, byte)
+ lines.append(prefix + " res |= ((int) {}) << ({} * 8);".format(param_name, byte))
+ lines.append(prefix + " return res;")
+ lines.append(prefix + " default:")
+ lines.append(prefix + " return 0;")
+ lines.append(prefix + " }")
+ lines.append(prefix + "}")
+ lines.append(prefix + "// END GENERATED CODE BLOCK")
+ return '\n'.join(lines)
+
+# Replace any line containing `macro` with `replacement`.
+def applyLineMacro(old_path: str, new_path: str, macro: str, replacement: str) -> bool:
+ new_lines = []
+ times_applied = 0
+ with open(old_path, 'r') as f:
+ for line in f:
+ if line[-1] == '\n':
+ line = line[0:len(line)-1]
+ if macro in line:
+ new_lines.append(replacement)
+ times_applied += 1
+ else:
+ new_lines.append(line)
+ with open(new_path, 'w') as f:
+ f.write('\n'.join(new_lines))
+ return times_applied
+
+if __name__ == "__main__":
+ sys.stdout.reconfigure(encoding="utf-8")
+
+ print("args: {}".format(" ".join(sys.argv)))
+
+ # Set cwd to the directory holding the script
+ abspath = os.path.abspath(__file__)
+ dname = os.path.dirname(abspath)
+ os.chdir(dname)
+
+ 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("--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 \
+ or not args.shader_template or not args.shader_path:
+ print("--bytes_per_char, --rows, --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)
+
+ replacement = generateUnityParams(nbytes, nrows, ncols, prefix = " ")
+ #print(replacement)
+ macro = "// %TEMPLATE__UNITY_ROW_COL_PARAMS%"
+ assert(applyLineMacro(args.shader_template, args.shader_path, macro, replacement) == 1)
+
+ replacement = generateCgParams(nbytes, nrows, ncols, prefix = " ")
+ #print(replacement)
+ macro = "// %TEMPLATE__CG_ROW_COL_PARAMS%"
+ assert(applyLineMacro(args.shader_path, args.shader_path, macro, replacement) == 1)
+
+ replacement = generateCgConstants(nbytes, nrows, ncols, prefix = " ")
+ #print(replacement)
+ macro = "// %TEMPLATE__CG_ROW_COL_CONSTANTS%"
+ assert(applyLineMacro(args.shader_path, args.shader_path, macro, replacement) == 1)
+
+ replacement = generateLetterAccessor(nbytes, nrows, ncols, prefix = " ")
+ #print(replacement)
+ macro = "// %TEMPLATE__CG_LETTER_ACCESSOR%"
+ assert(applyLineMacro(args.shader_path, args.shader_path, macro, replacement) == 1)