59 lines
2.1 KiB
GLSL
59 lines
2.1 KiB
GLSL
precision mediump float;
|
|
|
|
uniform float u_time;
|
|
uniform vec2 u_resolution;
|
|
uniform sampler2D u_charTexture;
|
|
uniform vec2 u_charPos; // Normalized 0-1 (Bottom-Left)
|
|
uniform vec2 u_charSize; // Normalized 0-1 (Width, Height)
|
|
|
|
varying vec2 vUv;
|
|
|
|
// reliable pseudo-random hash
|
|
float random(vec2 p) {
|
|
vec3 p3 = fract(vec3(p.xyx) * .1031);
|
|
p3 += dot(p3, p3.yzx + 33.33);
|
|
return fract((p3.x + p3.y) * p3.z);
|
|
}
|
|
|
|
void main() {
|
|
// Correct UV for aspect ratio if needed, but here we work in screen space mostly
|
|
|
|
// Background Noise
|
|
// Use floor to ensure we are sampling integer grid, making it purely pixel-noise
|
|
vec2 gridPos = floor(gl_FragCoord.xy);
|
|
float bgNoise = random(gridPos);
|
|
float val = step(0.5, bgNoise);
|
|
|
|
// Character Composition
|
|
vec2 charEnd = u_charPos + u_charSize;
|
|
bool inBox = (vUv.x >= u_charPos.x && vUv.x <= charEnd.x &&
|
|
vUv.y >= u_charPos.y && vUv.y <= charEnd.y);
|
|
|
|
if (inBox) {
|
|
vec2 texUv = (vUv - u_charPos) / u_charSize;
|
|
texUv.y = 1.0 - texUv.y;
|
|
|
|
vec4 texColor = texture2D(u_charTexture, texUv);
|
|
|
|
// Hard threshold to avoid any smooth edges revealing the shape
|
|
if (texColor.a > 0.5) {
|
|
// Inner Character Noise - Scrolls Down
|
|
float scrollSpeed = 200.0;
|
|
// Calculate scrolled position
|
|
vec2 scrollCoords = gl_FragCoord.xy;
|
|
scrollCoords.y += u_time * scrollSpeed;
|
|
|
|
// IMPORTANT: Floor the scrolled coordinates!
|
|
// This ensures the noise "pixels" look exactly like the background "pixels" in size and sharpness.
|
|
// If we don't floor, we get sub-pixel sampling which might look different (smooth/shimmering).
|
|
vec2 charGridPos = floor(scrollCoords);
|
|
|
|
// Use different seed offset to distinguish content, but same distribution
|
|
float charNoise = random(charGridPos + vec2(42.0, 99.0));
|
|
val = step(0.5, charNoise);
|
|
}
|
|
}
|
|
|
|
gl_FragColor = vec4(vec3(1.0 - val), 1.0);
|
|
}
|