Skip to content

Commit

Permalink
Fixed #61
Browse files Browse the repository at this point in the history
  • Loading branch information
Feu-Secret committed Jun 7, 2021
1 parent c048411 commit f102031
Show file tree
Hide file tree
Showing 7 changed files with 502 additions and 25 deletions.
10 changes: 4 additions & 6 deletions tokenmagic/fx/filters/FilterBlur.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { Anime } from "../Anime.js";
import {Anime} from "../Anime.js";
import "./proto/FilterProto.js";
import {FilterBlurEx} from "./FilterBlurEx.js";

export class FilterBlur extends PIXI.filters.BlurFilter {
export class FilterBlur extends FilterBlurEx {
constructor(params) {
super();
this.enabled = false;
Expand Down Expand Up @@ -43,12 +44,9 @@ export class FilterBlur extends PIXI.filters.BlurFilter {

calculatePadding() {
const scale = this.targetPlaceable.worldTransform.a;

this.blurXFilter.blur = scale * this.strengthX;
this.blurYFilter.blur = scale * this.strengthY;

this.updatePadding();

super.calculatePadding();
}
}
}
318 changes: 318 additions & 0 deletions tokenmagic/fx/filters/FilterBlurEx.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,318 @@
import { CustomFilter } from './CustomFilter.js';

export class FilterBlurEx extends CustomFilter {
blurXFilter;
blurYFilter;

_repeatEdgePixels;

constructor(strength = 8, quality = 4, resolution = PIXI.settings.FILTER_RESOLUTION, kernelSize = 5) {
super();

this.blurXFilter = new BlurFilterPassEx(true, strength, quality, resolution, kernelSize);
this.blurYFilter = new BlurFilterPassEx(false, strength, quality, resolution, kernelSize);

this.resolution = resolution;
this.quality = quality;
this.blur = strength;

this.repeatEdgePixels = false;
}

apply(filterManager, input, output, clearMode) {
const xStrength = Math.abs(this.blurXFilter.strength);
const yStrength = Math.abs(this.blurYFilter.strength);

if (xStrength && yStrength) {
const renderTarget = filterManager.getFilterTexture();

this.blurXFilter.apply(filterManager, input, renderTarget, PIXI.CLEAR_MODES.CLEAR);
this.blurYFilter.apply(filterManager, renderTarget, output, clearMode);

filterManager.returnFilterTexture(renderTarget);
}
else if (yStrength) {
this.blurYFilter.apply(filterManager, input, output, clearMode);
}
else {
this.blurXFilter.apply(filterManager, input, output, clearMode);
}
}

updatePadding() {
if (this._repeatEdgePixels) {
this.padding = 0;
}
else {
this.padding = Math.max(Math.abs(this.blurXFilter.strength), Math.abs(this.blurYFilter.strength)) * 2;
}
}

get blur() {
return this.blurXFilter.blur;
}

set blur(value) {
this.blurXFilter.blur = this.blurYFilter.blur = value;
this.updatePadding();
}

get quality() {
return this.blurXFilter.quality;
}

set quality(value) {
this.blurXFilter.quality = this.blurYFilter.quality = value;
}

get blurX() {
return this.blurXFilter.blur;
}

set blurX(value) {
this.blurXFilter.blur = value;
this.updatePadding();
}

get blurY() {
return this.blurYFilter.blur;
}

set blurY(value) {
this.blurYFilter.blur = value;
this.updatePadding();
}

get blendMode() {
return this.blurYFilter.blendMode;
}

set blendMode(value) {
this.blurYFilter.blendMode = value;
}

get repeatEdgePixels() {
return this._repeatEdgePixels;
}

set repeatEdgePixels(value) {
this._repeatEdgePixels = value;
this.updatePadding();
}
}

export class BlurFilterPassEx extends CustomFilter {
horizontal;
strength;
passes;
_quality;

constructor(horizontal, strength = 8, quality = 4, resolution = PIXI.settings.FILTER_RESOLUTION, kernelSize = 5) {
const vertSrc = generateBlurVertSource(kernelSize, horizontal);
const fragSrc = generateBlurFragSource(kernelSize);

super(
// vertex shader
vertSrc,
// fragment shader
fragSrc
);

this.horizontal = horizontal;

this.resolution = resolution;

this._quality = 0;

this.quality = quality;

this.blur = strength;
}

apply(filterManager, input, output, clearMode) {
if (output) {
if (this.horizontal) {
this.uniforms.strength = (1 / output.width) * (output.width / input.width);
} else {
this.uniforms.strength = (1 / output.height) * (output.height / input.height);
}
}
else {
if (this.horizontal) {
this.uniforms.strength = (1 / filterManager.renderer.width) * (filterManager.renderer.width / input.width);
} else {
this.uniforms.strength = (1 / filterManager.renderer.height) * (filterManager.renderer.height / input.height);
}
}

// screen space!
this.uniforms.strength *= this.strength;
this.uniforms.strength /= this.passes;

if (this.passes === 1) {
filterManager.applyFilter(this, input, output, clearMode);
}
else {
const renderTarget = filterManager.getFilterTexture();
const renderer = filterManager.renderer;

let flip = input;
let flop = renderTarget;

this.state.blend = false;
filterManager.applyFilter(this, flip, flop, PIXI.CLEAR_MODES.CLEAR);

for (let i = 1; i < this.passes - 1; i++) {
filterManager.bindAndClear(flip, PIXI.CLEAR_MODES.BLIT);

this.uniforms.uSampler = flop;

const temp = flop;

flop = flip;
flip = temp;

renderer.shader.bind(this);
renderer.geometry.draw(5);
}

this.state.blend = true;
filterManager.applyFilter(this, flop, output, clearMode);
filterManager.returnFilterTexture(renderTarget);
}
}

get blur() {
return this.strength;
}

set blur(value) {
this.padding = 1 + (Math.abs(value) * 2);
this.strength = value;
}

get quality() {
return this._quality;
}

set quality(value) {
this._quality = value;
this.passes = value;
}
}

const GAUSSIAN_VALUES = {
5: [0.153388, 0.221461, 0.250301],
7: [0.071303, 0.131514, 0.189879, 0.214607],
9: [0.028532, 0.067234, 0.124009, 0.179044, 0.20236],
11: [0.0093, 0.028002, 0.065984, 0.121703, 0.175713, 0.198596],
13: [0.002406, 0.009255, 0.027867, 0.065666, 0.121117, 0.174868, 0.197641],
15: [0.000489, 0.002403, 0.009246, 0.02784, 0.065602, 0.120999, 0.174697, 0.197448],
};

const fragTemplate = [
'varying vec2 vBlurTexCoords[%size%];',
'uniform sampler2D uSampler;',

'void main(void)',
'{',
' gl_FragColor = vec4(0.0);',
' %blur%',
'}',

].join('\n');

export function generateBlurFragSource(kernelSize) {
const kernel = GAUSSIAN_VALUES[kernelSize];
const halfLength = kernel.length;

let fragSource = fragTemplate;

let blurLoop = '';
const template = 'gl_FragColor += texture2D(uSampler, vBlurTexCoords[%index%]) * %value%;';
let value;

for (let i = 0; i < kernelSize; i++) {
let blur = template.replace('%index%', i.toString());

value = i;

if (i >= halfLength) {
value = kernelSize - i - 1;
}

blur = blur.replace('%value%', kernel[value].toString());

blurLoop += blur;
blurLoop += '\n';
}

fragSource = fragSource.replace('%blur%', blurLoop);
fragSource = fragSource.replace('%size%', kernelSize.toString());

return fragSource;
}

const vertTemplate = `
attribute vec2 aVertexPosition;
uniform mat3 projectionMatrix;
uniform float strength;
varying vec2 vBlurTexCoords[%size%];
uniform vec4 inputSize;
uniform vec4 outputFrame;
vec4 filterVertexPosition( void )
{
vec2 position = aVertexPosition * max(outputFrame.zw, vec2(0.)) + outputFrame.xy;
return vec4((projectionMatrix * vec3(position, 1.0)).xy, 0.0, 1.0);
}
vec2 filterTextureCoord( void )
{
return aVertexPosition * (outputFrame.zw * inputSize.zw);
}
void main(void)
{
gl_Position = filterVertexPosition();
vec2 textureCoord = filterTextureCoord();
%blur%
}`;

export function generateBlurVertSource(kernelSize, x) {
const halfLength = Math.ceil(kernelSize / 2);

let vertSource = vertTemplate;

let blurLoop = '';
let template;

if (x) {
template = 'vBlurTexCoords[%index%] = textureCoord + vec2(%sampleIndex% * strength, 0.0);';
}
else {
template = 'vBlurTexCoords[%index%] = textureCoord + vec2(0.0, %sampleIndex% * strength);';
}

for (let i = 0; i < kernelSize; i++) {
let blur = template.replace('%index%', i.toString());

blur = blur.replace('%sampleIndex%', `${i - (halfLength - 1)}.0`);

blurLoop += blur;
blurLoop += '\n';
}

vertSource = vertSource.replace('%blur%', blurLoop);
vertSource = vertSource.replace('%size%', kernelSize.toString());

return vertSource;
}

export function getMaxKernelSize(gl) {
const maxVaryings = (PIXI.gl.getParameter(PIXI.gl.MAX_VARYING_VECTORS));
let kernelSize = 15;

while (kernelSize > maxVaryings) {
kernelSize -= 2;
}

return kernelSize;
}
4 changes: 3 additions & 1 deletion tokenmagic/fx/filters/FilterDropShadow.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { Anime } from "../Anime.js";
import "./proto/FilterProto.js";
import {FilterDropShadowEx} from "./FilterDropShadowEx.js";

export class FilterDropShadow extends PIXI.filters.DropShadowFilter {
export class FilterDropShadow extends FilterDropShadowEx {
constructor(params) {
super();
this.enabled = false;
Expand All @@ -20,5 +21,6 @@ export class FilterDropShadow extends PIXI.filters.DropShadowFilter {
this.anime = new Anime(this);
this.normalizeTMParams();
}
this.autoFit = false;
}
}
Loading

0 comments on commit f102031

Please sign in to comment.