| static const char *demo_shader_msl = |
| "/*\n" |
| " * Copyright 2026 Behdad Esfahbod. All Rights Reserved.\n" |
| " */\n" |
| "\n" |
| "struct Uniforms {\n" |
| " float4x4 matViewProjection;\n" |
| " float2 viewport;\n" |
| " float gamma;\n" |
| " float stem_darkening;\n" |
| " float4 foreground;\n" |
| " float debug;\n" |
| "};\n" |
| "\n" |
| "struct VertexIn {\n" |
| " float2 position [[attribute(0)]];\n" |
| " float2 texcoord [[attribute(1)]];\n" |
| " float2 normal [[attribute(2)]];\n" |
| " float emPerPos [[attribute(3)]];\n" |
| " uint glyphLoc [[attribute(4)]];\n" |
| "};\n" |
| "\n" |
| "struct VertexOut {\n" |
| " float4 position [[position]];\n" |
| " float2 texcoord;\n" |
| " uint glyphLoc [[flat]];\n" |
| "};\n" |
| "\n" |
| "vertex VertexOut vertex_main(VertexIn in [[stage_in]],\n" |
| " constant Uniforms& uniforms [[buffer(1)]]) {\n" |
| " float2 pos = in.position;\n" |
| " float2 tex = in.texcoord;\n" |
| " float4 jac = float4(in.emPerPos, 0.0, 0.0, -in.emPerPos);\n" |
| "\n" |
| " hb_gpu_dilate(pos, tex, in.normal, jac,\n" |
| " uniforms.matViewProjection, uniforms.viewport);\n" |
| "\n" |
| " VertexOut out;\n" |
| " out.position = uniforms.matViewProjection * float4(pos, 0.0, 1.0);\n" |
| " out.texcoord = tex;\n" |
| " out.glyphLoc = in.glyphLoc;\n" |
| " return out;\n" |
| "}\n" |
| "\n" |
| "fragment float4 fragment_main(VertexOut in [[stage_in]],\n" |
| " constant Uniforms& uniforms [[buffer(1)]],\n" |
| " device const short4* atlas [[buffer(0)]]) {\n" |
| "#ifdef HB_GPU_DEMO_DRAW\n" |
| " float cov = hb_gpu_draw(in.texcoord, in.glyphLoc, atlas);\n" |
| " float4 c = float4(uniforms.foreground.rgb * uniforms.foreground.a,\n" |
| " uniforms.foreground.a) * cov;\n" |
| "#else\n" |
| " float cov;\n" |
| " float4 c = hb_gpu_paint(in.texcoord, in.glyphLoc, uniforms.foreground,\n" |
| " atlas, cov);\n" |
| "\n" |
| " if (cov > 0.0 && cov < 1.0) {\n" |
| " float adj = cov;\n" |
| " if (uniforms.stem_darkening > 0.0) {\n" |
| " float brightness = c.a > 0.0\n" |
| " ? dot(c.rgb, float3(1.0 / 3.0)) / c.a : 0.0;\n" |
| " float2 fw = fwidth(in.texcoord);\n" |
| " adj = hb_gpu_stem_darken(adj, brightness,\n" |
| " 1.0 / max(fw.x, fw.y));\n" |
| " }\n" |
| " if (uniforms.gamma != 1.0)\n" |
| " adj = pow(adj, uniforms.gamma);\n" |
| " c *= adj / cov;\n" |
| " }\n" |
| "#endif\n" |
| "\n" |
| " if (uniforms.debug > 0.0) {\n" |
| " int2 counts = _hb_gpu_curve_counts(in.texcoord, in.glyphLoc, atlas);\n" |
| " float r = clamp(float(counts.x) / 8.0, 0.0, 1.0);\n" |
| " float g = clamp(float(counts.y) / 8.0, 0.0, 1.0);\n" |
| " return float4(r, g, c.a, max(max(r, g), c.a));\n" |
| " }\n" |
| "\n" |
| " return c;\n" |
| "}\n" |
| ; |