Shaders.swift (1729B)
1 // Metal shaders, compiled at runtime (the Command Line Tools have no offline `metal` compiler). 2 let shaderSource = """ 3 #include <metal_stdlib> 4 using namespace metal; 5 6 struct Vertex { float3 pos; float3 normal; float3 color; }; // 16-byte aligned, matches Swift SIMD3<Float> 7 struct Uniforms { float4x4 mvp; float4x4 model; float4 material; }; 8 struct VOut { float4 pos [[position]]; float3 normal; float3 color; float3 world; float grid [[flat]]; }; 9 10 vertex VOut vmain(uint vid [[vertex_id]], const device Vertex *v [[buffer(0)]], constant Uniforms &u [[buffer(1)]]) { 11 VOut o; 12 o.pos = u.mvp * float4(v[vid].pos, 1); 13 o.normal = (u.model * float4(v[vid].normal, 0)).xyz; 14 o.color = v[vid].color; 15 o.world = (u.model * float4(v[vid].pos, 1)).xyz; 16 o.grid = u.material.x; 17 return o; 18 } 19 20 fragment float4 fmain(VOut in [[stage_in]]) { 21 float3 l = normalize(float3(0.4, 0.8, 0.6)); 22 float d = max(dot(normalize(in.normal), l), 0.0); 23 float3 color = in.color; 24 if (in.grid > .5 && in.normal.y > .5) { 25 float2 p = in.world.xz; 26 float2 footprint = max(fwidth(p), float2(1e-5)); 27 float2 distanceToLine = abs(fract(p + .5) - .5); 28 // Maintain a readable minimum footprint, then fade when adjacent lines become unresolved. 29 float2 halfWidth = max(float2(.0075), footprint * .8); 30 float2 coverage = 1 - smoothstep(halfWidth - footprint * .5, halfWidth + footprint * .5, distanceToLine); 31 float2 resolvable = 1 - smoothstep(float2(.20), float2(.45), footprint); 32 float line = max(coverage.x * resolvable.x, coverage.y * resolvable.y); 33 color = mix(color, float3(.35, .40, .55), line); 34 } 35 return float4(color * (0.25 + 0.75 * d), 1); 36 } 37 """