Skip to content

Instantly share code, notes, and snippets.

@Enie
Last active March 14, 2025 03:04
Show Gist options
  • Save Enie/f10f193c3605f6b739e42ec0cd8dfb3e to your computer and use it in GitHub Desktop.
Save Enie/f10f193c3605f6b739e42ec0cd8dfb3e to your computer and use it in GitHub Desktop.
Brushed Metal shader effect for SwiftUI
#include <metal_stdlib>
#include <SwiftUI/SwiftUI_Metal.h>
using namespace metal;
// use Color(0.73,0.73,0.73,1.0) as currentColor for the original brushed look
// draw long bright sine waves on current color
// add up phase in each line to not have the same curve in each line but overlapping brush grooves
[[ stitchable ]] half4 brushedMetal(float2 position, half4 currentColor, float2 size) {
float phaseOffset = cos((position.y*size.x + position.x) / size.x);
float pattern = sin(position.y/size.y + phaseOffset * 12)
+ cos(sin(position.y / size.y));
half4 highlightColor = currentColor+half4(0.12,0.12,0.12,-0.33);
half4 mixed = mix(currentColor, highlightColor, pattern);
return half4(((1 - mixed) * highlightColor + mixed * currentColor - sin(position.x/size.x*M_PI_F - M_PI_F)*0.4-0.2).rgb, currentColor.a);
}
import SwiftUI
@main
struct BrushedMetalDemoApp: App {
var body: some Scene {
WindowGroup {
BrushedMetalView {
ContentView()
}
}
.windowStyle(.hiddenTitleBar)
.windowToolbarStyle(.unified)
}
}
import SwiftUI
struct BrushedMetalView<Content: View>: View {
var content: () -> Content
var body: some View {
GeometryReader { geometry in
content()
.background{
Rectangle()
.ignoresSafeArea()
.colorEffect(ShaderLibrary.brushedMetal(.float2(geometry.size)))
}
}
}
}
struct ContentView: View {
@State var text: String = ""
var body: some View {
VStack {
TextEditor(text: $text)
.padding()
}
.background(Color(cgColor: NSColor.textBackgroundColor.cgColor))
.cornerRadius(8)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.padding()
.shadow(color:.white,radius: 0,y:1)
.shadow(color:.black,radius: 0,y:-1)
}
}
#Preview {
BrushedMetalView {
ContentView()
}
}
@Enie
Copy link
Author

Enie commented Aug 19, 2024

Preview on how it looks like.:
brushed macOS

@helje5
Copy link

helje5 commented Aug 19, 2024

struct BrassMetalModifier: ViewModifier {

  static let darkWindowBackgroundColor =
    CGColor(gray: 50/256, alpha: 1.0)
  
  func body(content: Content) -> some View {
    content.background {
      Color(Self.darkWindowBackgroundColor) // effect works on this
        .overlay {
          GeometryReader { geometry in
            Color.black // no effect??
              .colorEffect(ShaderLibrary.brushedMetal(.float2(geometry.size)))
          }
        }
    }
  }
}
extension View {
  func brushedMetal() -> some View {
    modifier(BrassMetalModifier())
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment