Skip to content

Commit

Permalink
feat: add fog filter (experimental, might change at any time, use at …
Browse files Browse the repository at this point in the history
…your own risk)

Closes #67
  • Loading branch information
ghost91- committed Sep 1, 2022
1 parent 417cc51 commit 336eea5
Show file tree
Hide file tree
Showing 11 changed files with 302 additions and 158 deletions.
51 changes: 51 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
"rollup": "2.78.1",
"rollup-plugin-livereload": "2.0.5",
"rollup-plugin-sourcemaps": "0.6.3",
"rollup-plugin-string": "3.0.0",
"rollup-plugin-styles": "4.0.0",
"rollup-plugin-terser": "7.0.2",
"standard-version": "9.5.0",
Expand Down
4 changes: 4 additions & 0 deletions rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import copy from "@guanghechen/rollup-plugin-copy";
import livereload from "rollup-plugin-livereload";
import sourcemaps from "rollup-plugin-sourcemaps";
import styles from "rollup-plugin-styles";
import { string } from "rollup-plugin-string";
import { terser } from "rollup-plugin-terser";

import { distDirectory, name, sourceDirectory } from "./tools/const.mjs";
Expand Down Expand Up @@ -40,6 +41,9 @@ const config = {
sourceMap: true,
minimize: isProduction,
}),
string({
include: [`${sourceDirectory}/**/*.frag`, `${sourceDirectory}/**/*.vert`],
}),
copy({
verbose: true,
targets: [{ src: staticFiles, dest: distDirectory }],
Expand Down
4 changes: 2 additions & 2 deletions src/filter-effects/filter-effects-db.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { BloomFilter } from "./filters/bloom.js";
import { ColorFilter } from "./filters/color.js";
// import { FogFilter } from "./filters/fog.js";
import { FogFilter } from "./filters/fog.js";
import { LightningFilter } from "./filters/lightning.js";
import { OldFilmFilter } from "./filters/old-film.js";
import { PredatorFilter } from "./filters/predator.js";
Expand All @@ -12,7 +12,7 @@ import { UnderwaterFilter } from "./filters/underwater.js";
export const filterEffects = {
bloom: BloomFilter,
color: ColorFilter,
// fog: FXFogFilter
fog: FogFilter,
lightning: LightningFilter,
oldfilm: OldFilmFilter,
predator: PredatorFilter,
Expand Down
134 changes: 114 additions & 20 deletions src/filter-effects/filters/fog.js
Original file line number Diff line number Diff line change
@@ -1,45 +1,139 @@
import { fog } from "./shaders/fog.js";
import { customVertex2D } from "./shaders/customvertex2D.js";
import { FXMasterFilterEffectMixin } from "./mixins/filter.js";
import fog from "./shaders/fog.frag";
import customVertex2D from "./shaders/custom-vertex-2d.vert";
import { FadingFilterMixin } from "./mixins/fading-filter.js";

export class FogFilter extends FXMasterFilterEffectMixin(PIXI.Filter) {
export class FogFilter extends FadingFilterMixin(PIXI.Filter) {
constructor(options, id) {
super(options, id, customVertex2D, fog);
this.color = new Float32Array([1.0, 0.4, 0.1, 0.55]);
this.dimensions = new Float32Array([1.0, 1.0]);
this.time = 0.0;
this.density = 0.65;
this.uniforms.time = 0.0;
this.uniforms.dimensions = new Float32Array([0.0, 0.0]);
this.uniforms.color = new Float32Array([0.0, 0.0, 0.0, 1.0]);
}

/** @type {number} */
lastTick;

/** @override */
static label = "FXMASTER.FilterEffectFog";

/** @override */
static icon = "fas fa-cloud";

apply(filterManager, input, output, clear) {
this.uniforms.color = this.color;
this.uniforms.dimensions = this.dimensions;
this.uniforms.time = this.time;
this.uniforms.density = this.density;
this.uniforms.dimensions = this.dimensions;
/** @override */
static get parameters() {
return {
dimensions: {
label: "FXMASTER.Scale",
type: "range",
max: 5,
min: 0,
step: 0.1,
value: 1,
skipInitialAnimation: true,
},
speed: {
label: "FXMASTER.Speed",
type: "range",
max: 5,
min: 0,
step: 0.1,
value: 1,
skipInitialAnimation: true,
},
density: {
label: "FXMASTER.Density",
type: "range",
max: 1,
min: 0,
step: 0.05,
value: 0.65,
},
color: {
label: "FXMASTER.Tint",
type: "color",
value: {
value: "#000000",
apply: false,
},
skipInitialAnimation: true,
},
};
}

filterManager.applyFilter(this, input, output, clear);
/** @override */
static get neutral() {
return {
density: 0,
};
}

/** @type {number} */
get r() {
return this.uniforms.color[0];
}
set r(value) {
this.uniforms.color[0] = value;
}

/** @type {number} */
get g() {
return this.uniforms.color[1];
}
set g(value) {
this.uniforms.color[1] = value;
}

/** @type {number} */
get b() {
return this.uniforms.color[2];
}
set b(value) {
this.uniforms.color[2] = value;
}

/** @type {number} */
get density() {
return this.uniforms.density;
}
set density(value) {
this.uniforms.density = value;
}

/** @type {number} */
get dimensions() {
return this.uniforms.dimensions[0];
}
set dimensions(value) {
this.uniforms.dimensions[0] = this.uniforms.dimensions[1] = (value * 100) / (canvas?.dimensions?.size ?? 100);
}

/** @override */
static get parameters() {
return {};
configure(options) {
if (!options) {
return;
}
const { color, ...otherOptions } = options;
const { r, g, b } = foundry.utils.Color.from(color.apply ? color.value : 0x000000);
super.configure({ ...otherOptions, r, g, b });
}

/** @override */
static get neutral() {
return {};
play(options) {
this.lastTick = canvas.app.ticker.lastTime;
super.play(options);
}

/** @override */
async step() {
this.time = canvas.app.ticker.lastTime;
const delta = canvas.app.ticker.lastTime - this.lastTick;
this.lastTick = canvas.app.ticker.lastTime;
this.uniforms.time += delta * this.speed * 0.1;
await super.step();
}

apply(filterManager, input, output, clear, currentState) {
this.uniforms.filterMatrix ??= new PIXI.Matrix();
this.uniforms.filterMatrix.copyFrom(currentState.target.worldTransform).invert();
return super.apply(filterManager, input, output, clear, currentState);
}
}
17 changes: 16 additions & 1 deletion src/filter-effects/filters/mixins/fading-filter.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ export function FadingFilterMixin(Base) {
*/
currentAnimation;

/** Has this filter already been initialized? */
initialized = false;

/**
* Apply options to this filter effect as an animation.
* @param {object} [options] The options to animate
Expand All @@ -31,7 +34,18 @@ export function FadingFilterMixin(Base) {
await this.currentAnimation;
}
const data = { name, duration };
const anim = Object.entries(options).map(([key, value]) => ({ parent: this, attribute: key, to: value }));

const [toAnimate, toSet] = Object.entries(options)
.partition(([key]) => !!this.constructor.parameters[key]?.skipInitialAnimation && !this.initialized)
.map(Object.fromEntries);

this.applyOptions(toSet);

const anim = Object.entries(toAnimate).map(([key, value]) => ({
parent: this.optionContext,
attribute: key,
to: value,
}));
this.currentAnimation = CanvasAnimation.animate(anim, data).finally(() => (this.currentAnimation = undefined));
return this.currentAnimation;
}
Expand All @@ -44,6 +58,7 @@ export function FadingFilterMixin(Base) {
this.enabled = true;
this.animateOptions();
}
this.initialized = true;
}

/** @override */
Expand Down
10 changes: 9 additions & 1 deletion src/filter-effects/filters/mixins/filter.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,14 +81,22 @@ export function FXMasterFilterEffectMixin(Base) {
this.options = { ...this.constructor.default, ...options };
}

/**
* The context on which options should be applied.
* @type {object}
*/
get optionContext() {
return this;
}

/**
* Apply options to this filter effect, setting the corresponding properties on this effect itself.
* @param {object} options The options to apply
*/
applyOptions(options = this.options) {
const keys = Object.keys(options);
for (const key of keys) {
this[key] = options[key];
this.optionContext[key] = options[key];
}
}

Expand Down
22 changes: 22 additions & 0 deletions src/filter-effects/filters/shaders/custom-vertex-2d.vert
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// SPDX-FileCopyrightText: 2022 Johannes Loher
//
// SPDX-License-Identifier: BSD-3-Clause

precision mediump float;

attribute vec2 aVertexPosition;

uniform mat3 projectionMatrix;
uniform mat3 filterMatrix;
uniform vec4 inputSize;
uniform vec4 outputFrame;

varying vec2 vTextureCoord;
varying vec2 vFilterCoord;

void main(void) {
vTextureCoord = aVertexPosition * (outputFrame.zw * inputSize.zw);
vec2 position = aVertexPosition * max(outputFrame.zw, vec2(0.)) + outputFrame.xy;
vFilterCoord = (filterMatrix * vec3(position, 1.0)).xy;
gl_Position = vec4((projectionMatrix * vec3(position, 1.0)).xy, 0.0, 1.0);
}
Loading

0 comments on commit 336eea5

Please sign in to comment.