UNPKG

shader-converter-wasm

Version:

WebAssembly-based shader language converter and validator. Convert between GLSL, WGSL, SPIR-V, Metal, and HLSL in the browser.

290 lines (217 loc) 7.8 kB
# Shader Converter WASM [![npm version](https://img.shields.io/npm/v/shader-converter-wasm.svg)](https://www.npmjs.com/package/shader-converter-wasm) [![License](https://img.shields.io/npm/l/shader-converter-wasm.svg)](https://github.com/yourusername/shader-converter-wasm/blob/main/LICENSE) A WebAssembly-based shader language converter and validator for the browser. Convert between GLSL, WGSL, SPIR-V, Metal, and HLSL with zero native dependencies. ## ✨ Features - 🔄 **15 Conversion Paths**: Convert between GLSL ↔ WGSL ↔ SPIR-V → Metal/HLSL - ✅ **Validation**: Syntax and semantic validation with detailed error reporting - 🔍 **Auto-Detection**: Intelligent shader language detection with confidence scoring - 📦 **Resource Analysis**: Extract uniforms, textures, inputs, and outputs - 🎯 **Entry Point Analysis**: Detailed entry point information - 🧩 **SPIR-V Processing**: Binary and assembly manipulation - 🚀 **Browser-Native**: Runs entirely in the browser via WebAssembly - 📦 **Zero Dependencies**: No native toolchain required ## 📦 Installation ```bash npm install shader-converter-wasm ``` ## 🚀 Quick Start ```javascript import init, { ShaderConverter } from 'shader-converter-wasm'; // Initialize WASM module await init(); // Create converter instance const converter = new ShaderConverter(); // Convert WGSL to GLSL const wgsl = ` @vertex fn main(@location(0) pos: vec3<f32>) -> @builtin(position) vec4<f32> { return vec4<f32>(pos, 1.0); }`; const glsl = converter.convert(wgsl, 'wgsl', 'glsl', 'vertex'); console.log(glsl); ``` ## 📚 Supported Conversions | From / To | GLSL | WGSL | SPIR-V | Metal | HLSL | |-----------|------|------|--------|-------|------| | **GLSL** | - | ✓ | ✓ | ✓ | ✓ | | **WGSL** | ✓ | - | ✓ | ✓ | ✓ | | **SPIR-V**| ✓ | ✓ | - | ✓ | ✓ | ## 🎯 Core API ### Shader Conversion ```javascript // Basic conversion converter.convert(source, fromFormat, toFormat, stage); // Example: WGSL to Metal const metal = converter.convert(wgslCode, 'wgsl', 'metal', 'fragment'); ``` ### Shader Validation ```javascript // Detailed validation const result = converter.validate_detailed(source, 'wgsl', null); const data = JSON.parse(result); if (data.valid) { console.log('Valid shader!', data.stats); } else { console.error('Validation errors:', data.errors); } ``` ### Auto-Detection ```javascript // Detect shader language and stage const result = converter.detect_shader(unknownCode); const detection = JSON.parse(result); console.log(detection.language); // 'wgsl' console.log(detection.confidence); // 0.95 console.log(detection.stage); // 'vertex' ``` ### Resource Analysis ```javascript // Extract shader resources const result = converter.analyze_resources(source, 'wgsl'); const resources = JSON.parse(result); console.log(resources.uniforms); // ['modelMatrix', 'viewMatrix'] console.log(resources.textures); // ['colorTexture', 'normalTexture'] console.log(resources.inputs); // ['position', 'normal', 'uv'] console.log(resources.outputs); // ['fragColor'] ``` ### Entry Point Analysis ```javascript // Get entry point information const result = converter.analyze_entry_points(source, 'wgsl'); const data = JSON.parse(result); data.entry_points.forEach(ep => { console.log(`${ep.name} (${ep.stage})`); console.log(`Workgroup size: ${ep.workgroup_size}`); }); ``` ### Best Practices Check ```javascript // Check for performance issues and best practices const result = converter.check_shader(source, 'wgsl'); const check = JSON.parse(result); console.log('Complexity:', check.complexity); // 'low' | 'medium' | 'high' console.log('Warnings:', check.warnings); console.log('Suggestions:', check.suggestions); ``` ## 📖 Complete Example ```javascript import init, { ShaderConverter } from 'shader-converter-wasm'; async function processShader(shaderCode) { // Initialize await init(); const converter = new ShaderConverter(); // 1. Auto-detect language const detection = JSON.parse(converter.detect_shader(shaderCode)); console.log(`Detected: ${detection.language} (${detection.confidence * 100}%)`); // 2. Validate shader const validation = JSON.parse( converter.validate_detailed(shaderCode, detection.language, null) ); if (!validation.valid) { console.error('Validation errors:', validation.errors); return; } // 3. Analyze resources const resources = JSON.parse( converter.analyze_resources(shaderCode, detection.language) ); console.log('Resources:', resources); // 4. Convert to other formats const glsl = converter.convert(shaderCode, detection.language, 'glsl', null); const metal = converter.convert(shaderCode, detection.language, 'metal', null); const hlsl = converter.convert(shaderCode, detection.language, 'hlsl', null); return { glsl, metal, hlsl }; } ``` ## 🔧 SPIR-V Processing ```javascript import { SpirvProcessor } from 'shader-converter-wasm'; const processor = new SpirvProcessor(); // Binary to assembly const assembly = processor.binary_to_assembly(spirvBytes); // Assembly to binary const binary = processor.assembly_to_binary(assemblyText); // Validate SPIR-V binary const isValid = processor.validate_binary(spirvBytes); // Get module info const info = processor.get_module_info(spirvBytes); ``` ## 📊 API Response Formats ### Detection Result ```typescript { language: 'glsl' | 'wgsl' | 'spirv', confidence: number, // 0.0 - 1.0 stage: 'vertex' | 'fragment' | 'compute' | 'unknown' } ``` ### Validation Result ```typescript { valid: boolean, errors?: [{ type: 'syntax' | 'semantic', message: string }], stats?: { entryPoints: number, functions: number, globals: number, types: number } } ``` ### Resource Analysis ```typescript { uniforms: string[], textures: string[], inputs: string[], outputs: string[] } ``` ## 🎨 Use Cases - **WebGPU Applications**: Convert GLSL shaders to WGSL - **Shader Playgrounds**: Build online shader editors with live conversion - **Cross-Platform Tools**: Convert shaders for multiple graphics APIs - **Shader Analysis**: Validate and analyze shader code in the browser - **Educational Tools**: Teach shader programming with instant feedback ## 🌐 Browser Compatibility - Chrome 57+ - Firefox 52+ - Safari 11+ - Edge 16+ Requires WebAssembly support. ## ⚡ Performance Tips 1. **Initialize once**: Call `await init()` only once at startup 2. **Reuse instances**: Create converter/processor instances once and reuse 3. **Batch operations**: Process multiple shaders without re-initializing ```javascript // ✓ Good await init(); const converter = new ShaderConverter(); const result1 = converter.convert(code1, 'wgsl', 'glsl', null); const result2 = converter.convert(code2, 'wgsl', 'metal', null); // ✗ Bad await init(); const result1 = new ShaderConverter().convert(code1, 'wgsl', 'glsl', null); await init(); const result2 = new ShaderConverter().convert(code2, 'wgsl', 'metal', null); ``` ## 📄 License MIT License - see LICENSE file for details ## 🔗 Links - [Documentation](https://github.com/yourusername/shader-converter-wasm#readme) - [API Reference](./API.md) - [Examples](./examples) - [Report Issues](https://github.com/yourusername/shader-converter-wasm/issues) ## 🙏 Acknowledgments Built with: - [naga](https://github.com/gfx-rs/naga) - Shader translation library - [rspirv](https://github.com/gfx-rs/rspirv) - SPIR-V parser and builder - [wasm-bindgen](https://github.com/rustwasm/wasm-bindgen) - Rust/WASM bindings ## 🤝 Contributing Contributions are welcome! Please feel free to submit a Pull Request. --- Made with ❤️ using Rust and WebAssembly