File Structure Best Practices
Recommended Directory Layout
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
}
}
// 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
/**
* 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
public struct GlassMaterial: ViewModifier {
let ior: Float
let thickness: Float
let tint: Color
}
Version Control Strategies
Shader Versioning
enum ShaderVersion {
case v1_0_0
case v1_1_0
case v2_0_0
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
)
}
}