admaDIC App Development & IT Solutions

SwiftUI Shader Rainbow Ring

by Annett Schwarze | 2026-02-13

With SwiftUI it is easy to add Metal shaders and with this example a simple rainbow ring is created. The shader is implemented in a `.metal` file. The function name is defined as `rainbowRing`. To use it in SwiftUI, the modifier `.visualEffect` is used. `rainbowRing` is automatically available as part of the `ShaderLibrary` type.

The ring is determined by computing the distance of the points to be drawn to the center. If that distance is within a small interval, a rainbow color is returned, otherwise the original color is used. To build the rainbow the hue component of a color is determined by calculating the angle of the vector pointing from the center to the position of a ring pixel. An offset allows to shift the angle, which effectively rotates the rainbow ring.

        
import SwiftUI

struct ShaderRainbowRingView: View {
    @State private var offset: Double = 0.5
    var body: some View {
        VStack {
            Text("Rainbow Ring")
                .font(.largeTitle)

            VStack {
                Spacer()
                ZStack {
                    Color.white
                    Image(systemName: "cloud.sun")
                        .resizable()
                        .aspectRatio(contentMode: .fit)
                        .padding(32)
                        .foregroundStyle(Color.gray)
                }
                    .frame(width: 200, height: 200)
                    .visualEffect({ [offset] content, geo in
                        content
                            .colorEffect(
                                ShaderLibrary.rainbowRing(.float2(geo.size), .float(offset))
                            )
                    })
                Spacer()
                Slider(value: $offset, label: { Text("Rainbow Offset") })
                    .padding()
                Text("\(offset)")
            }
        }
    }
}

#Preview {
    ShaderRainbowRingView()
}
    
        
#include 
using namespace metal;

#include 
using namespace metal;

half3 hsv2rgb(half3 c) {
    half4 K = half4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
    half3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
    return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}

[[ stitchable ]]
half4 rainbowRing(
    float2 position,
    half4 color,
    float2 size,
    float offset
) {
    float2 center = size * 0.5;
    float2 uv2 = (position - center) / size * 2;
    float dist = length(uv2);
    if (0.9 < dist && dist < 1.0) {
        float angle = atan2(uv2.y, uv2.x);
        float norm = (angle / M_PI_F + 1) / 2.0;
        float hue = fract(norm + offset);
        half3 rgb = hsv2rgb(half3(hue, 1.0, 1.0));
        return half4(rgb.rgb, 1.0);
    } else {
        return color;
    }
}
    
SwiftUI Shader Rainbow Ring

 

www.admadic.de | webmaster@admadic.de | Legal Notice and Trademarks | Privacy
© 2005-2007 - admaDIC | All Rights Reserved
All other trademarks and/or registered trademarks are the property of their respective owners
Last Change: Fri Feb 13 17:58:07 2026 GMT