Categories
iOS Metal Swift SwiftUI

Applying metal shader to text in SwiftUI

WWDC ’23 introduced view modifiers for applying shaders to SwiftUI views. The new view modifiers are called colorEffect, distortionEffect, and layerEffect. In addition, the Shader also conforms to the ShapeStyle protocol which means that we can directly pass the shader to the foregroundStyle view modifier and then SwiftUI uses the shader to compute pixel color values for the view. In this post, we are going to have a look at what it takes to apply a shader to text. What we will not cover is how to use each of the new view modifiers, what were mentioned before.

Metal shaders are defined in .metal files. Therefore, the first step is to add a new .metal file to the project. As an example, we’ll create a shader which applies a stripe effect to the text. The .metal file’s implementation is shown below:

#include <metal_stdlib>
using namespace metal;

[[ stitchable ]] half4 stripes(float2 position, float stripeWidth) {
    bool isAlternativeColor = uint(position.x / stripeWidth) & 1;
    return isAlternativeColor ? half4(0, 0, 1, 1) : half4(1, 0, 0, 1);
}

The shader function returns color of the pixel for the current pixel position. The stripeWidth argument is going to be handled by us for configuring the width of the stripe. When the shader function is defined, then the next step is using the new ShaderLibrary type for accessing the shader function. Since the ShaderLibrary type implements @dynamicMemberLookup then the metal shader function in the .metal file can be accessed directly though the name stripes.

var shader: Shader {
  ShaderLibrary.stripes(.float(15))
}

The last step is applying the shader to the Text value using the foregroundStyle view modifier.

Text("Hello, world!")
  .font(.largeTitle)
  .foregroundStyle(shader)

The final result can be seen here:

Sample code: SwiftUIMetalTextShaderExample (Xcode 15 beta 5)

If this was helpful, please let me know on Mastodon@toomasvahter or Twitter @toomasvahter. Feel free to subscribe to RSS feed. Thank you for reading.

One reply on “Applying metal shader to text in SwiftUI”