它在做什么
GLITCH INDEX 把文本输入当成实验材料。速度决定时间采样,扰动改变切片位移,颜色选择控制两个通道的对比关系。目标不是模拟随机故障,而是让每一个失真参数都可以被解释、复现和撤销。
关键实现
离屏 Canvas 先使用 Archivo Variable 的 wdth 宽度轴排出一份清晰字形,并上传为 GPU 纹理。fragment shader 按水平扫描线采样纹理,以时间相位、焦点和文字 seed 产生受控位移;暖色与蓝色通道朝相反方向偏移,同时保留稳定主体维持可读性。输入框本身始终是原生表单控件,因此键盘、触摸和输入法不依赖 Canvas 命中测试。
性能与降级
循环在离屏或页面隐藏时停止。reduced-motion 会释放 WebGL renderer,保留由同一文字、色彩和 wdth 轴参数驱动的静态 DOM 版本。动态效果只重绘实验区域,控制面板更新不会触发页面级布局;脚本或 WebGL 失败时仍可编辑文字并理解当前参数。
浏览器兼容
支持 WebGL 1.0 的现代浏览器运行 shader 版本;context lost 时立即切回 DOM,并在上下文恢复后重新初始化。变量字体不可用时会回退到系统无衬线字体,WebGL 不可用时保留静态字形、双色通道与全部原生控件。
KEY SOURCE / LIVE IMPLEMENTATION
运行源码节选
这不是为文档复制的示例。构建过程直接读取当前实验使用的 TypeScript 文件,并提取下方标记区段。
const FRAGMENT_SHADER_SOURCE = `
precision highp float;
varying vec2 vUv;
uniform sampler2D uGlyph;
uniform vec2 uFocus;
uniform float uPhase;
uniform float uDistortion;
uniform float uPulse;
uniform float uSeed;
uniform vec3 uAccent;
float hash11(float value) {
return fract(sin(value * 91.173 + uSeed * 0.013) * 43758.5453);
}
void main() {
float line = floor(vUv.y * mix(96.0, 30.0, uDistortion));
float timeSlice = floor(uPhase * 9.0);
float burst = step(0.54, hash11(line + timeSlice));
float focusWeight = max(0.12, 1.0 - abs(vUv.y - uFocus.y) * 2.35);
float maximumShift = (0.003 + uDistortion * 0.072 + uPulse * 0.038) * focusWeight;
float direction = hash11(line * 1.7 + timeSlice * 0.31) * 2.0 - 1.0;
float shift = direction * maximumShift * mix(0.08, 1.0, burst);
vec2 baseUv = vec2(vUv.x + shift, vUv.y);
float body = texture2D(uGlyph, baseUv).r;
float warm = texture2D(uGlyph, vec2(baseUv.x + maximumShift * 0.34, vUv.y)).r;
float cool = texture2D(uGlyph, vec2(baseUv.x - maximumShift * 0.26, vUv.y)).r;
vec3 paper = vec3(0.953, 0.941, 0.914);
vec3 blue = vec3(0.08, 0.28, 1.0);
vec3 color = vec3(0.063, 0.075, 0.094);
color += body * paper * 0.92;
color += warm * uAccent * (0.16 + uDistortion * 0.72);
color += cool * blue * (0.12 + uDistortion * 0.58);
float scanline = 0.965 + 0.035 * sin(vUv.y * 900.0 + uPhase * 3.0);
gl_FragColor = vec4(clamp(color * scanline, 0.0, 1.0), 1.0);
}
`; 生产 fragment shader 直接读取速度、扰动、焦点、文字 seed 与颜色通道,没有第二份演示实现。