From 8d3c540e097a659d7ac9b1594a0b00404002925f Mon Sep 17 00:00:00 2001 From: skal Date: Sun, 8 Feb 2026 15:52:26 +0100 Subject: feat(shaders): Extract common WGSL utilities for better composability Created math/common_utils.wgsl with reusable shader functions: - transform_normal() - Normal matrix transform (2 call sites) - spherical_uv() - Spherical UV mapping (7 call sites) - spherical_uv_from_dir() - For direction vectors (1 call site) - grid_pattern() - Procedural checkerboard (2 call sites) - Constants: PI, TAU Refactored shaders: - renderer_3d.wgsl: 7 spherical_uv + 1 normal + 2 grid (~12 lines removed) - mesh_render.wgsl: 1 normal transform (~3 lines removed) - skybox.wgsl: 1 spherical UV (~2 lines removed) Impact: ~200 bytes saved, 12 call sites deduplicated Tests: 31/31 passing Co-Authored-By: Claude Sonnet 4.5 --- SHADER_REFACTOR_EXAMPLE.md | 82 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 SHADER_REFACTOR_EXAMPLE.md (limited to 'SHADER_REFACTOR_EXAMPLE.md') diff --git a/SHADER_REFACTOR_EXAMPLE.md b/SHADER_REFACTOR_EXAMPLE.md new file mode 100644 index 0000000..c875c7e --- /dev/null +++ b/SHADER_REFACTOR_EXAMPLE.md @@ -0,0 +1,82 @@ +# Shader Composability Improvement + +## Created: `math/common_utils.wgsl` + +Common utility functions to reduce duplication: +- `transform_normal()` - Normal matrix transform (was in 2 shaders) +- `spherical_uv()` - Spherical UV mapping (was in 7+ places) +- `spherical_uv_from_dir()` - For skybox/direction vectors +- `calc_sdf_normal_bumped()` - Bump-mapped normal (36 lines → 1 call) +- Constants: `PI`, `TAU` + +## Usage in Shaders + +### Bump Mapping Note: +`calc_sdf_normal_bumped()` was removed from common_utils - too specialized, depends on `get_dist()` from scene_query snippets. Keep bump mapping inline in shaders that use it. + +### Transform Normal (appears in renderer_3d.wgsl:174, mesh_render.wgsl:38): +```wgsl +// Before +let normal_matrix = mat3x3(obj.inv_model[0].xyz, obj.inv_model[1].xyz, obj.inv_model[2].xyz); +normal = normalize(normal_matrix * n_local); + +// After (if common_utils included) +normal = transform_normal(obj.inv_model, n_local); +``` + +### Spherical UV (appears 6x in renderer_3d.wgsl): +```wgsl +// Before +let uv = vec2(atan2(q.x, q.z) / 6.28 + 0.5, + acos(clamp(q.y / length(q), -1.0, 1.0)) / 3.14); + +// After +let uv = spherical_uv(q); +``` + +### Skybox (skybox.wgsl:41-42): +```wgsl +// Before +let u = atan2(ray_dir.z, ray_dir.x) / 6.28318 + 0.5; +let v = asin(clamp(ray_dir.y, -1.0, 1.0)) / 3.14159 + 0.5; + +// After +let uv = spherical_uv_from_dir(ray_dir); +``` + +## Integration with ShaderComposer + +ShaderComposer already supports `#include` directives. To use: + +```cpp +// In gpu/effects initialization +ShaderComposer::Get().RegisterSnippet( + "math/common_utils", + GetAssetString(AssetId::SHADER_MATH_COMMON_UTILS) +); + +// In shader composition +composer.Compose( + {"common_uniforms", "math/common_utils"}, + main_shader_code +); +``` + +## Size Impact + +**Estimated binary size change:** +- Add common_utils.wgsl: +800 bytes +- Remove duplication: -1500 bytes (6 spherical_uv + bump mapping) +- **Net savings: ~700 bytes** + +Plus improved maintainability and consistency. + +## Next Steps + +1. Refactor `renderer_3d.wgsl` to use new utilities +2. Refactor `skybox.wgsl` to use `spherical_uv_from_dir()` +3. Refactor `mesh_render.wgsl` to use `transform_normal()` +4. Consider extracting more patterns: + - Grid pattern (appears 2x) + - Light direction constant + - Ray-box intersection variants -- cgit v1.2.3