Skip to content

Instantly share code, notes, and snippets.

@Priva28
Last active February 8, 2024 00:40
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Priva28/c4becef12fd8dd399cc769f2c7a5c246 to your computer and use it in GitHub Desktop.
Save Priva28/c4becef12fd8dd399cc769f2c7a5c246 to your computer and use it in GitHub Desktop.
SwiftUI CRT effect using metal shaders.
import SwiftUI
struct ContentView: View {
@State private var startDate = Date()
var body: some View {
VStack {
GeometryReader { geo in
ZStack {
TimelineView(.animation) { _ in
Image("someImage")
.resizable()
.scaledToFill()
.blur(radius: 1.2)
.layerEffect(
ShaderLibrary.crtEffect(
.float(-startDate.timeIntervalSinceNow),
.float2(geo.size)
),
maxSampleOffset: .zero
)
.opacity(0.4)
}
}
.overlay(
Text("Some content")
.fontWidth(.expanded)
.fontWeight(.heavy)
.minimumScaleFactor(0.5)
.foregroundStyle(.white)
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .leading)
.padding(24)
.layerEffect(
ShaderLibrary.crtEffect(
.float(-startDate.timeIntervalSinceNow),
.float2(geo.size)
),
maxSampleOffset: .zero
)
)
}
.aspectRatio(1, contentMode: .fit)
Spacer()
}
.background(
RadialGradient(stops: [
.init(color: .white.opacity(0.2), location: 0),
.init(color: .black, location: 1)
], center: .center, startRadius: 10, endRadius: 1000)
)
}
}
#include <metal_stdlib>
#include <SwiftUI/SwiftUI.h>
using namespace metal;
float2 distort(float2 uv, float strength) {
float2 dist = 0.5 - uv;
uv.x = (uv.x - dist.y * dist.y * dist.x * strength);
uv.y = (uv.y - dist.x * dist.x * dist.y * strength);
return uv;
}
[[stitchable]]
half4 crtEffect(float2 position, SwiftUI::Layer layer, float time, float2 size) {
float2 uv = position / size;
uv = distort(uv, 0.3);
// render color
half4 col;
col.r = layer.sample(float2(uv.x, uv.y) * size).r;
col.g = layer.sample(float2(uv.x, uv.y) * size).g;
col.b = layer.sample(float2(uv.x, uv.y) * size).b;
col.a = layer.sample(float2(uv.x, uv.y) * size).a;
// brighten image
col *= half4(0.95, 1.05, 0.95, 1);
col *= 2.8;
// add scan lines
float scans = clamp(0.35 + 0.35 * sin(3.5 * time + uv.y * size.y * 1.5), 0.0, 1.0);
float s = pow(scans, 1.7);
float sn = 0.4 + 0.7 * s;
col = col * half4(sn, sn, sn, 1);
// normalise color
col *= 1.0 + 0.01 * sin(110.0 * time);
float c = clamp((fmod(position.x, 2.0) - 1.0) * 2.0, 0.0, 1.0);
col *= 1.0 - 0.65 * half4(c, c, c, 1);
return col;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment