@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
191 lines (190 loc) • 5.88 kB
JavaScript
"use strict";
import { Vector2 } from "three";
import { TypedPostNode, PostParamOptions } from "./_Base";
import { NodeParamsConfig, ParamConfig } from "../utils/params/ParamsConfig";
import { BlendFunction, GlitchEffect, EffectPass, GlitchMode } from "postprocessing";
import { BLEND_FUNCTION_MENU_OPTIONS } from "../../../core/post/BlendFunction";
import { NodeContext } from "../../poly/NodeContext";
const GLITCH_MODES = [
GlitchMode.DISABLED,
GlitchMode.SPORADIC,
GlitchMode.CONSTANT_MILD,
GlitchMode.CONSTANT_WILD
];
const GLITCH_MODE_BY_INDEX = ["DISABLED", "SPORADIC", "CONSTANT_MILD", "CONSTANT_WILD"];
export const GLITCH_MODE_MENU_OPTIONS = {
menu: {
entries: GLITCH_MODES.map((value) => {
return {
name: GLITCH_MODE_BY_INDEX[value],
value
};
})
}
};
class GlitchPostParamsConfig extends NodeParamsConfig {
constructor() {
super(...arguments);
// useTexture = ParamConfig.BOOLEAN(0, {
// ...PostParamOptions,
// });
this.texture = ParamConfig.NODE_PATH("", {
nodeSelection: {
context: NodeContext.COP
},
dependentOnFoundNode: false,
...PostParamOptions
// visibleIf: {useTexture: 1},
});
// dtSize = ParamConfig.INTEGER(64, {
// separatorBefore: true,
// ...PostParamOptions,
// range: [2, 128],
// rangeLocked: [true, false],
// visibleIf: {useTexture: 0},
// });
/** @param mode */
this.mode = ParamConfig.INTEGER(GLITCH_MODES.indexOf(GlitchMode.CONSTANT_MILD), {
...GLITCH_MODE_MENU_OPTIONS,
...PostParamOptions
});
this.minDelay = ParamConfig.FLOAT(0.5, {
separatorBefore: true,
...PostParamOptions,
range: [0, 1],
rangeLocked: [true, false]
});
this.maxDelay = ParamConfig.FLOAT(0.5, {
...PostParamOptions,
range: [0, 1],
rangeLocked: [true, false]
});
this.minDuration = ParamConfig.FLOAT(0.5, {
separatorBefore: true,
...PostParamOptions,
range: [0, 1],
rangeLocked: [true, false]
});
this.maxDuration = ParamConfig.FLOAT(0.5, {
...PostParamOptions,
range: [0, 1],
rangeLocked: [true, false]
});
this.minStrength = ParamConfig.FLOAT(0.5, {
separatorBefore: true,
...PostParamOptions,
range: [0, 1],
rangeLocked: [true, false]
});
this.maxStrength = ParamConfig.FLOAT(0.5, {
...PostParamOptions,
range: [0, 1],
rangeLocked: [true, false]
});
/** @param columns */
this.columns = ParamConfig.INTEGER(2, {
...PostParamOptions,
range: [0, 20],
rangeLocked: [true, false]
});
/** @param ratio */
this.ratio = ParamConfig.FLOAT(1, {
range: [0, 1],
rangeLocked: [true, true],
...PostParamOptions
});
/** @param blend function */
this.blendFunction = ParamConfig.INTEGER(BlendFunction.SCREEN, {
...PostParamOptions,
...BLEND_FUNCTION_MENU_OPTIONS
});
/** @param if true, the offset parameter will be updated on each render to reflect the intensity of the glitch. This can be used to drive other effects with it */
this.updateOffset = ParamConfig.BOOLEAN(0, {
separatorBefore: true,
...PostParamOptions
});
this.offset = ParamConfig.VECTOR2([0, 0], {
cook: false,
visibleIf: {
updateOffset: 1
}
});
}
}
const ParamsConfig = new GlitchPostParamsConfig();
export class GlitchPostNode extends TypedPostNode {
constructor() {
super(...arguments);
this.paramsConfig = ParamsConfig;
this._rendererSize = new Vector2();
this._offsetArray = [0, 0];
this._onRenderBound = this._onRender.bind(this);
}
static type() {
return "glitch";
}
createPass(context) {
this._lastViewer = context.viewer;
context.renderer.getSize(this._rendererSize);
this._lastEffect = new GlitchEffect({
blendFunction: this.pv.blendFunction,
chromaticAberrationOffset: new Vector2(0, 0)
// delay:this.pv.delay,
// duration:this.pv.duration,
// strength:this.pv.strength,
// dtSize: this.pv.dtSize,
});
const pass = new EffectPass(context.camera, this._lastEffect);
this.updatePass(pass);
return pass;
}
async updatePass(pass) {
const effect = pass.effects[0];
effect.blendFunction = this.pv.blendFunction;
effect.mode = GLITCH_MODES[this.pv.mode];
effect.minDelay = this.pv.minDelay;
effect.maxDelay = this.pv.maxDelay;
effect.minDuration = this.pv.minDuration;
effect.maxDuration = this.pv.maxDuration;
effect.minStrength = this.pv.minStrength;
effect.maxStrength = this.pv.maxStrength;
effect.columns = this.pv.columns;
effect.ratio = this.pv.ratio;
const texture = await this._fetchTexture();
if (texture) {
effect.perturbationMap = texture;
}
this._updateOnTickCallback();
}
async _fetchTexture() {
var _a;
const textureNode = this.pv.texture.nodeWithContext(NodeContext.COP, (_a = this.states) == null ? void 0 : _a.error);
if (textureNode) {
const container = await textureNode.compute();
return container.coreContent();
}
}
_onTickCallbackName() {
return `post/glitch-${this.graphNodeId()}`;
}
_updateOnTickCallback() {
if (!this._lastViewer) {
return;
}
const callbackName = this._onTickCallbackName();
if (this.pv.updateOffset) {
if (!this._lastViewer.registeredAfterRenderCallbacks().has(callbackName)) {
this._lastViewer.registerOnAfterRender(callbackName, this._onRenderBound);
}
} else {
this._lastViewer.unRegisterOnAfterRender(callbackName);
}
}
_onRender() {
if (!this._lastEffect) {
return;
}
this._lastEffect.chromaticAberrationOffset.toArray(this._offsetArray);
this.p.offset.set(this._offsetArray);
}
}