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];