import { Skia } from "@shopify/react-native-skia"; // Color Shift: cyclic hue/saturation breathing effect // Uniforms: time, intensity, speed export const colorShiftShader = Skia.RuntimeEffect.Make(` uniform shader image; uniform float2 resolution; uniform float time; uniform float intensity; uniform float speed; // RGB to HSL conversion float3 rgb2hsl(float3 c) { float mx = max(c.r, max(c.g, c.b)); float mn = min(c.r, min(c.g, c.b)); float l = (mx + mn) * 0.5; float s = 0.0; float h = 0.0; if (mx != mn) { float d = mx - mn; s = l > 0.5 ? d / (2.0 - mx - mn) : d / (mx + mn); if (mx == c.r) { h = (c.g - c.b) / d + (c.g < c.b ? 6.0 : 0.0); } else if (mx == c.g) { h = (c.b - c.r) / d + 2.0; } else { h = (c.r - c.g) / d + 4.0; } h /= 6.0; } return float3(h, s, l); } float hue2rgb(float p, float q, float t) { float tt = t; if (tt < 0.0) tt += 1.0; if (tt > 1.0) tt -= 1.0; if (tt < 1.0/6.0) return p + (q - p) * 6.0 * tt; if (tt < 1.0/2.0) return q; if (tt < 2.0/3.0) return p + (q - p) * (2.0/3.0 - tt) * 6.0; return p; } float3 hsl2rgb(float3 hsl) { float h = hsl.x; float s = hsl.y; float l = hsl.z; if (s == 0.0) return float3(l); float q = l < 0.5 ? l * (1.0 + s) : l + s - l * s; float p = 2.0 * l - q; return float3( hue2rgb(p, q, h + 1.0/3.0), hue2rgb(p, q, h), hue2rgb(p, q, h - 1.0/3.0) ); } half4 main(float2 coord) { half4 color = image.eval(coord); float3 hsl = rgb2hsl(float3(color.rgb)); float t = time * speed * 0.15; // Shift hue cyclically hsl.x = fract(hsl.x + intensity * 0.1 * sin(t)); // Pulse saturation hsl.y = clamp(hsl.y + intensity * 0.15 * sin(t * 1.3), 0.0, 1.0); // Subtle luminance breathing hsl.z = clamp(hsl.z + intensity * 0.03 * sin(t * 0.8), 0.0, 1.0); float3 rgb = hsl2rgb(hsl); return half4(half3(rgb), color.a); } `)!;