Gradient Waves Shader
Sleek minimalist waves with smooth gradients in blue and purple
Sleek minimalist waves with smooth gradients in blue and purple
Option 1: Using CLI (Recommended)
Install this shader directly using the CLI:
npx shaderz add
Select "Gradient Waves" from the list. The component will be added to /components/shaderz/GradientWavesShader.tsx.
Option 2: Manual Installation
Copy the component code from the Usage section below.
npm install three @types/three framer-motion
Basic Usage:
Basic Usage:
'use client';import React, { useRef, useEffect } from 'react';const GradientWavesShader: React.FC = () => {const canvasRef = useRef<HTMLCanvasElement>(null);const containerRef = useRef<HTMLDivElement>(null);const animationRef = useRef<number | null>(null);useEffect(() => {const canvas = canvasRef.current;const container = containerRef.current;if (!canvas || !container) return;const gl = canvas.getContext('webgl2') || canvas.getContext('webgl');if (!gl) return;const resizeCanvas = () => {const rect = container.getBoundingClientRect();canvas.width = rect.width;canvas.height = rect.height;gl.viewport(0, 0, canvas.width, canvas.height);};resizeCanvas();window.addEventListener('resize', resizeCanvas);const vertexShaderSource = `attribute vec2 position;void main() {gl_Position = vec4(position, 0.0, 1.0);}`;const fragmentShaderSource = `precision highp float;uniform vec2 resolution;uniform float time;// Improved hashfloat hash(float n) {return fract(sin(n) * 43758.5453123);}// 2D rotation matrixmat2 rot(float a) {float c = cos(a), s = sin(a);return mat2(c, -s, s, c);}// Smooth value noisefloat noise(vec2 p) {vec2 i = floor(p);vec2 f = fract(p);f = f * f * (3.0 - 2.0 * f);float a = hash(i.x + i.y * 57.0);float b = hash(i.x + 1.0 + i.y * 57.0);float c = hash(i.x + (i.y + 1.0) * 57.0);float d = hash(i.x + 1.0 + (i.y + 1.0) * 57.0);return mix(mix(a, b, f.x), mix(c, d, f.x), f.y);}// Layered fbmfloat fbm(vec2 p) {float v = 0.0;float a = 0.5;vec2 shift = vec2(100.0);for(int i = 0; i < 5; i++) {v += a * noise(p);p = rot(0.5) * p * 2.0 + shift;a *= 0.5;}return v;}// Ribbon-like wave patternfloat ribbonWave(vec2 p, float time, float index) {float freq = 2.0 + index * 0.5;float phase = time * (0.3 + index * 0.1);// Sinusoidal waves with offsetfloat wave = sin(p.x * freq + phase) * 0.5 + 0.5;wave *= sin(p.x * freq * 1.5 - phase * 0.8) * 0.5 + 0.5;// Add vertical componentfloat yWave = sin(p.y * (freq * 0.5) + phase * 0.5) * 0.3;return wave + yWave;}// Distance to ribbonfloat ribbonDist(vec2 p, float time, float index) {float offset = index * 0.3 - 0.6;float wave = ribbonWave(p, time, index);float centerY = sin(p.x * (1.5 + index * 0.3) + time * (0.4 + index * 0.1)) * 0.4 + offset;float width = 0.15 + sin(time * 0.5 + index) * 0.05;float dist = abs(p.y - centerY - wave * 0.2);return smoothstep(width, 0.0, dist);}void main() {vec2 uv = gl_FragCoord.xy / resolution.xy;vec2 p = (uv - 0.5) * 2.0;p.x *= resolution.x / resolution.y;float t = time * 0.4;// Add subtle flow distortionvec2 flow = vec2(fbm(p * 1.5 + t * 0.2) - 0.5,fbm(p * 1.5 - t * 0.15) - 0.5) * 0.3;vec2 distorted = p + flow;// Multiple ribbon waves with depthfloat ribbons = 0.0;vec3 color = vec3(0.0);for(int i = 0; i < 5; i++) {float fi = float(i);float ribbon = ribbonDist(distorted, t, fi);// Depth-based coloringfloat depth = fi / 5.0;// Gradient colors - deep blue to violet to pinkvec3 c1 = vec3(0.1, 0.15, 0.4); // Deep bluevec3 c2 = vec3(0.3, 0.2, 0.6); // Violetvec3 c3 = vec3(0.5, 0.25, 0.7); // Purplevec3 c4 = vec3(0.7, 0.3, 0.8); // Light purplevec3 ribbonColor = mix(c1, c2, depth);ribbonColor = mix(ribbonColor, c3, smoothstep(0.3, 0.7, depth));ribbonColor = mix(ribbonColor, c4, smoothstep(0.7, 1.0, depth));// Add gradient variation based on positionfloat gradientShift = sin(distorted.x * 2.0 + t + fi) * 0.5 + 0.5;ribbonColor = mix(ribbonColor, ribbonColor * 1.3, gradientShift * 0.4);// Brightness based on wave positionfloat brightness = ribbonWave(distorted, t, fi);ribbonColor *= 0.7 + brightness * 0.3;// Accumulate with depth sortingcolor = mix(color, ribbonColor, ribbon * (0.9 - depth * 0.2));ribbons += ribbon;}// Edge highlightingfor(int i = 0; i < 5; i++) {float fi = float(i);float ribbon = ribbonDist(distorted, t, fi);float edge = ribbon * (1.0 - ribbon) * 4.0;// Bright edge glowvec3 edgeColor = vec3(0.4, 0.5, 1.0);color += edgeColor * edge * 0.3;}// Subtle shimmer overlayfloat shimmer = fbm(distorted * 8.0 + vec2(t * 2.0, t));shimmer = pow(shimmer, 4.0);color += vec3(0.6, 0.7, 1.0) * shimmer * ribbons * 0.15;// Vignette for depthfloat vignette = 1.0 - length(uv - 0.5) * 0.5;color *= vignette;// Brightness adjustment for minimalismcolor *= 0.85;gl_FragColor = vec4(color, 1.0);}`;const createShader = (gl: WebGLRenderingContext, type: number, source: string) => {const shader = gl.createShader(type);if (!shader) return null;gl.shaderSource(shader, source);gl.compileShader(shader);if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {console.error('Shader compile error:', gl.getShaderInfoLog(shader));gl.deleteShader(shader);return null;}return shader;};const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexShaderSource);const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSource);if (!vertexShader || !fragmentShader) return;const program = gl.createProgram();if (!program) return;gl.attachShader(program, vertexShader);gl.attachShader(program, fragmentShader);gl.linkProgram(program);if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {console.error('Program link error:', gl.getProgramInfoLog(program));return;}const positionBuffer = gl.createBuffer();gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);gl.bufferData(gl.ARRAY_BUFFER,new Float32Array([-1, -1,1, -1,-1, 1,1, 1,]),gl.STATIC_DRAW);const positionLocation = gl.getAttribLocation(program, 'position');const resolutionLocation = gl.getUniformLocation(program, 'resolution');const timeLocation = gl.getUniformLocation(program, 'time');let startTime = Date.now();const render = () => {if (!gl || !canvas) return;gl.clearColor(0, 0, 0, 1);gl.clear(gl.COLOR_BUFFER_BIT);gl.useProgram(program);gl.enableVertexAttribArray(positionLocation);gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);gl.uniform2f(resolutionLocation, canvas.width, canvas.height);gl.uniform1f(timeLocation, (Date.now() - startTime) / 1000);gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);animationRef.current = requestAnimationFrame(render);};render();return () => {window.removeEventListener('resize', resizeCanvas);if (animationRef.current) {cancelAnimationFrame(animationRef.current);}gl.deleteProgram(program);gl.deleteShader(vertexShader);gl.deleteShader(fragmentShader);gl.deleteBuffer(positionBuffer);};}, []);return (<div ref={containerRef} className="absolute inset-0 w-full h-full bg-black overflow-hidden"><canvasref={canvasRef}className="absolute top-0 left-0 w-full h-full"/></div>);};export default GradientWavesShader;
Hero Section Background Example:
import GradientWavesShader from '@/components/shaderz/GradientWavesShader';export default function Home() {return (<section className="relative min-h-screen">{/* Shader background */}<div className="absolute inset-0 -z-10"><GradientWavesShader /></div>{/* Your hero content */}<div className="relative z-10 flex items-center justify-center min-h-screen"><h1 className="text-6xl font-bold text-white">Welcome to Your Site</h1></div></section>);}