Appendix B: Shader Library Organization

Professional development workflows: File structure, parameter validation, documentation standards, and version control strategies.

File Structure Best Practices

MyApp/
├── Shaders/
│   ├── MyApp-Bridging-Header.h
│   ├── ShaderTypes.h          // Shared types between Swift and Metal
│   ├── Core/
│   │   ├── Math.metal         // Shared math functions
│   │   ├── Noise.metal        // Noise functions
│   │   └── Color.metal        // Color space conversions
│   ├── Effects/
│   │   ├── Blur.metal
│   │   ├── Glow.metal
│   │   └── Distortion.metal
│   ├── Materials/
│   │   ├── Glass.metal
│   │   ├── Metal.metal
│   │   └── Fabric.metal
│   └── UI/
│       ├── Buttons.metal
│       ├── Cards.metal
│       └── Backgrounds.metal

Shader Naming Conventions

// Function naming pattern: categoryTypeVariant
[[ stitchable ]] half4 uiButtonGlow(...)
[[ stitchable ]] half4 materialGlassFrosted(...)
[[ stitchable ]] half4 effectBlurGaussian(...)

// Parameter naming
float time              // Animation time
float2 position         // Current pixel position
float2 size            // View size
float2 center          // Effect center point
float intensity        // Effect strength (0-1)
float radius           // Effect radius

Parameter Validation Patterns

Swift-Side Validation

struct ShaderParameters {
    var intensity: Float {
        didSet { intensity = max(0, min(1, intensity)) }
    }
    
    var radius: Float {
        didSet { radius = max(0, radius) }
    }
    
    var colorComponents: SIMD3<Float> {
        didSet { colorComponents = clamp(colorComponents, min: 0, max: 1) }
    }
    
    func validate() -> Bool {
        guard intensity >= 0 && intensity <= 1 else { return false }
        guard radius >= 0 else { return false }
        guard all(colorComponents .>= 0) && all(colorComponents .<= 1) else { return false }
        return true
    }
}

Metal-Side Safety

// Always clamp inputs to valid ranges
float safeIntensity = saturate(intensity);
float safeRadius = max(0.0, radius);
float2 safeUV = clamp(uv, 0.0, 1.0);

// Prevent division by zero
float safeDivide(float a, float b) {
    return a / max(b, 0.0001);
}

// Safe normalization
float3 safeNormalize(float3 v) {
    float len = length(v);
    return len > 0.0001 ? v / len : float3(0, 0, 1);
}

Documentation Standards

Metal Documentation Template

/**
 * Creates a glass material effect with refraction and reflection
 *
 * @param position     Current pixel position in view coordinates
 * @param layer        Input layer for refraction sampling
 * @param size         View size in pixels
 * @param ior          Index of refraction (1.0-2.0, glass=1.5)
 * @param thickness    Glass thickness for chromatic aberration (0.0-1.0)
 * @param tint         Glass color tint
 *
 * @return Modified color with glass effect applied
 *
 * @performance O(n) where n is blur sample count
 * @quality Requires iOS 17.0+
 */
[[ stitchable ]] half4 materialGlass(
    float2 position,
    SwiftUI::Layer layer,
    float2 size,
    float ior,
    float thickness,
    half4 tint
) {
    // Implementation
}

Swift Documentation

/// A glass material effect that simulates realistic light refraction
///
/// This effect creates a convincing glass appearance by:
/// - Calculating Fresnel reflections based on viewing angle
/// - Applying chromatic aberration for thickness variation
/// - Sampling the background with refraction offsets
///
/// - Parameters:
///   - ior: Index of refraction (1.0-2.0). Common values:
///     - Water: 1.33
///     - Glass: 1.5
///     - Diamond: 2.42
///   - thickness: Simulated glass thickness affecting color separation
///   - tint: Color tint applied to the glass
///
/// - Performance: Heavy effect, consider using on small views only
/// - Complexity: O(n) where n is sample count
public struct GlassMaterial: ViewModifier {
    let ior: Float
    let thickness: Float
    let tint: Color
}

Version Control Strategies

Shader Versioning

enum ShaderVersion {
    case v1_0_0  // Initial release
    case v1_1_0  // Added parameter validation
    case v2_0_0  // Breaking change: new parameter order
    
    var libraryName: String {
        switch self {
        case .v1_0_0: return "ShaderLibrary_v1"
        case .v1_1_0: return "ShaderLibrary_v1_1"
        case .v2_0_0: return "ShaderLibrary_v2"
        }
    }
}

Migration Patterns

protocol ShaderMigration {
    associatedtype OldParameters
    associatedtype NewParameters
    
    static func migrate(_ old: OldParameters) -> NewParameters
}

struct GlowEffectMigration_v1_to_v2: ShaderMigration {
    static func migrate(_ old: GlowParameters_v1) -> GlowParameters_v2 {
        GlowParameters_v2(
            radius: old.radius,
            intensity: old.intensity,
            color: old.color,
            blendMode: .normal  // New parameter with default
        )
    }
}