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