Skip to content

Instantly share code, notes, and snippets.

@Enie
Last active August 19, 2024 14:28
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;
constant float4 gray = {0.73,0.73,0.73,1.0};
constant float4 brushMetalGray = {0.85,0.85,0.85,0.66};
// draw long bright sine waves on gray background
// 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));
float4 mixed = mix(gray, brushMetalGray, pattern); // there is something wrong here and in the next line where mixed is used, but it looks good, so i'll leave it like that for now.
return half4((1 - mixed) * brushMetalGray + mixed * gray - sin(position.x/size.x*M_PI_F - M_PI_F)*0.4-0.2);
}
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