How can I add pixelated effect with distortion?

I am using a distortion but I want to add a pixelated effect where on mouse hover it should clear the pixelated area and give me a distortion effect.

How can I do it?

I am trying this fragment and it is not working

uniform float time;
uniform float progress;
uniform sampler2D uDataTexture;
uniform sampler2D uTexture;

uniform vec4 resolution;
varying vec2 vUv;
varying vec3 vPosition;
float PI = 3.141592653589793238;
void main() {
vec2 newUV = (vUv - vec2(0.5))resolution.zw + vec2(0.5);
vec4 color = texture2D(uTexture,newUV);
vec4 offset = texture2D(uDataTexture,vUv);
float pixelSize = 0.02;
vec2 pixelatedUV = floor(vUv / pixelSize) * pixelSize;
gl_FragColor = vec4(vUv,0.0,1.);
gl_FragColor = vec4(offset.r,0.,0.,1.);
gl_FragColor = color;
gl_FragColor = texture2D(uTexture,newUV - 0.02
offset.rg);
// gl_FragColor = offset;

}

When you say not working, do you mean you get errors in the console?

Can you reproduce your problem in a glitch or codepen?

There isn’t really enough info here to help you…

At initial stage when image loads it should be like below image

Then on hover I want the image to be clear and the effect should work as in the video

Also I am sharing the files

This is app.js

import * as THREE from "three";
import fragment from "./shader/fragment.glsl";
import vertex from "./shader/vertex.glsl";
import GUI from "lil-gui";

function clamp(number, min, max) {
  return Math.max(min, Math.min(number, max));
}

export default class Sketch {
  constructor(options) {
    this.scene = new THREE.Scene();

    this.container = options.dom;
    this.img = this.container.querySelector('img')
    this.width = this.container.offsetWidth;
    this.height = this.container.offsetHeight;
    this.renderer = new THREE.WebGLRenderer({alpha:true});
    console.log("this.renderer", this.renderer);
    // this.renderer.setPixelRatio(window.devicePixelRatio);
    
    this.renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
    this.renderer.setSize(this.width, this.height);
    this.renderer.setClearColor(0xeeeeee, 0);
    this.renderer.physicallyCorrectLights = true;
    this.renderer.outputEncoding = THREE.sRGBEncoding;

    this.container.appendChild(this.renderer.domElement);

    this.camera = new THREE.PerspectiveCamera(
      70,
      window.innerWidth / window.innerHeight,
      0.1,
      100
    );

    var frustumSize = 1; // use to decrease size of image
    var aspect = window.innerWidth / window.innerHeight;
    this.camera = new THREE.OrthographicCamera(frustumSize / -1.8, frustumSize / 1.8, frustumSize / 2, frustumSize / -2, -1000, 1000);
    this.camera.position.set(0, 0, 2);

    this.time = 0;

    this.mouse = {
      x: 0,
      y: 0,
      prevX: 0,
      prevY: 0,
      vX: 0,
      vY: 0
    }

    this.isPlaying = true;
    this.settings();
    this.addObjects();
    this.resize();
    this.render();
    this.setupResize();

    this.mouseEvents()

  }

  getValue(val){
    return parseFloat(this.container.getAttribute('data-'+val))
  }


  mouseEvents() {
    window.addEventListener('mousemove', (e) => {
      this.mouse.x = e.clientX / this.width;
      this.mouse.y = e.clientY / this.height;

      // console.log(this.mouse.x,this.mouse.y)

      this.mouse.vX = this.mouse.x - this.mouse.prevX;
      this.mouse.vY = this.mouse.y - this.mouse.prevY;


      this.mouse.prevX = this.mouse.x
      this.mouse.prevY = this.mouse.y;


      // console.log(this.mouse.vX,'vx')
    })
  }

  settings() {
    let that = this;
    this.settings = {
      grid: this.getValue('grid')||34,
      mouse: this.getValue('mouse')||0.25,
      strength: this.getValue('strength')||1,
      relaxation: this.getValue('relaxation')||0.7,
    pixelRatio: .1
    };


    this.gui = new GUI();

    this.gui.add(this.settings, "grid", 2, 1000, 1).onFinishChange(() => {
      this.regenerateGrid()
    });
    this.gui.add(this.settings, "mouse", 0, 1, 0.01);
    this.gui.add(this.settings, "strength", 0, 1, 0.01);
    this.gui.add(this.settings, "relaxation", 0, 1, 0.01);
  }

  setupResize() {
    window.addEventListener("resize", this.resize.bind(this));
  }

  resize() {
    this.width = this.container.offsetWidth;
    this.height = this.container.offsetHeight;
    this.renderer.setSize(this.width, this.height);
    this.camera.aspect = this.width / this.height;


    // image cover
    this.imageAspect = .18 / .34;
    let a1;
    let a2;
    if (this.height / this.width > this.imageAspect) {
      a1 = (this.width / this.height) * this.imageAspect;
      a2 = 1;
    } else {
      a1 = 1;
      a2 = (this.height / this.width) / this.imageAspect;
    }

    this.material.uniforms.resolution.value.x = this.width;
    this.material.uniforms.resolution.value.y = this.height;
    this.material.uniforms.resolution.value.z = a1;
    this.material.uniforms.resolution.value.w = a2;

    this.camera.updateProjectionMatrix();
    this.regenerateGrid()


  }

  regenerateGrid() {
    this.size = this.settings.grid;

    const width = this.size;
    const height = this.size;

    const size = width * height;
    const data = new Float32Array(3 * size);
    const color = new THREE.Color(0xffffff);

    const r = Math.floor(color.r * 255);
    const g = Math.floor(color.g * 255);
    const b = Math.floor(color.b * 255);

    for (let i = 0; i < size; i++) {
      let r = Math.random() * 255 - 125;
      let r1 = Math.random() * 255 - 125;

      const stride = i * 3;

      data[stride] = r;
      data[stride + 1] = r1;
      data[stride + 2] = r;

    }

    // used the buffer to create a DataTexture

    this.texture = new THREE.DataTexture(data, width, height, THREE.RGBFormat, THREE.FloatType);

    this.texture.magFilter = this.texture.minFilter = THREE.NearestFilter;
    this.texture.generateMipmaps = false
    this.texture.wrapS = THREE.RepeatWrapping
    this.texture.wrapT = THREE.RepeatWrapping

    if (this.material) {
      this.material.uniforms.uDataTexture.value = this.texture;
      this.material.uniforms.uDataTexture.value.needsUpdate = true;
    }
    
  }

  addObjects() {

    this.regenerateGrid()
    let texture = new THREE.Texture(this.img)
    texture.needsUpdate = true;
    this.material = new THREE.ShaderMaterial({
      extensions: {
        derivatives: "#extension GL_OES_standard_derivatives : enable"
      },
      side: THREE.DoubleSide,
      uniforms: {
        time: {
          value: 0
        },
        resolution: {
          value: new THREE.Vector4()
        },
        uTexture: {
          value: texture
        },
        uDataTexture: {
          value: this.texture
        },
      },
      vertexShader: vertex,
      fragmentShader: fragment
    });

    this.geometry = new THREE.PlaneGeometry(1, 1, 1, 1);

    this.plane = new THREE.Mesh(this.geometry, this.material);
    this.scene.add(this.plane);
  }


  updateDataTexture() {
    let data = this.texture.image.data;
    for (let i = 0; i < data.length; i += 3) {
      data[i] *= this.settings.relaxation
      data[i + 1] *= this.settings.relaxation
    }

    let gridMouseX = this.size * this.mouse.x;
    let gridMouseY = this.size * (1 - this.mouse.y);
    let maxDist = this.size * this.settings.mouse;
    let aspect = this.height / this.width

    for (let i = 0; i < this.size; i++) {
      for (let j = 0; j < this.size; j++) {

        let distance = ((gridMouseX - i) ** 2) / aspect + (gridMouseY - j) ** 2
        let maxDistSq = maxDist ** 2;

        if (distance < maxDistSq) {

          let index = 3 * (i + this.size * j);

          let power = maxDist / Math.sqrt(distance);
          power = clamp(power, 0, 10)
          // if(distance <this.size/32) power = 1;
          // power = 1;

          data[index] += this.settings.strength * 100 * this.mouse.vX * power;
          data[index + 1] -= this.settings.strength * 100 * this.mouse.vY * power;

        }
      }
    }

    this.mouse.vX *= 0.9;
    this.mouse.vY *= 0.9;
    this.texture.needsUpdate = true
  }


  render() {
    if (!this.isPlaying) return;
    this.time += 0.05;
    this.updateDataTexture()
    this.material.uniforms.time.value = this.time;
    requestAnimationFrame(this.render.bind(this));
    this.renderer.render(this.scene, this.camera);
  }
}

setTimeout(() => {
  new Sketch({
      dom: document.getElementById("canvasContainer1")
  });
}, 500); // 2000 milliseconds (2 seconds) delay

setTimeout(() => {
  new Sketch({
      dom: document.getElementById("canvasContainer")
  });

}, 2500);

Then this fragment which is showing jelly type distortion effect

uniform float time;
uniform float progress;
uniform sampler2D uDataTexture;
uniform sampler2D uTexture;


uniform vec4 resolution;
varying vec2 vUv;
varying vec3 vPosition;
float PI = 3.141592653589793238;
void main()	{
	vec2 newUV = (vUv - vec2(0.5))*resolution.zw + vec2(0.5);
	vec4 color = texture2D(uTexture,newUV);
	vec4 offset = texture2D(uDataTexture,vUv);
	gl_FragColor = vec4(vUv,0.0,1.);
	gl_FragColor = vec4(offset.r,0.,0.,1.);
	gl_FragColor = color;
	gl_FragColor = texture2D(uTexture,newUV - 0.02*offset.rg);
	// gl_FragColor = offset;

}

Then I have updated the fragment now it is showing the pixelated and jelly effect as well

precision mediump float;

uniform float time;
uniform float progress;
uniform sampler2D uDataTexture;
uniform sampler2D uTexture;

uniform vec4 resolution;
varying vec2 vUv;
varying vec3 vPosition;
float PI = 3.141592653589793238;

void main()	{

	vec2 newUV = (vUv - vec2(0.5))*resolution.zw + vec2(0.5);
	vec4 color = texture2D(uTexture,newUV);
	vec4 offset = texture2D(uDataTexture,vUv);
	
   

    float pixelSize = 0.01;
    vec2 pixelatedUV = floor(vUv / pixelSize) * pixelSize;

    // Apply pixelation
    vec4 pixelatedColor = texture2D(uTexture, pixelatedUV);

    // Apply static distortion to the pixelated color
    float distortion = 0.02;
    vec2 distortedUV = pixelatedUV + distortion * sin(pixelatedUV.y * 10.0);

    // Sample the distorted color
    color = texture2D(uTexture, distortedUV);

    // Output the final color
	gl_FragColor = vec4(vUv,0.0,1.);
	gl_FragColor = vec4(offset.r,0.,0.,1.);
   // gl_FragColor = color;
gl_FragColor = texture2D(uTexture,distortedUV - 0.02*offset.rg);	
}

Please check the video after my second updated fragment

![screen-capture (5)|video](upload://hlqCpcTKtUsOOEiQHFh7cZ9MrzU.webm)

Now I want on hover it should clear from pixelate to normal image with distortion effect

In above msg video was in code now you can view video here