SwiftUI Shader Simple Lens
With SwiftUI it is easy to add Metal shaders and with this example a simple lens effect is created. The simple lens shader is implemented in a `.metal` file. The function name is defined as `simpleLens`. To use it in SwiftUI, the modifier `.visualEffect` is used. `simpleLens` is automatically available as part of the `ShaderLibrary` type.
import SwiftUI
struct SampleShaderLensView: View {
@State private var loc = CGPoint.zero
var body: some View {
ZStack {
Image("mtfuji")
.resizable()
.scaledToFill()
Text("富士山\nMount Fuji")
.font(.largeTitle)
.bold()
}
.drawingGroup()
.visualEffect { content, proxy in
content
.layerEffect(
ShaderLibrary.simpleLens(
.float2(proxy.size.applying(CGAffineTransform(scaleX: 0.3, y: 0.3))),
.float2(loc),
.float(0.15),
.float(1.5)
),
maxSampleOffset: .zero
)
}
.gesture(
DragGesture(minimumDistance: 0)
.onChanged { loc = $0.location }
)
}
}
#Preview {
SampleShaderLensView()
}
#include#include using namespace metal; [[ stitchable ]] half4 simpleLens( float2 position, SwiftUI::Layer layer, float2 size, float2 pos, float maxDistance, float zoomFactor ) { half2 norm = half2(position / size); half2 center = half2(pos / size); half2 d = norm - center; half ar = size.x / size.y; half distance = (d.x * d.x) + (d.y * d.y) / ar / ar; half zm = 1.0h; if (distance < maxDistance) { zm /= zoomFactor; } half2 p = d * zm + center; return layer.sample(float2(p) * size); }