SwiftUIのViewにMetalのシェーダーを適用する
トピック
distortionEffect,colorEffect,layerEffectが追加された(iOS17)
これらはMetalシェーダーを渡してViewに効果を適用することが出来る。
共通
いずれも引数にShader
を取る。
Shader
はShaderFunction
とカスタム引数からなる。
ShaderFunction
はMetalで定義されたシェーダを扱うための型である。
これらのmodifierから使用されるシェーダー側(.metalファイル)では
#include <metal_stdlib>
#include <SwiftUI/SwiftUI_Metal.h>
のように
#include <SwiftUI/SwiftUI_Metal.h>
が必要になる
またこれらのmodifierから使用されるシェーダー関数はいずれも[[ stitchable ]]
属性を指定する必要がある。
[[stitchable]] half4 shaderFunctionName(float4 position, ...)
ShaderFunction
を取得するにはShaderLibrary
のdynamicMemberLookup機能で、さもShaderLibrary
のメンバのように取得できる。
let shader = ShaderLibrary.shaderFunctionName
もちろん普通にイニシャライザでShaderFunction
を作ることも出来る。
let shader = ShaderFunction(ShaderLibrary.standard, "shaderFunctionName")
参考:
distortionEffect
ピクセル座標を移動する
- 入力:ピクセル座標
- 出力:ピクセル座標
シェーダーのシグネチャ
関数名は任意
[[ stitchable ]] float2 distShader(float2 position, ...)
Swift側呼び出し例
Image(systemName: "figure.run.circle.fill")
.font(.system(size: 300))
.distortionEffect(ShaderLibrary.distShader(.float(startDate.timeIntervalSinceNow)), maxSampleOffset: .zero)
colorEffect
ピクセルが出力する色を指定する
- 入力:ピクセル座標と通常出力されるはずの色
- 出力:表示する色
シェーダーのシグネチャ
関数名は任意
[[ stitchable ]] half4 colorShader(float2 position, half4 currentColor,...)
Swift側呼び出し例
Image(systemName: "figure.run.circle.fill")
.font(.system(size: 300))
.colorEffect(ShaderLibrary.colorShader(.float(10), .color(.blue)))
試したところ、visionOSのModel3Dのようなものには適用できないらしく、シミュレーター上では🚫マークがビュー全体に表示される
(すでにRealityKitなどでシェーダーが走るから?)
ただ、その🚫マークにはシェーダが適用される
layerEffect
ピクセルが出力する色を指定する
- 入力:ピクセル座標と画像サンプラー
- 出力:表示する色
シェーダーのシグネチャ
関数名は任意
SwiftUI::Layer
を指定してサンプラーとすることも出来るようだ。
[[ stitchable ]] half4 layerShader(float2 position, SwiftUI::Layer layer,...) {
...
half4 currentColor = layer.sample(position);
...
}
Swift側呼び出し例
Image(systemName: "figure.run.circle.fill")
.font(.system(size: 300))
.layerEffect(ShaderLibrary.layerShader(.float(10)), maxSampleOffset: .zero)
それぞれCoreImageの
CIWarpKernel
CIColorKernel
に相当するものだと思えば良いだろうか。
CIKernelは現在はMetalをサポートしているが、更に昔にはCore Image Kernel LanguageとかGLSLでも書けた。