JSFiddle - React, Tailwind, and code Playground

by kouty79

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/pixi.js/4.7.0/pixi.min.js"></script>
<input type="range" min="1" max="100" value="50" id="progress"><br>

JavaScript

var app = new PIXI.Application({ width: 640, height: 480 });
document.body.appendChild(app.view);

const imgUrl = 
	'https://wallpapers.wallhaven.cc/wallpapers/full/wallhaven-615925.png';
const sprite = PIXI.Sprite.fromImage(imgUrl);
sprite.scale.set(0.5);
app.stage.addChild(sprite);
document.querySelector('#progress').oninput = function() {
	filter.progress = this.value / 100;
};

const Vertex = `attribute vec2 aVertexPosition;
attribute vec2 aTextureCoord;

uniform mat3 projectionMatrix;
uniform mat3 filterMatrix;

varying vec2 vTextureCoord;
varying vec2 vFilterCoord;

void main(void)
{
   gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);
   vFilterCoord = ( filterMatrix * vec3( aTextureCoord, 1.0)  ).xy;
   vTextureCoord = aTextureCoord;
}
`;

const Fragment = `
precision mediump float;

varying vec2 vTextureCoord;
uniform sampler2D uSampler;
uniform float progress;

vec2 xskew (vec2 p, float persp, float center) {
  float x = mix(p.x, 1.0-p.x, center);
  return (
    (
      vec2( x, (p.y - 0.5*(1.0-persp) * x) / (1.0+(persp-1.0)*x) )
      - vec2(0.5-distance(center, 0.5), 0.0)
    )
    * vec2(0.5 / distance(center, 0.5) * (center<0.5 ? 1.0 : -1.0), 1.0)
    + vec2(center<0.5 ? 0.0 : 1.0, 0.0)
  );
}

void main(void)
{
		float persp = 0.7;
		float persp2 = mix(pow(progress, 2.0), 1.0, persp);
    vec2 coord = xskew(vTextureCoord.xy, persp2, 0.5);
    gl_FragColor = texture2D(uSampler, coord);
}
`;


class PerspectiveFilter extends PIXI.Filter {
  constructor() {
    const maskMatrix = new PIXI.Matrix();
    super(
      Vertex,
      Fragment,
      // custom uniforms
      {
        progress: {
          type: "1f",
          value: 0.5
        }
      }
    );
    this.padding = 0;
    this.maskMatrix = maskMatrix;
  }

  set progress(value) {
    this.uniforms.progress = value;
  }
}
const filter = new PerspectiveFilter();
sprite.filters = [filter];