PIXI Black And White Filter

Demonstration of Custom PIXI BlackAndWhite Filter with intensity control

by adil_invideo

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/pixi.js/5.1.3/pixi.min.js"></script>
<div class="parent">
<h2>PIXI Black And White Filter</h2>
<input type="range" max="1" min="0" step="0.01" id="intensity" value="0"/>
</div>

CSS

body {
  font-family: sans-serif;
}

.parent {
  display: flex;
  flex-direction: column;
  width: 200px;
}

JavaScript

//References:
// https://stackoverflow.com/questions/5830139/how-can-i-do-these-image-processing-tasks-using-opengl-es-2-0-shaders/9402041#9402041
// https://www.shadertoy.com/view/wdccDr
// https://pixijs.download/dev/docs/packages_filters_filter-color-matrix_src_ColorMatrixFilter.ts.html#line316

const imageSrc = "https://c.files.bbci.co.uk/3ED6/production/_106768061_gettyimages-1126199440.jpg";

const frag = `
 varying highp vec2 vTextureCoord;
 uniform sampler2D uSampler;
 uniform lowp float intensity; 
const mat4 colorMatrix = mat4( 
            0.3, 0.6, 0.1, 0,
            0.3, 0.6, 0.1, 0,
            0.3, 0.6, 0.1, 0,
            0, 0, 0, 1
);

 void main()
 {
     lowp vec4 textureColor = texture2D(uSampler, vTextureCoord);
     lowp vec4 outputColor = textureColor * colorMatrix;
     gl_FragColor = (intensity * outputColor) + ((1.0 - intensity) * textureColor);
 }
`;

class BlackAndWhiteFilter extends PIXI.Filter {

  constructor() {
    super(null, frag, {
      intensity: 0.0
    });
  }

  get intensity() {
    return this._intensity;
  }

  set intensity(value) {
    this._intensity = value;
    this._updateTransform();
  }

  _updateTransform() {
    this.uniforms.intensity = this._intensity; 
  }
}

const app = new PIXI.Application({
  width: 400,
  height: 250,
  transparent: true
});

document.body.appendChild(app.view);

const sprite = PIXI.Sprite.fromImage(imageSrc);

sprite.width = app.screen.width;
sprite.height = app.screen.height;

app.stage.addChild(sprite);
const filter = new BlackAndWhiteFilter();
sprite.filters = [filter];

document.getElementById('intensity').oninput = (event) => {
  filter.intensity = parseFloat(event.target.value);
};