uniform sampler2D uTexture; uniform float uGridSize; uniform float uStrength; uniform vec2 uViewOffset; uniform vec2 uResolution; uniform float uTime; uniform vec2 uPetSize; uniform bool uIsVideo; varying vec2 vUv; varying vec3 vWorldPosition; float hash(vec2 p) { return fract(sin(dot(p, vec2(41.3, 17.9))) * 15731.743); } float noise(vec2 p) { vec2 i = floor(p); vec2 f = fract(p); f = f * f * (3.0 - 2.0 * f); return mix(mix(hash(i), hash(i + vec2(1.0, 0.0)), f.x), mix(hash(i + vec2(0.0, 1.0)), hash(i + vec2(1.0)), f.x), f.y); } vec3 srgbToLinear(vec3 value) { return mix(value / 12.92, pow((value + 0.055) / 1.055, vec3(2.4)), step(vec3(0.04045), value)); } vec4 mediaSample(vec2 uv) { vec3 background = srgbToLinear(vec3(17.0, 25.0, 35.0) / 255.0); if (any(lessThan(uv, vec2(0.0))) || any(greaterThan(uv, vec2(1.0)))) return vec4(background, 1.0); vec4 color = texture2D(uTexture, uv); if (uIsVideo) color.rgb = srgbToLinear(color.rgb); return color; } vec2 hitUv(vec3 ray) { float rayZ = abs(ray.z) < 0.0001 ? (ray.z < 0.0 ? -0.0001 : 0.0001) : ray.z; float signedT = -vWorldPosition.z / rayZ; return (vWorldPosition + ray * signedT).xy / uPetSize + 0.5; } void main() { vec2 stableUv = vUv * (uResolution / max(uResolution.y, 1.0)); vec2 noisePos = stableUv * 9.0 + uViewOffset * 0.6; vec2 randomNormal = vec2(noise(noisePos), noise(noisePos + vec2(23.7))) - vec2(0.5); vec3 incident = normalize(vWorldPosition - cameraPosition); vec3 normal = normalize(vec3(randomNormal * 0.32, 1.0)); vec3 refracted = refract(incident, normal, 0.75); vec2 centerUv = mix(hitUv(incident), hitUv(refracted), clamp(uStrength, 0.0, 1.0)); vec2 radius = vec2(0.008) * clamp(uStrength, 0.0, 1.0); vec4 color = vec4(0.0); color += mediaSample(centerUv + vec2(-radius.x, -radius.y)); color += mediaSample(centerUv + vec2(0.0, -radius.y)); color += mediaSample(centerUv + vec2(radius.x, -radius.y)); color += mediaSample(centerUv + vec2(-radius.x, 0.0)); color += mediaSample(centerUv); color += mediaSample(centerUv + vec2(radius.x, 0.0)); color += mediaSample(centerUv + vec2(-radius.x, radius.y)); color += mediaSample(centerUv + vec2(0.0, radius.y)); color += mediaSample(centerUv + vec2(radius.x, radius.y)); color /= 9.0; color.a = 1.0; gl_FragColor = color; #include }