💨

SwiftUI×Metalでエフェクトをかける

2023/06/18に公開

先日、開催されたWWDC2023はVison Proで大盛り上がりでしたね!(早く開発したくてうずうずしてます!)

他にも色々なアップデートがありました。個人的にVisionPro以外にこれは!と思ったのがSwiftUIのMetalサポートです!早速触ってみました!

まずは新規でSwiftUIのプロジェクトを作成後、Metalファイルを作成します。
SwiftUIで使用できるようにSwiftUI_metal.hをincludeします。
Metalで関数を作成します。アトリビュートに[[ stitchable ]]をつけるのを忘れないでください!

第一引数にfloat2型のpositionとすることで、iPhoneのスクリーンのpositionがとれます。
第二引数移行にSwiftUI側から好きな値を流し込めます。

任意のエフェクトをかけてください。(.colorEffectやdistortionEffectなど)このエフェクトの引数にShaderFunctionを取ることができるようになっています。
ShaderFunctionは基本関数名でMetal側の関数を探索するので文字列で適用したい関数名を指定してください。
また、任意の値を渡す場合は型を指定して送ることができます。argumentsの順番はMetal側で受け取る引数の順番にもなっているので気をつけてください!

import SwiftUI

struct ContentView: View {
    @State private var value: Float = 0
    var body: some View {
        ShaderView()
    }
    
    @ViewBuilder
    func ShaderView() -> some View {
        VStack {
            Image(systemName: "apple.logo")
                .resizable()
                .aspectRatio(contentMode: .fit)
                .frame(height: 200)
                .distortionEffect(
                    .init(function: .init(library: .default, name: "effect"),
                          arguments: [.float(value)]),
                    maxSampleOffset: .zero)
                .padding()
            
            Slider(value: $value, in: 1...10)
        }
    }
}



#Preview {
    ContentView()
}

#include <metal_stdlib>
#include "SwiftUI/SwiftUI_Metal.h"
using namespace metal;

[[ stitchable ]] float2 effect(float2 position, float size) {
    float2 pos = round(position / size) * size;
    return pos;
}

Discussion