Skip to content

Instantly share code, notes, and snippets.

@juliendargelos
Created April 20, 2025 11:27
Show Gist options
  • Save juliendargelos/dee3d4ee0ff67c203b9f45cff19701cf to your computer and use it in GitHub Desktop.
Save juliendargelos/dee3d4ee0ff67c203b9f45cff19701cf to your computer and use it in GitHub Desktop.
Adaptation of the native GLSL mix function, leveraging native GLSL vector algebra and swizzling for cyclic linear or smooth (sigmoid) interpolation across vector components. Also includes 2-3-4-colors cyclic gradient functions based on cycleMix and smoothCycleMix.
#include cycle-mix.glsl
vec4 cycleGradient(vec4 a, vec4 b, float x) {
x *= 0.5;
return vec4(
cycleMix(vec2(a.x, b.x), x),
cycleMix(vec2(a.y, b.y), x),
cycleMix(vec2(a.z, b.z), x),
cycleMix(vec2(a.w, b.w), x)
);
}
vec4 cycleGradient(vec4 a, vec4 b, vec4 c, float x) {
x *= 0.6666667;
return vec4(
cycleMix(vec3(a.x, b.x, c.x), x),
cycleMix(vec3(a.y, b.y, c.y), x),
cycleMix(vec3(a.z, b.z, c.z), x),
cycleMix(vec3(a.w, b.w, c.w), x)
);
}
vec4 cycleGradient(vec4 a, vec4 b, vec4 c, vec4 d, float x) {
x *= 0.75;
return vec4(
cycleMix(vec4(a.x, b.x, c.x, d.x), x),
cycleMix(vec4(a.y, b.y, c.y, d.y), x),
cycleMix(vec4(a.z, b.z, c.z, d.z), x),
cycleMix(vec4(a.w, b.w, c.w, d.w), x)
);
}
/**
* Linear interpolation between the components of a vector based on x ∈ [0; 1],
* cycling through its components then wrapping back to the first one,
* and repeating periodically when x ∈ ℝ \ [0; 1].
*/
float cycleMix(vec2 v, float x) {
float t = mod(x, 1.) * 2.;
float i = floor(t);
return dot(mix(v, v.yx, fract(t)), vec2(
1. - step(1., i),
step(1., i)
));
}
float cycleMix(vec3 v, float x) {
float t = mod(x, 1.) * 3.;
float i = floor(t);
return dot(mix(v, v.yzx, fract(t)), vec3(
1. - step(1., i),
step(1., i) * (1. - step(2., i)),
step(2., i)
));
}
float cycleMix(vec4 v, float x) {
float t = mod(x, 1.) * 4.;
float i = floor(t);
return dot(mix(v, v.yzwx, fract(t)), vec4(
1. - step(1., i),
step(1., i) * (1. - step(2., i)),
step(2., i) * (1. - step(3., i)),
step(3., i)
));
}
#include smooth-cycle-mix.glsl
vec4 smoothCycleGradient(vec4 a, vec4 b, float x) {
x *= 0.5;
return vec4(
smoothCycleMix(vec2(a.x, b.x), x),
smoothCycleMix(vec2(a.y, b.y), x),
smoothCycleMix(vec2(a.z, b.z), x),
smoothCycleMix(vec2(a.w, b.w), x)
);
}
vec4 smoothCycleGradient(vec4 a, vec4 b, vec4 c, float x) {
x *= 0.6666667;
return vec4(
smoothCycleMix(vec3(a.x, b.x, c.x), x),
smoothCycleMix(vec3(a.y, b.y, c.y), x),
smoothCycleMix(vec3(a.z, b.z, c.z), x),
smoothCycleMix(vec3(a.w, b.w, c.w), x)
);
}
vec4 smoothCycleGradient(vec4 a, vec4 b, vec4 c, vec4 d, float x) {
x *= 0.75;
return vec4(
smoothCycleMix(vec4(a.x, b.x, c.x, d.x), x),
smoothCycleMix(vec4(a.y, b.y, c.y, d.y), x),
smoothCycleMix(vec4(a.z, b.z, c.z, d.z), x),
smoothCycleMix(vec4(a.w, b.w, c.w, d.w), x)
);
}
/**
* Sigmoid interpolation between the components of a vector based on x ∈ [0; 1],
* cycling through its components then wrapping back to the first one,
* and repeating periodically when x ∈ ℝ \ [0; 1].
*/
float smoothCycleMix(vec2 v, float x) {
float t = mod(x, 1.) * 2.;
float i = floor(t);
return dot(mix(v, v.yx, smoothstep(0., 1., fract(t))), vec2(
1. - step(1., i),
step(1., i)
));
}
float smoothCycleMix(vec3 v, float x) {
float t = mod(x, 1.) * 3.;
float i = floor(t);
return dot(mix(v, v.yzx, smoothstep(0., 1., fract(t))), vec3(
1. - step(1., i),
step(1., i) * (1. - step(2., i)),
step(2., i)
));
}
float smoothCycleMix(vec4 v, float x) {
float t = mod(x, 1.) * 4.;
float i = floor(t);
return dot(mix(v, v.yzwx, smoothstep(0., 1., fract(t))), vec4(
1. - step(1., i),
step(1., i) * (1. - step(2., i)),
step(2., i) * (1. - step(3., i)),
step(3., i)
));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment