pcbjam/tests/gal-regression/wasm/generate_shaders.py
Viktor Vaczi 6fa6c9207f feat(webgl): Migrate to pure WebGL 2.0 and fix GL canvas layering
Update submodules and build config for pure WebGL 2.0 (drop -sFULL_ES3):
- kicad: VBO-based drawing, compositor FBO rewrite, shader conversion
- wxwidgets: Fix z-index layering so GL canvas renders above 2D UI canvas
- Build: Remove FULL_ES3 from linker flags
- GAL tests: White background, opaque alpha, shared shader converter,
  updated baseline screenshots

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 12:38:24 +01:00

118 lines
3.6 KiB
Python

#!/usr/bin/env python3
"""
Generate C++ shader headers from KiCad GLSL files.
This script converts GLSL shader files to C++ headers compatible with
KiCad's BUILTIN_SHADERS namespace.
"""
import os
import sys
# Import the canonical GLSL converter from the KiCad shaders directory.
# This ensures the test uses the exact same conversion as the KiCad WASM build.
_kicad_shaders_dir = os.path.join(
os.path.dirname(os.path.abspath(__file__)),
'..', '..', '..', 'kicad', 'common', 'gal', 'shaders'
)
sys.path.insert(0, os.path.abspath(_kicad_shaders_dir))
from convert_glsl_es3 import convert_glsl120_to_es300
def convert_shader_to_cpp(source_path, var_name):
"""Convert a shader file to C++ header content."""
with open(source_path, 'rb') as f:
data = f.read()
# Convert GLSL 1.20 to GLSL ES 3.00 for WebGL 2.0
shader_source = data.decode('utf-8')
is_fragment = '_frag' in var_name or 'frag' in source_path.lower()
shader_source = convert_glsl120_to_es300(shader_source, is_fragment)
data = shader_source.encode('utf-8')
# Convert to hex array
hex_values = ', '.join(f'0x{b:02x}' for b in data)
hex_values += ', 0x00' # Null terminate
array_size = len(data)
header_content = f"""// Auto-generated shader header from {os.path.basename(source_path)}
#ifndef {var_name.upper()}_H
#define {var_name.upper()}_H
#include <string>
namespace KIGFX {{
namespace BUILTIN_SHADERS {{
extern std::string {var_name};
}}
}}
#endif // {var_name.upper()}_H
"""
cpp_content = f"""// Auto-generated from {os.path.basename(source_path)}
#include <string>
#include "{var_name}.h"
namespace KIGFX {{
namespace BUILTIN_SHADERS {{
static unsigned char {var_name}_bytes[] = {{ {hex_values} }};
std::string {var_name} = std::string(reinterpret_cast<char const*>({var_name}_bytes), {array_size});
}}
}}
"""
return header_content, cpp_content
def main():
script_dir = os.path.dirname(os.path.abspath(__file__))
kicad_root = os.path.abspath(os.path.join(script_dir, '..', '..', '..', 'kicad'))
shaders_dir = os.path.join(kicad_root, 'common', 'gal', 'shaders')
output_dir = os.path.join(script_dir, 'generated')
os.makedirs(output_dir, exist_ok=True)
shaders = [
('kicad_frag.glsl', 'glsl_kicad_frag'),
('kicad_vert.glsl', 'glsl_kicad_vert'),
('smaa_base.glsl', 'glsl_smaa_base'),
('smaa_pass_1_frag_color.glsl', 'glsl_smaa_pass_1_frag_color'),
('smaa_pass_1_frag_luma.glsl', 'glsl_smaa_pass_1_frag_luma'),
('smaa_pass_1_vert.glsl', 'glsl_smaa_pass_1_vert'),
('smaa_pass_2_frag.glsl', 'glsl_smaa_pass_2_frag'),
('smaa_pass_2_vert.glsl', 'glsl_smaa_pass_2_vert'),
('smaa_pass_3_frag.glsl', 'glsl_smaa_pass_3_frag'),
('smaa_pass_3_vert.glsl', 'glsl_smaa_pass_3_vert'),
]
generated_cpp_files = []
for shader_file, var_name in shaders:
source_path = os.path.join(shaders_dir, shader_file)
if not os.path.exists(source_path):
print(f"Warning: {source_path} not found, skipping")
continue
header_content, cpp_content = convert_shader_to_cpp(source_path, var_name)
header_path = os.path.join(output_dir, f'{var_name}.h')
cpp_path = os.path.join(output_dir, f'{var_name}.cpp')
with open(header_path, 'w') as f:
f.write(header_content)
with open(cpp_path, 'w') as f:
f.write(cpp_content)
generated_cpp_files.append(cpp_path)
print(f"Generated {var_name}.h and {var_name}.cpp")
print(f"\nGenerated {len(generated_cpp_files)} shader files in {output_dir}")
if __name__ == '__main__':
main()