#ifdef GL_ES precision highp float; #endif uniform vec2 uGridDims; uniform vec2 uCubeSize; uniform float uVoxelateProgress; uniform vec2 uRippleCenter; uniform float uEffectSpread; uniform float uEffectDepth; uniform float uOrganicMode; uniform float uUseRandomDepth; uniform float uUsePixelate; uniform float uUseRGBShift; attribute float aRandomDepth; varying vec2 vUv; varying vec3 vNormal; varying float vHighlightStrength; varying float vGlitchStrength; const float PI = 3.141592653589793; const float SUPPRESSION_RANGE = 0.05; const float NORMAL_DAMPING = 6.0; const float SLOW_DAMPING = 2.0; const float PIXELATION_TIME = 0.9; float random(vec2 st) { return fract(sin(dot(st.xy, vec2(12.9898, 78.233))) * 43758.5453123); } float elasticOut(float t, float p, float damp_exp) { float tClamped = clamp(t, 0.0, 1.0); if(tClamped <= 0.0001) return 0.0; if(tClamped >= 0.9999) return 1.0; return pow(2.0, -damp_exp * tClamped) * sin((tClamped - p / 4.0) * (2.0 * PI) / p) + 1.0; } void main() { // --- 1. Get basic instance information --- float instanceId = float(gl_InstanceID); float col = mod(instanceId, uGridDims.x); float row = floor(instanceId / uGridDims.x); vec2 uvStep = 1.0 / uGridDims; vec2 baseUv = vec2(col, row) * uvStep; vec2 centerUv = baseUv + (uvStep * 0.5); float gridAspect = uGridDims.x / uGridDims.y; vec2 aspectVec = vec2(gridAspect, 1.0); float distFromCenter = distance(centerUv * aspectVec, uRippleCenter * aspectVec); float rndPhase = random(vec2(instanceId, 123.456)); float rndBounce = random(vec2(instanceId, 987.654)); // --- 2. Animation Progress (Wave Progress) // A. Organic Mode (Noise, Elastic) float noisyDist = max(0.0, distFromCenter + (rndPhase - 0.5) * 0.3); float progressOrganic = clamp((uVoxelateProgress - noisyDist) / uEffectSpread, 0.0, 1.0); float suppression = 1.0 - smoothstep(0.0, SUPPRESSION_RANGE, noisyDist); float currentDamp = mix(NORMAL_DAMPING, SLOW_DAMPING, suppression); float valOrganic = elasticOut(progressOrganic, 0.2 + rndPhase * 0.2, currentDamp); float bounceDiff = max(0.0, valOrganic - 1.0); valOrganic += bounceDiff * (uEffectDepth + rndBounce * 1.1); float highlightOrganic = step(0.01, bounceDiff) * smoothstep(0.0, 0.35, 1.0 - progressOrganic) * (0.5 + rndPhase * 0.5); // B. Smooth Mode (No-Noise, Sine) float progressSmooth = smoothstep(distFromCenter, distFromCenter + uEffectSpread, uVoxelateProgress); float valSmoothBounce = sin(progressSmooth * PI) * step(progressSmooth, 0.99); float valSmooth = progressSmooth + (valSmoothBounce * uEffectDepth); float highlightSmooth = valSmoothBounce; float finalScaleVal = mix(valSmooth, valOrganic, uOrganicMode); vHighlightStrength = mix(highlightSmooth, highlightOrganic, uOrganicMode); // --- 3. UV Coordinates (Pixelate and Glitch) --- vec3 nMask = step(0.5, abs(normal)); vec2 faceCoords = (position.zy * nMask.x) + (position.xz * nMask.y) + (position.xy * nMask.z); vec2 localRatio = clamp((faceCoords / uCubeSize.x) + 0.5, 0.0, 1.0); vec2 smoothUv = baseUv + (localRatio * uvStep); float effectiveProgress = mix(progressSmooth, progressOrganic, uOrganicMode); float pixelPhase = smoothstep(0.0, PIXELATION_TIME, effectiveProgress); float glitchIntensity = pow(sin(pixelPhase * PI), 0.5); vec2 noiseOffset = vec2(random(vec2(instanceId + pixelPhase * 100.0, 0.0)), random(vec2(instanceId + pixelPhase * 100.0, 1.0))) - 0.5; vec2 pixelateUv = mix(smoothUv, centerUv, pixelPhase) + (noiseOffset * glitchIntensity * 0.3); vUv = mix(smoothUv, pixelateUv, uUsePixelate); vGlitchStrength = glitchIntensity * uUseRGBShift; // --- 4. Coordinate Transformation (Depth) --- float baseDepth = 0.05; float targetDepth = mix(1.0, aRandomDepth, uUseRandomDepth); float currentDepth = baseDepth + (targetDepth - baseDepth) * finalScaleVal; vec3 transformed = position; transformed.z *= currentDepth; vNormal = normalize((instanceMatrix * vec4(normal, 0.0)).xyz); gl_Position = projectionMatrix * modelViewMatrix * instanceMatrix * vec4(transformed, 1.0); }