LogoBanner
GitHubTwitter

Plasma Shader

An electric plasma WebGL shader with purple-pink colors. Creates stunning mathematical wave patterns and energy effects.

Preview

Installation

Option 1: Using CLI (Recommended)

Install this shader directly using the CLI:

npx shaderz add

Select "Plasma" from the list. The component will be added to /components/shaderz/PlasmaShader.tsx.

Option 2: Manual Installation

Copy the component code from the Usage section below.

Required Dependencies

npm install three @types/three framer-motion

Usage

Basic Usage:

'use client';
import { useEffect, useRef } from 'react';
function PlasmaShader() {
const canvasRef = useRef<HTMLCanvasElement>(null);
const glRef = useRef<WebGLRenderingContext | null>(null);
const programRef = useRef<WebGLProgram | null>(null);
const animationRef = useRef<number | null>(null);
useEffect(() => {
const canvas = canvasRef.current;
if (!canvas) return;
const gl = canvas.getContext('webgl');
glRef.current = gl;
if (!gl) {
console.error('WebGL not supported');
return;
}
const resizeCanvas = () => {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
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;
vec3 plasma(vec2 uv, float time) {
float v = 0.0;
vec2 c = uv;
v += sin((c.x + time) * 2.0);
v += sin((c.y + time) * 3.0);
v += sin((c.x + c.y + time) * 2.0);
c += vec2(sin(time * 0.5) * 2.0, cos(time * 0.3) * 2.0);
v += sin(sqrt(c.x * c.x + c.y * c.y + 1.0) + time);
return vec3(
sin(v * 3.14159),
sin(v * 3.14159 + 2.094),
sin(v * 3.14159 + 4.188)
) * 0.5 + 0.5;
}
void main() {
vec2 uv = (gl_FragCoord.xy - 0.5 * resolution.xy) / resolution.y;
uv *= 2.0;
vec3 color = plasma(uv, time * 0.8);
// Add some glow effect
float glow = 1.0 - length(uv) * 0.3;
color *= glow;
// Purple-pink gradient overlay
vec3 purpleGradient = mix(
vec3(0.4, 0.1, 0.8),
vec3(0.8, 0.2, 0.6),
(uv.y + 1.0) * 0.5
);
color = mix(color, purpleGradient, 0.3);
gl_FragColor = vec4(color, 0.9);
}
`;
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;
}
programRef.current = program;
const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
const positions = new Float32Array([
-1, -1,
1, -1,
-1, 1,
1, 1
]);
gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);
const positionLocation = gl.getAttribLocation(program, 'position');
const resolutionLocation = gl.getUniformLocation(program, 'resolution');
const timeLocation = gl.getUniformLocation(program, 'time');
gl.enable(gl.BLEND);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
const render = (time: number) => {
time *= 0.001;
gl.clearColor(0, 0, 0, 0);
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, time);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
animationRef.current = requestAnimationFrame(render);
};
animationRef.current = requestAnimationFrame(render);
return () => {
window.removeEventListener('resize', resizeCanvas);
if (animationRef.current) {
cancelAnimationFrame(animationRef.current);
}
};
}, []);
return (
<div className="absolute inset-0 w-full h-full bg-black overflow-hidden">
<canvas
ref={canvasRef}
className="absolute top-0 left-0 w-full h-full pointer-events-none opacity-95"
/>
</div>
);
}
export default PlasmaShader;

Hero Section Background Example:

app/page.tsx
import PlasmaShader from '@/components/shaderz/PlasmaShader';
export default function Home() {
return (
<section className="relative min-h-screen">
{/* Shader background */}
<div className="absolute inset-0 -z-10">
<PlasmaShader />
</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>
);
}

Features

  • Mathematical Patterns: Uses sine waves and mathematical functions for realistic plasma effects
  • Dynamic Colors: Purple-pink gradient that shifts and flows
  • Glow Effects: Built-in radial glow and energy visualization
  • Smooth Animation: Continuous flowing motion

Customization

Customize the plasma effect by modifying:

  • Wave Frequency: Adjust the sine wave frequencies for different patterns
  • Color Gradient: Change the purple-pink gradient to any color scheme
  • Glow Intensity: Modify the radial glow strength
  • Animation Speed: Control the plasma flow speed

Technical Details

The shader uses:

  • Multiple sine wave overlays
  • Radial distance calculations for glow effects
  • Time-based animation for continuous motion
  • Optimized fragment shader for performance