#include using namespace metal; struct VertexInput { float2 position; float2 tex_coord; }; struct VertexOutput { float4 position [[position]]; float2 tex_coord; }; struct Glyph { float2 atlas_position; float2 size; float2 target_position; float y_offset; float _haha_alignment; }; struct UniformParams { float2 screen_size; }; float4 to_device_position(float2 position, float2 size) { return float4(((position / size) * 2.0) - float2(1.0), 1.0, 1.0); } vertex VertexOutput vs_main( uint vertex_id [[vertex_id]], uint glyph_id [[instance_id]], constant VertexInput *vertices [[buffer(0)]], constant Glyph *glyphs [[buffer(1)]], constant UniformParams ¶ms [[buffer(2)]] ) { VertexOutput out; Glyph glyph = glyphs[glyph_id]; float2 scaled_size = ((vertices[vertex_id].position + 1.0) / 2.0) * (glyph.size/2.0); float2 scaled_size_2 = ((vertices[vertex_id].position + 1.0) / 2.0) * (glyph.size); float2 glyph_pos = scaled_size + glyph.target_position + float2(0, glyph.y_offset/2.0+32); float4 device_position = to_device_position(glyph_pos, params.screen_size); float2 atlas_position = (scaled_size_2 + glyph.atlas_position) / 1024.0; device_position.y = -device_position.y; out.position = device_position; out.tex_coord = atlas_position; return out; } fragment float4 fs_main(VertexOutput in [[stage_in]], texture2d texture [[texture(0)]]) { constexpr sampler texture_sampler (mag_filter::linear, min_filter::linear); float text_color = texture.sample(texture_sampler, in.tex_coord).r; return float4(text_color * float3(1,1,1), text_color); }