Pixel Distortion Impact with Three.js

Pixel Distortion Effect with Three.js

From our sponsor: On the lookout for an intuitive whiteboard type challenge administration instrument? Give Shortcut a attempt without cost.

The inventive coder’s dream is to rule pixels on their display. To rearrange them in lovely patterns and do no matter you need with them. Nicely, that is precisely what we’re going to do with this demo. Let’s distort and rule pixels with the facility of our mouse cursor, identical to the builders of the superb Infinite Dangerous Man web site did!


The scene is the same old, we simply create a fullscreen picture on a display, so it preserves the facet ratio, and has its “background-size: cowl” utilized by means of the glsl shader. Ultimately, we’ve got a geometry stretched for the entire viewport, and a bit of shader like this:

vec2 newUV = (vUv - vec2(0.5))*facet + vec2(0.5);
    gl_FragColor = texture2D(uTexture,newUV);

The entire thing simply reveals the picture, no distortions but.

The Magnificent Knowledge Texture

I hope by this time you recognize that any texture in WebGL is principally simply numbers corresponding to every pixel’s coloration.

Three.js has a selected API to create your individual textures pixel by pixel. It’s known as, no shock, DataTexture. So let’s create one other texture for our demo, with random numbers:

    const dimension = rows * columns;
    const knowledge = new Float32Array(3 * dimension);

    for(let i = 0; i < dimension; i++) 
          const stride = i * 3;
          let r = Math.random() * 255 ;
          let r1 = Math.random() * 255 ;

          knowledge[stride] = r; // pink, and in addition X
          knowledge[stride + 1] = r1; // inexperienced, and in addition Y
          knowledge[stride + 2] = 0; // blue
    this.texture = new THREE.DataTexture(knowledge, width, peak, THREE.RGBFormat, THREE.FloatType);

That is closely primarily based on the default instance from the documentation. The one distinction is, we’re utilizing FloatType texture, so we’re not certain to solely integer numbers. One of many attention-grabbing issues is, that numbers must be between 0 and 255, regardless that, within the GLSL it is going to be 0..1 vary anyway. It is best to simply maintain that in thoughts, so you might be utilizing right quantity ranges.

What can also be an attention-grabbing thought, is that GLSL doesn’t actually care what the numbers imply in your knowledge constructions. It could possibly be each coloration.rgb, and coloration.xyz. And that’s exactly what we’ll use right here, we don’t care about actual coloration of this texture, we’ll use it as a distortion for our demo! Simply as a pleasant knowledge construction for GLSL.

However, simply to know higher, that is what the feel will seem like once you need to preview it:

You see these massive rectangles as a result of i picked one thing like 25×35 DataTexture dimension, which is de facto low-res.
Additionally, it has colours as a result of im utilizing two totally different random numbers for XY(Crimson-Inexperienced) variables, which leads to this.

So now, we might already use this texture as a distortion in our fragment shader:

    vec4 coloration = texture2D(uTexture,newUV);
    vec4 offset = texture2D(uDataTexture,vUv);
    // we're distorting UVs with new texture values
    gl_FragColor = texture2D(uTexture,newUV - 0.02*offset.rg);

The Mouse and its energy

So now, let’s make it dynamic! We are going to want a few issues. First, we’d like the mouse place and pace. And in addition, the mouse radius, which means, at what distance would the mouse distort our picture.

A brief rationalization: On every step of the animation, I’ll loop by means of my grid cells aka pixels of DataTexture. And assign some values primarily based on mouse place and pace. Second, im going to chill out the distortion. This must be achieved, if the consumer stops shifting mouse, the distortion ought to come to 0.

So, now the code appears like this, simplified a bit, for higher understanding the idea:

    let knowledge = DataTexture.picture.knowledge;
    // loop by means of all of the pixels of DataTexture
    for (let i = 0; i < rows; i++) {
    for (let j = 0; j < cols; j++) 
        // get distance between mouse, and present DataTexture pixel
      let distance = distanceBetween(mouse, [i,j])
      if (distance < maxDistance) 

        let index = 3 * (i + this.dimension * j); // get the pixel coordinate on display
        knowledge[index] = this.mouse.vX ; // mouse pace
        knowledge[index + 1] =  this.mouse.vY ; // mouse pace
    // slowly transfer system in the direction of 0 distortion
    for (let i = 0; i < knowledge.size; i += 3) 
      knowledge[i] *= 0.9
      knowledge[i + 1] *= 0.9
    DataTexture.needsUpdate = true;

A few issues are added to make it look higher, however the idea is right here. When you ever labored with particle programs, that is precisely that idea, besides our particles by no means transfer, we simply change some values of the particles (distortion inside every massive pixel).


I left the settings open within the final demo, so you may play with parameters and provide you with your individual distinctive really feel of the animation. Let me know what it impressed you to create!

Leave a Reply

Your email address will not be published. Required fields are marked *

Related Posts