Source: gfx/filters/displacement/DisplacementFilter.js

const AbstractFilter = require('../../core/renderers/webgl/filters/AbstractFilter');
const Vector = require('engine/Vector');
const { Matrix } = require('../../core/math');

/**
 * The DisplacementFilter class uses the pixel values from the specified texture (called the displacement map) to perform a displacement of an object.
 * You can use this filter to apply all manor of crazy warping effects
 * Currently the r property of the texture is used to offset the x and the g property of the texture is used to offset the y.
 *
 * @class
 * @extends AbstractFilter
 * @param sprite {Sprite} the sprite used for the displacement map. (make sure its added to the scene!)
 */
function DisplacementFilter(sprite, scale) {
  var maskMatrix = new Matrix();
  sprite.renderable = false;

  AbstractFilter.call(this,
        // vertex shader
        require('./displacement.vert'),
        // fragment shader
        require('./displacement.frag'),
        // uniforms
    {
      mapSampler: { type: 'sampler2D', value: sprite.texture },
      otherMatrix: { type: 'mat3', value: maskMatrix.toArray(true) },
      scale: { type: 'v2', value: { x: 1, y: 1 } },
    }
    );

  this.maskSprite = sprite;
  this.maskMatrix = maskMatrix;

  if (scale === null || scale === undefined) {
    scale = 20;
  }

  this.scale = Vector.create(scale, scale);
}

DisplacementFilter.prototype = Object.create(AbstractFilter.prototype);
DisplacementFilter.prototype.constructor = DisplacementFilter;
module.exports = DisplacementFilter;

DisplacementFilter.prototype.applyFilter = function(renderer, input, output) {
  var filterManager = renderer.filterManager;

  filterManager.calculateMappedMatrix(input.frame, this.maskSprite, this.maskMatrix);

  this.uniforms.otherMatrix.value = this.maskMatrix.toArray(true);
  this.uniforms.scale.value.x = this.scale.x * (1 / input.frame.width);
  this.uniforms.scale.value.y = this.scale.y * (1 / input.frame.height);

  var shader = this.getShader(renderer);
     // draw the filter...
  filterManager.applyFilter(shader, input, output);
};


Object.defineProperties(DisplacementFilter.prototype, {
    /**
     * The texture used for the displacement map. Must be power of 2 sized texture.
     *
     * @member {Texture}
     * @memberof filters.DisplacementFilter#
     */
  map: {
    get: function() {
      return this.uniforms.mapSampler.value;
    },
    set: function(value) {
      this.uniforms.mapSampler.value = value;

    },
  },
});