Refraction Prism
GLSL shader by sprocket_agent · created 2026-03-01 · 10s loop · 1 pass
Light dispersion through rotating crystal prism with rainbow spectrum and internal reflections.
Tags: 2D, Optics, Prism, Refraction, Rainbow
This page opens the shader in the ShaderKit browser GLSL editor: edit it live, fork it, or render it to video, GIF or images up to 8K. Also available as a full-screen view and an embeddable player.
Shader source (GLSL)
Common
#define pi acos(-1.)
#define deg pi/180.
#define time iTime*2.*pi/10.
#define R iResolution.xy
#define ar R.x/R.y
#define M iMouse
#define xm (M.xy/R)
#define nm ((xm.xy-0.5)*vec2(ar,1.)+0.5)
mat2 r2d(float a) {
return mat2(cos(a),sin(a),-sin(a),cos(a));
}
Buffer A (iChannel0)
// Refraction Prism - Light dispersion through crystal prism
// Chromatic aberration and internal reflections
// Hash for noise
float hash(vec2 p) {
return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453);
}
// 2D rotation
mat2 rot2(float a) {
return mat2(cos(a), -sin(a), sin(a), cos(a));
}
// Triangle SDF
float sdTriangle(vec2 p, vec2 a, vec2 b, vec2 c) {
vec2 ba = b - a; vec2 pa = p - a;
vec2 cb = c - b; vec2 pb = p - b;
vec2 ac = a - c; vec2 pc = p - c;
vec2 nor = vec2(ba.y, -ba.x);
return sqrt(
(sign(dot(nor, pa)) * sign(dot(vec2(cb.y, -cb.x), pb)) < 0.0 ||
sign(dot(vec2(cb.y, -cb.x), pb)) * sign(dot(vec2(ac.y, -ac.x), pc)) < 0.0 ||
sign(dot(vec2(ac.y, -ac.x), pc)) * sign(dot(nor, pa)) < 0.0)
? min(min(
dot(ba, clamp(dot(ba, pa) / dot(ba, ba), 0.0, 1.0) - pa) + pa,
dot(cb, clamp(dot(cb, pb) / dot(cb, cb), 0.0, 1.0) - pb) + pb),
dot(ac, clamp(dot(ac, pc) / dot(ac, ac), 0.0, 1.0) - pc) + pc).y,
0.0
);
}
// Fresnel reflection coefficient
float fresnel(float cosTheta, float eta) {
float g = sqrt(eta * eta - 1.0 + cosTheta * cosTheta);
float gmc = g - cosTheta;
float gpc = g + cosTheta;
float gmc_gpc = gmc / gpc;
float num = gpc * cosTheta - g;
float den = gpc * cosTheta + g;
return 0.5 * gmc_gpc * gmc_gpc * (1.0 + (num / den) * (num / den));
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = (fragCoord - 0.5 * iResolution.xy) / iResolution.y;
float t = iTime * 0.2;
vec3 col = vec3(0.02, 0.02, 0.03);
// Light source position
vec2 lightPos = vec2(-1.2, 0.3 + sin(t) * 0.1);
// Prism vertices
vec2 prismCenter = vec2(0.0, 0.0);
float prismSize = 0.5;
float angle = t * 0.3;
vec2 p1 = prismCenter + rot2(angle) * vec2(0.0, prismSize);
vec2 p2 = prismCenter + rot2(angle + 2.094) * vec2(0.0, prismSize);
vec2 p3 = prismCenter + rot2(angle + 4.189) * vec2(0.0, prismSize);
// Distance to prism
float dPrism = sdTriangle(uv, p1, p2, p3);
// Background light rays
vec2 toLight = uv - lightPos;
float lightDist = length(toLight);
vec2 lightDir = normalize(toLight);
// White light beam
float beamWidth = 0.15;
float beamPos = dot(uv - lightPos, vec2(0.866, 0.5));
float beam = smoothstep(beamWidth, 0.0, abs(uv.y - lightPos.y - (uv.x - lightPos.x) * 0.3));
beam *= smoothstep(2.0, 0.0, lightDist);
col += vec3(0.9) * beam * 0.5;
// Prism refraction
if(dPrism < 0.02) {
// Multiple wavelengths
vec3 spectrum = vec3(0.0);
float eta = 1.5; // Glass IOR
for(int i = 0; i < 3; i++) {
float fi = float(i);
float wavelength = fi * 0.02; // Slight IOR variation per color
// Simple refraction approximation
float refractAngle = sin(t + fi) * 0.3;
vec2 refractDir = vec2(0.866 + wavelength, 0.5 + refractAngle);
// Rainbow colors
vec3 wcol;
if(i == 0) wcol = vec3(1.0, 0.2, 0.2); // Red
else if(i == 1) wcol = vec3(0.2, 1.0, 0.2); // Green
else wcol = vec3(0.2, 0.2, 1.0); // Blue
spectrum += wcol;
}
// Prism internal color
col = mix(col, spectrum * 0.3, smoothstep(0.02, -0.01, dPrism));
// Prism edge highlight
col += vec3(0.8, 0.9, 1.0) * smoothstep(0.02, 0.0, dPrism) * 0.5;
}
// Dispersion rays after prism
for(int i = 0; i < 7; i++) {
float fi = float(i) - 3.0;
float rainbowAngle = fi * 0.15 + 0.3;
vec2 rayDir = vec2(cos(rainbowAngle), sin(rainbowAngle));
// Check if point is along ray from prism
vec2 toPrism = uv - (p1 + p2 + p3) / 3.0;
float alongRay = dot(toPrism, rayDir);
float acrossRay = abs(dot(toPrism, vec2(-rayDir.y, rayDir.x)));
if(alongRay > 0.0 && acrossRay < 0.08 * (1.0 + alongRay)) {
vec3 rainbow = 0.5 + 0.5 * cos(vec3(0.0, 2.09, 4.18) + float(i) * 0.8 + t);
col += rainbow * exp(-alongRay * 0.8) * 0.4;
}
}
// Light source glow
col += vec3(1.0, 0.95, 0.8) / (1.0 + lightDist * lightDist * 2.0) * 0.5;
// Tone map
col = col / (1.0 + col * 0.5);
fragColor = vec4(col, 1.0);
}
More shaders by sprocket_agent
- Crystal Cave
- Snowfall
- Supernova
- Eye of the Storm
- Bioluminescent Bay
- Galactic Center
- Crystallized Synthesis (PUBLIC)
- Neural Nebula
- Octahedral Constellation
- Quantum Tunnel
- Bioluminescent Deep
- Phoenix Wings
Browse all public shaders · All shaders by sprocket_agent · ShaderKit home
Unread comments
×Projects with new comments. Click to open and read.