Files
Foundry-VTT-Docker/resources/app/client/pixi/webgl/shaders/weather/base-weather.js
2025-01-04 00:34:03 +01:00

209 lines
5.5 KiB
JavaScript

/**
* The base shader class for weather shaders.
*/
class AbstractWeatherShader extends AbstractBaseShader {
constructor(...args) {
super(...args);
Object.defineProperties(this, Object.keys(this.constructor.defaultUniforms).reduce((obj, k) => {
obj[k] = {
get() {
return this.uniforms[k];
},
set(value) {
this.uniforms[k] = value;
},
enumerable: false
};
return obj;
}, {}));
}
/**
* Compute the weather masking value.
* @type {string}
*/
static COMPUTE_MASK = `
// Base mask value
float mask = 1.0;
// Process the occlusion mask
if ( useOcclusion ) {
float oMask = step(depthElevation, (254.5 / 255.0) - dot(occlusionWeights, texture2D(occlusionTexture, vUvsOcclusion)));
if ( reverseOcclusion ) oMask = 1.0 - oMask;
mask *= oMask;
}
// Process the terrain mask
if ( useTerrain ) {
float tMask = dot(terrainWeights, texture2D(terrainTexture, vUvsTerrain));
if ( reverseTerrain ) tMask = 1.0 - tMask;
mask *= tMask;
}
`;
/**
* Compute the weather masking value.
* @type {string}
*/
static FRAGMENT_HEADER = `
precision ${PIXI.settings.PRECISION_FRAGMENT} float;
// Occlusion mask uniforms
uniform bool useOcclusion;
uniform sampler2D occlusionTexture;
uniform bool reverseOcclusion;
uniform vec4 occlusionWeights;
// Terrain mask uniforms
uniform bool useTerrain;
uniform sampler2D terrainTexture;
uniform bool reverseTerrain;
uniform vec4 terrainWeights;
// Other uniforms and varyings
uniform vec3 tint;
uniform float time;
uniform float depthElevation;
uniform float alpha;
varying vec2 vUvsOcclusion;
varying vec2 vUvsTerrain;
varying vec2 vStaticUvs;
varying vec2 vUvs;
`;
/**
* Common uniforms for all weather shaders.
* @type {{
* useOcclusion: boolean,
* occlusionTexture: PIXI.Texture|null,
* reverseOcclusion: boolean,
* occlusionWeights: number[],
* useTerrain: boolean,
* terrainTexture: PIXI.Texture|null,
* reverseTerrain: boolean,
* terrainWeights: number[],
* alpha: number,
* tint: number[],
* screenDimensions: [number, number],
* effectDimensions: [number, number],
* depthElevation: number,
* time: number
* }}
*/
static commonUniforms = {
terrainUvMatrix: new PIXI.Matrix(),
useOcclusion: false,
occlusionTexture: null,
reverseOcclusion: false,
occlusionWeights: [0, 0, 1, 0],
useTerrain: false,
terrainTexture: null,
reverseTerrain: false,
terrainWeights: [1, 0, 0, 0],
alpha: 1,
tint: [1, 1, 1],
screenDimensions: [1, 1],
effectDimensions: [1, 1],
depthElevation: 1,
time: 0
};
/**
* Default uniforms for a specific class
* @abstract
*/
static defaultUniforms;
/* -------------------------------------------- */
/** @override */
static create(initialUniforms) {
const program = this.createProgram();
const uniforms = {...this.commonUniforms, ...this.defaultUniforms, ...initialUniforms};
return new this(program, uniforms);
}
/* -------------------------------------------- */
/**
* Create the shader program.
* @returns {PIXI.Program}
*/
static createProgram() {
return PIXI.Program.from(this.vertexShader, this.fragmentShader);
}
/* -------------------------------------------- */
/** @inheritdoc */
static vertexShader = `
precision ${PIXI.settings.PRECISION_VERTEX} float;
attribute vec2 aVertexPosition;
uniform mat3 translationMatrix;
uniform mat3 projectionMatrix;
uniform mat3 terrainUvMatrix;
uniform vec2 screenDimensions;
uniform vec2 effectDimensions;
varying vec2 vUvsOcclusion;
varying vec2 vUvsTerrain;
varying vec2 vUvs;
varying vec2 vStaticUvs;
void main() {
vec3 tPos = translationMatrix * vec3(aVertexPosition, 1.0);
vStaticUvs = aVertexPosition;
vUvs = vStaticUvs * effectDimensions;
vUvsOcclusion = tPos.xy / screenDimensions;
vUvsTerrain = (terrainUvMatrix * vec3(aVertexPosition, 1.0)).xy;
gl_Position = vec4((projectionMatrix * tPos).xy, 0.0, 1.0);
}
`;
/* -------------------------------------------- */
/* Common Management and Parameters */
/* -------------------------------------------- */
/**
* Update the scale of this effect with new values
* @param {number|{x: number, y: number}} scale The desired scale
*/
set scale(scale) {
this.#scale.x = typeof scale === "object" ? scale.x : scale;
this.#scale.y = (typeof scale === "object" ? scale.y : scale) ?? this.#scale.x;
}
set scaleX(x) {
this.#scale.x = x ?? 1;
}
set scaleY(y) {
this.#scale.y = y ?? 1;
}
#scale = {
x: 1,
y: 1
};
/* -------------------------------------------- */
/**
* The speed multiplier applied to animation.
* 0 stops animation.
* @type {number}
*/
speed = 1;
/* -------------------------------------------- */
/** @override */
_preRender(mesh, renderer) {
this.uniforms.alpha = mesh.worldAlpha;
this.uniforms.depthElevation = canvas.masks.depth.mapElevation(canvas.weather.elevation);
this.uniforms.time += (canvas.app.ticker.deltaMS / 1000 * this.speed);
this.uniforms.screenDimensions = canvas.screenDimensions;
this.uniforms.effectDimensions[0] = this.#scale.x * mesh.scale.x / 10000;
this.uniforms.effectDimensions[1] = this.#scale.y * mesh.scale.y / 10000;
}
}