This commit is contained in:
2025-01-04 00:34:03 +01:00
parent 41829408dc
commit 0ca14bbc19
18111 changed files with 1871397 additions and 0 deletions

View File

@@ -0,0 +1,91 @@
/**
* The default coloration shader used by standard rendering and animations.
* A fragment shader which creates a solid light source.
*/
class AdaptiveBackgroundShader extends AdaptiveLightingShader {
/**
* Memory allocations for the Adaptive Background Shader
* @type {string}
*/
static SHADER_HEADER = `
${this.FRAGMENT_UNIFORMS}
${this.VERTEX_FRAGMENT_VARYINGS}
${this.FRAGMENT_FUNCTIONS}
${this.CONSTANTS}
${this.SWITCH_COLOR}
`;
/** @inheritdoc */
static fragmentShader = `
${this.SHADER_HEADER}
${this.PERCEIVED_BRIGHTNESS}
void main() {
${this.FRAGMENT_BEGIN}
${this.ADJUSTMENTS}
${this.BACKGROUND_TECHNIQUES}
${this.FALLOFF}
${this.FRAGMENT_END}
}`;
/** @override */
static defaultUniforms = {
technique: 1,
contrast: 0,
shadows: 0,
saturation: 0,
intensity: 5,
attenuation: 0.5,
exposure: 0,
ratio: 0.5,
color: [1, 1, 1],
colorBackground: [1, 1, 1],
screenDimensions: [1, 1],
time: 0,
useSampler: true,
primaryTexture: null,
depthTexture: null,
darknessLevelTexture: null,
depthElevation: 1,
ambientBrightest: [1, 1, 1],
ambientDarkness: [0, 0, 0],
ambientDaylight: [1, 1, 1],
weights: [0, 0, 0, 0],
dimLevelCorrection: 1,
brightLevelCorrection: 2,
computeIllumination: false,
globalLight: false,
globalLightThresholds: [0, 0]
};
static {
const initial = foundry.data.LightData.cleanData();
this.defaultUniforms.technique = initial.coloration;
this.defaultUniforms.contrast = initial.contrast;
this.defaultUniforms.shadows = initial.shadows;
this.defaultUniforms.saturation = initial.saturation;
this.defaultUniforms.intensity = initial.animation.intensity;
this.defaultUniforms.attenuation = initial.attenuation;
}
/**
* Flag whether the background shader is currently required.
* Check vision modes requirements first, then
* if key uniforms are at their default values, we don't need to render the background container.
* @type {boolean}
*/
get isRequired() {
const vs = canvas.visibility.lightingVisibility;
// Checking if a vision mode is forcing the rendering
if ( vs.background === VisionMode.LIGHTING_VISIBILITY.REQUIRED ) return true;
// Checking if disabled
if ( vs.background === VisionMode.LIGHTING_VISIBILITY.DISABLED ) return false;
// Then checking keys
const keys = ["contrast", "saturation", "shadows", "exposure", "technique"];
return keys.some(k => this.uniforms[k] !== this.constructor.defaultUniforms[k]);
}
}

View File

@@ -0,0 +1,517 @@
/* eslint-disable no-tabs */
/**
* @typedef {Object} ShaderTechnique
* @property {number} id The numeric identifier of the technique
* @property {string} label The localization string that labels the technique
* @property {string|undefined} coloration The coloration shader fragment when the technique is used
* @property {string|undefined} illumination The illumination shader fragment when the technique is used
* @property {string|undefined} background The background shader fragment when the technique is used
*/
/**
* This class defines an interface which all adaptive lighting shaders extend.
*/
class AdaptiveLightingShader extends AbstractBaseShader {
/**
* Has this lighting shader a forced default color?
* @type {boolean}
*/
static forceDefaultColor = false;
/* -------------------------------------------- */
/** Called before rendering. */
update() {
this.uniforms.depthElevation = canvas.masks.depth.mapElevation(this.uniforms.elevation ?? 0);
}
/* -------------------------------------------- */
/**
* Common attributes for vertex shaders.
* @type {string}
*/
static VERTEX_ATTRIBUTES = `
attribute vec2 aVertexPosition;
attribute float aDepthValue;
`;
/**
* Common uniforms for vertex shaders.
* @type {string}
*/
static VERTEX_UNIFORMS = `
uniform mat3 translationMatrix;
uniform mat3 projectionMatrix;
uniform float rotation;
uniform float angle;
uniform float radius;
uniform float depthElevation;
uniform vec2 screenDimensions;
uniform vec2 resolution;
uniform vec3 origin;
uniform vec3 dimensions;
`;
/**
* Common varyings shared by vertex and fragment shaders.
* @type {string}
*/
static VERTEX_FRAGMENT_VARYINGS = `
varying vec2 vUvs;
varying vec2 vSamplerUvs;
varying float vDepth;
`;
/**
* Common functions used by the vertex shaders.
* @type {string}
* @abstract
*/
static VERTEX_FUNCTIONS = "";
/**
* Common uniforms shared by fragment shaders.
* @type {string}
*/
static FRAGMENT_UNIFORMS = `
uniform int technique;
uniform bool useSampler;
uniform bool hasColor;
uniform bool computeIllumination;
uniform bool linkedToDarknessLevel;
uniform bool enableVisionMasking;
uniform bool globalLight;
uniform float attenuation;
uniform float borderDistance;
uniform float contrast;
uniform float shadows;
uniform float exposure;
uniform float saturation;
uniform float intensity;
uniform float brightness;
uniform float luminosity;
uniform float pulse;
uniform float brightnessPulse;
uniform float backgroundAlpha;
uniform float illuminationAlpha;
uniform float colorationAlpha;
uniform float ratio;
uniform float time;
uniform float darknessLevel;
uniform float darknessPenalty;
uniform vec2 globalLightThresholds;
uniform vec3 color;
uniform vec3 colorBackground;
uniform vec3 colorVision;
uniform vec3 colorTint;
uniform vec3 colorEffect;
uniform vec3 colorDim;
uniform vec3 colorBright;
uniform vec3 ambientDaylight;
uniform vec3 ambientDarkness;
uniform vec3 ambientBrightest;
uniform int dimLevelCorrection;
uniform int brightLevelCorrection;
uniform vec4 weights;
uniform sampler2D primaryTexture;
uniform sampler2D framebufferTexture;
uniform sampler2D depthTexture;
uniform sampler2D darknessLevelTexture;
uniform sampler2D visionTexture;
// Shared uniforms with vertex shader
uniform ${PIXI.settings.PRECISION_VERTEX} float rotation;
uniform ${PIXI.settings.PRECISION_VERTEX} float angle;
uniform ${PIXI.settings.PRECISION_VERTEX} float radius;
uniform ${PIXI.settings.PRECISION_VERTEX} float depthElevation;
uniform ${PIXI.settings.PRECISION_VERTEX} vec2 resolution;
uniform ${PIXI.settings.PRECISION_VERTEX} vec2 screenDimensions;
uniform ${PIXI.settings.PRECISION_VERTEX} vec3 origin;
uniform ${PIXI.settings.PRECISION_VERTEX} vec3 dimensions;
uniform ${PIXI.settings.PRECISION_VERTEX} mat3 translationMatrix;
uniform ${PIXI.settings.PRECISION_VERTEX} mat3 projectionMatrix;
`;
/**
* Common functions used by the fragment shaders.
* @type {string}
* @abstract
*/
static FRAGMENT_FUNCTIONS = `
#define DARKNESS -2
#define HALFDARK -1
#define UNLIT 0
#define DIM 1
#define BRIGHT 2
#define BRIGHTEST 3
vec3 computedDimColor;
vec3 computedBrightColor;
vec3 computedBackgroundColor;
float computedDarknessLevel;
vec3 getCorrectedColor(int level) {
if ( (level == HALFDARK) || (level == DIM) ) {
return computedDimColor;
} else if ( (level == BRIGHT) || (level == DARKNESS) ) {
return computedBrightColor;
} else if ( level == BRIGHTEST ) {
return ambientBrightest;
} else if ( level == UNLIT ) {
return computedBackgroundColor;
}
return computedDimColor;
}
`;
/** @inheritdoc */
static CONSTANTS = `
${super.CONSTANTS}
const float INVTHREE = 1.0 / 3.0;
const vec2 PIVOT = vec2(0.5);
const vec4 ALLONES = vec4(1.0);
`;
/** @inheritdoc */
static vertexShader = `
${this.VERTEX_ATTRIBUTES}
${this.VERTEX_UNIFORMS}
${this.VERTEX_FRAGMENT_VARYINGS}
${this.VERTEX_FUNCTIONS}
void main() {
vec3 tPos = translationMatrix * vec3(aVertexPosition, 1.0);
vUvs = aVertexPosition * 0.5 + 0.5;
vDepth = aDepthValue;
vSamplerUvs = tPos.xy / screenDimensions;
gl_Position = vec4((projectionMatrix * tPos).xy, 0.0, 1.0);
}`;
/* -------------------------------------------- */
/* GLSL Helper Functions */
/* -------------------------------------------- */
/**
* Construct adaptive shader according to shader type
* @param {string} shaderType shader type to construct : coloration, illumination, background, etc.
* @returns {string} the constructed shader adaptive block
*/
static getShaderTechniques(shaderType) {
let shader = "";
let index = 0;
for ( let technique of Object.values(this.SHADER_TECHNIQUES) ) {
if ( technique[shaderType] ) {
let cond = `if ( technique == ${technique.id} )`;
if ( index > 0 ) cond = `else ${cond}`;
shader += `${cond} {${technique[shaderType]}\n}\n`;
index++;
}
}
return shader;
}
/* -------------------------------------------- */
/**
* The coloration technique coloration shader fragment
* @type {string}
*/
static get COLORATION_TECHNIQUES() {
return this.getShaderTechniques("coloration");
}
/* -------------------------------------------- */
/**
* The coloration technique illumination shader fragment
* @type {string}
*/
static get ILLUMINATION_TECHNIQUES() {
return this.getShaderTechniques("illumination");
}
/* -------------------------------------------- */
/**
* The coloration technique background shader fragment
* @type {string}
*/
static get BACKGROUND_TECHNIQUES() {
return this.getShaderTechniques("background");
}
/* -------------------------------------------- */
/**
* The adjustments made into fragment shaders
* @type {string}
*/
static get ADJUSTMENTS() {
return `vec3 changedColor = finalColor;\n
${this.CONTRAST}
${this.SATURATION}
${this.EXPOSURE}
${this.SHADOW}
if ( useSampler ) finalColor = changedColor;`;
}
/* -------------------------------------------- */
/**
* Contrast adjustment
* @type {string}
*/
static CONTRAST = `
// Computing contrasted color
if ( contrast != 0.0 ) {
changedColor = (changedColor - 0.5) * (contrast + 1.0) + 0.5;
}`;
/* -------------------------------------------- */
/**
* Saturation adjustment
* @type {string}
*/
static SATURATION = `
// Computing saturated color
if ( saturation != 0.0 ) {
vec3 grey = vec3(perceivedBrightness(changedColor));
changedColor = mix(grey, changedColor, 1.0 + saturation);
}`;
/* -------------------------------------------- */
/**
* Exposure adjustment
* @type {string}
*/
static EXPOSURE = `
// Computing exposed color for background
if ( exposure > 0.0 ) {
float halfExposure = exposure * 0.5;
float attenuationStrength = attenuation * 0.25;
float lowerEdge = 0.98 - attenuationStrength;
float upperEdge = 1.02 + attenuationStrength;
float finalExposure = halfExposure *
(1.0 - smoothstep(ratio * lowerEdge, clamp(ratio * upperEdge, 0.0001, 1.0), dist)) +
halfExposure;
changedColor *= (1.0 + finalExposure);
}
`;
/* -------------------------------------------- */
/**
* Switch between an inner and outer color, by comparing distance from center to ratio
* Apply a strong gradient between the two areas if attenuation uniform is set to true
* @type {string}
*/
static SWITCH_COLOR = `
vec3 switchColor( in vec3 innerColor, in vec3 outerColor, in float dist ) {
float attenuationStrength = attenuation * 0.7;
float lowerEdge = 0.99 - attenuationStrength;
float upperEdge = 1.01 + attenuationStrength;
return mix(innerColor, outerColor, smoothstep(ratio * lowerEdge, clamp(ratio * upperEdge, 0.0001, 1.0), dist));
}`;
/* -------------------------------------------- */
/**
* Shadow adjustment
* @type {string}
*/
static SHADOW = `
// Computing shadows
if ( shadows != 0.0 ) {
float shadowing = mix(1.0, smoothstep(0.50, 0.80, perceivedBrightness(changedColor)), shadows);
// Applying shadow factor
changedColor *= shadowing;
}`;
/* -------------------------------------------- */
/**
* Transition between bright and dim colors, if requested
* @type {string}
*/
static TRANSITION = `
finalColor = switchColor(computedBrightColor, computedDimColor, dist);`;
/**
* Incorporate falloff if a attenuation uniform is requested
* @type {string}
*/
static FALLOFF = `
if ( attenuation != 0.0 ) depth *= smoothstep(1.0, 1.0 - attenuation, dist);
`;
/**
* Compute illumination uniforms
* @type {string}
*/
static COMPUTE_ILLUMINATION = `
float weightDark = weights.x;
float weightHalfdark = weights.y;
float weightDim = weights.z;
float weightBright = weights.w;
if ( computeIllumination ) {
computedDarknessLevel = texture2D(darknessLevelTexture, vSamplerUvs).r;
computedBackgroundColor = mix(ambientDaylight, ambientDarkness, computedDarknessLevel);
computedBrightColor = mix(computedBackgroundColor, ambientBrightest, weightBright);
computedDimColor = mix(computedBackgroundColor, computedBrightColor, weightDim);
// Apply lighting levels
vec3 correctedComputedBrightColor = getCorrectedColor(brightLevelCorrection);
vec3 correctedComputedDimColor = getCorrectedColor(dimLevelCorrection);
computedBrightColor = correctedComputedBrightColor;
computedDimColor = correctedComputedDimColor;
}
else {
computedBackgroundColor = colorBackground;
computedDimColor = colorDim;
computedBrightColor = colorBright;
computedDarknessLevel = darknessLevel;
}
computedDimColor = max(computedDimColor, computedBackgroundColor);
computedBrightColor = max(computedBrightColor, computedBackgroundColor);
if ( globalLight && ((computedDarknessLevel < globalLightThresholds[0]) || (computedDarknessLevel > globalLightThresholds[1])) ) discard;
`;
/**
* Initialize fragment with common properties
* @type {string}
*/
static FRAGMENT_BEGIN = `
${this.COMPUTE_ILLUMINATION}
float dist = distance(vUvs, vec2(0.5)) * 2.0;
vec4 depthColor = texture2D(depthTexture, vSamplerUvs);
float depth = smoothstep(0.0, 1.0, vDepth) * step(depthColor.g, depthElevation) * step(depthElevation, (254.5 / 255.0) - depthColor.r);
vec4 baseColor = useSampler ? texture2D(primaryTexture, vSamplerUvs) : vec4(1.0);
vec3 finalColor = baseColor.rgb;
`;
/**
* Shader final
* @type {string}
*/
static FRAGMENT_END = `
gl_FragColor = vec4(finalColor, 1.0) * depth;
`;
/* -------------------------------------------- */
/* Shader Techniques for lighting */
/* -------------------------------------------- */
/**
* A mapping of available shader techniques
* @type {Record<string, ShaderTechnique>}
*/
static SHADER_TECHNIQUES = {
LEGACY: {
id: 0,
label: "LIGHT.LegacyColoration"
},
LUMINANCE: {
id: 1,
label: "LIGHT.AdaptiveLuminance",
coloration: `
float reflection = perceivedBrightness(baseColor);
finalColor *= reflection;`
},
INTERNAL_HALO: {
id: 2,
label: "LIGHT.InternalHalo",
coloration: `
float reflection = perceivedBrightness(baseColor);
finalColor = switchColor(finalColor, finalColor * reflection, dist);`
},
EXTERNAL_HALO: {
id: 3,
label: "LIGHT.ExternalHalo",
coloration: `
float reflection = perceivedBrightness(baseColor);
finalColor = switchColor(finalColor * reflection, finalColor, dist);`
},
COLOR_BURN: {
id: 4,
label: "LIGHT.ColorBurn",
coloration: `
float reflection = perceivedBrightness(baseColor);
finalColor = (finalColor * (1.0 - sqrt(reflection))) / clamp(baseColor.rgb * 2.0, 0.001, 0.25);`
},
INTERNAL_BURN: {
id: 5,
label: "LIGHT.InternalBurn",
coloration: `
float reflection = perceivedBrightness(baseColor);
finalColor = switchColor((finalColor * (1.0 - sqrt(reflection))) / clamp(baseColor.rgb * 2.0, 0.001, 0.25), finalColor * reflection, dist);`
},
EXTERNAL_BURN: {
id: 6,
label: "LIGHT.ExternalBurn",
coloration: `
float reflection = perceivedBrightness(baseColor);
finalColor = switchColor(finalColor * reflection, (finalColor * (1.0 - sqrt(reflection))) / clamp(baseColor.rgb * 2.0, 0.001, 0.25), dist);`
},
LOW_ABSORPTION: {
id: 7,
label: "LIGHT.LowAbsorption",
coloration: `
float reflection = perceivedBrightness(baseColor);
reflection *= smoothstep(0.35, 0.75, reflection);
finalColor *= reflection;`
},
HIGH_ABSORPTION: {
id: 8,
label: "LIGHT.HighAbsorption",
coloration: `
float reflection = perceivedBrightness(baseColor);
reflection *= smoothstep(0.55, 0.85, reflection);
finalColor *= reflection;`
},
INVERT_ABSORPTION: {
id: 9,
label: "LIGHT.InvertAbsorption",
coloration: `
float r = reversePerceivedBrightness(baseColor);
finalColor *= (r * r * r * r * r);`
},
NATURAL_LIGHT: {
id: 10,
label: "LIGHT.NaturalLight",
coloration: `
float reflection = perceivedBrightness(baseColor);
finalColor *= reflection;`,
background: `
float ambientColorIntensity = perceivedBrightness(computedBackgroundColor);
vec3 mutedColor = mix(finalColor,
finalColor * mix(color, computedBackgroundColor, ambientColorIntensity),
backgroundAlpha);
finalColor = mix( finalColor,
mutedColor,
computedDarknessLevel);`
}
};
/* -------------------------------------------- */
/* Deprecations and Compatibility */
/* -------------------------------------------- */
/**
* @deprecated since v12
* @ignore
*/
getDarknessPenalty(darknessLevel, luminosity) {
const msg = "AdaptiveLightingShader#getDarknessPenalty is deprecated without replacement. " +
"The darkness penalty is no longer applied on light and vision sources.";
foundry.utils.logCompatibilityWarning(msg, {since: 12, until: 14});
return 0;
}
}

View File

@@ -0,0 +1,116 @@
/**
* The default coloration shader used by standard rendering and animations.
* A fragment shader which creates a light source.
*/
class AdaptiveColorationShader extends AdaptiveLightingShader {
/** @override */
static FRAGMENT_END = `
gl_FragColor = vec4(finalColor * depth, 1.0);
`;
/**
* The adjustments made into fragment shaders
* @type {string}
*/
static get ADJUSTMENTS() {
return `
vec3 changedColor = finalColor;\n
${this.SATURATION}
${this.SHADOW}
finalColor = changedColor;\n`;
}
/** @override */
static SHADOW = `
// Computing shadows
if ( shadows != 0.0 ) {
float shadowing = mix(1.0, smoothstep(0.25, 0.35, perceivedBrightness(baseColor.rgb)), shadows);
// Applying shadow factor
changedColor *= shadowing;
}
`;
/**
* Memory allocations for the Adaptive Coloration Shader
* @type {string}
*/
static SHADER_HEADER = `
${this.FRAGMENT_UNIFORMS}
${this.VERTEX_FRAGMENT_VARYINGS}
${this.FRAGMENT_FUNCTIONS}
${this.CONSTANTS}
${this.SWITCH_COLOR}
`;
/** @inheritdoc */
static fragmentShader = `
${this.SHADER_HEADER}
${this.PERCEIVED_BRIGHTNESS}
void main() {
${this.FRAGMENT_BEGIN}
finalColor = color * colorationAlpha;
${this.COLORATION_TECHNIQUES}
${this.ADJUSTMENTS}
${this.FALLOFF}
${this.FRAGMENT_END}
}`;
/** @inheritdoc */
static defaultUniforms = {
technique: 1,
shadows: 0,
contrast: 0,
saturation: 0,
colorationAlpha: 1,
intensity: 5,
attenuation: 0.5,
ratio: 0.5,
color: [1, 1, 1],
time: 0,
hasColor: false,
screenDimensions: [1, 1],
useSampler: false,
primaryTexture: null,
depthTexture: null,
darknessLevelTexture: null,
depthElevation: 1,
ambientBrightest: [1, 1, 1],
ambientDarkness: [0, 0, 0],
ambientDaylight: [1, 1, 1],
weights: [0, 0, 0, 0],
dimLevelCorrection: 1,
brightLevelCorrection: 2,
computeIllumination: false,
globalLight: false,
globalLightThresholds: [0, 0]
};
static {
const initial = foundry.data.LightData.cleanData();
this.defaultUniforms.technique = initial.coloration;
this.defaultUniforms.contrast = initial.contrast;
this.defaultUniforms.shadows = initial.shadows;
this.defaultUniforms.saturation = initial.saturation;
this.defaultUniforms.intensity = initial.animation.intensity;
this.defaultUniforms.attenuation = initial.attenuation;
}
/**
* Flag whether the coloration shader is currently required.
* @type {boolean}
*/
get isRequired() {
const vs = canvas.visibility.lightingVisibility;
// Checking if a vision mode is forcing the rendering
if ( vs.coloration === VisionMode.LIGHTING_VISIBILITY.REQUIRED ) return true;
// Checking if disabled
if ( vs.coloration === VisionMode.LIGHTING_VISIBILITY.DISABLED ) return false;
// Otherwise, we need the coloration if it has color
return this.constructor.forceDefaultColor || this.uniforms.hasColor;
}
}

View File

@@ -0,0 +1,119 @@
/**
* The default coloration shader used by standard rendering and animations.
* A fragment shader which creates a solid light source.
*/
class AdaptiveDarknessShader extends AdaptiveLightingShader {
/** @override */
update() {
super.update();
this.uniforms.darknessLevel = canvas.environment.darknessLevel;
}
/* -------------------------------------------- */
/**
* Flag whether the darkness shader is currently required.
* Check vision modes requirements first, then
* if key uniforms are at their default values, we don't need to render the background container.
* @type {boolean}
*/
get isRequired() {
const vs = canvas.visibility.lightingVisibility;
// Checking if darkness layer is disabled
if ( vs.darkness === VisionMode.LIGHTING_VISIBILITY.DISABLED ) return false;
// Otherwise, returns true in every circumstances
return true;
}
/* -------------------------------------------- */
/* GLSL Statics */
/* -------------------------------------------- */
/** @override */
static defaultUniforms = {
intensity: 5,
color: Color.from("#8651d5").rgb,
screenDimensions: [1, 1],
time: 0,
primaryTexture: null,
depthTexture: null,
visionTexture: null,
darknessLevelTexture: null,
depthElevation: 1,
ambientBrightest: [1, 1, 1],
ambientDarkness: [0, 0, 0],
ambientDaylight: [1, 1, 1],
weights: [0, 0, 0, 0],
dimLevelCorrection: 1,
brightLevelCorrection: 2,
borderDistance: 0,
darknessLevel: 0,
computeIllumination: false,
globalLight: false,
globalLightThresholds: [0, 0],
enableVisionMasking: false
};
static {
const initial = foundry.data.LightData.cleanData();
this.defaultUniforms.intensity = initial.animation.intensity;
}
/* -------------------------------------------- */
/**
* Shader final
* @type {string}
*/
static FRAGMENT_END = `
gl_FragColor = vec4(finalColor, 1.0) * depth;
`;
/* -------------------------------------------- */
/**
* Initialize fragment with common properties
* @type {string}
*/
static FRAGMENT_BEGIN = `
${this.COMPUTE_ILLUMINATION}
float dist = distance(vUvs, vec2(0.5)) * 2.0;
vec4 depthColor = texture2D(depthTexture, vSamplerUvs);
float depth = smoothstep(0.0, 1.0, vDepth) *
step(depthColor.g, depthElevation) *
step(depthElevation, (254.5 / 255.0) - depthColor.r) *
(enableVisionMasking ? 1.0 - step(texture2D(visionTexture, vSamplerUvs).r, 0.0) : 1.0) *
(1.0 - smoothstep(borderDistance, 1.0, dist));
vec4 baseColor = texture2D(primaryTexture, vSamplerUvs);
vec3 finalColor = baseColor.rgb;
`;
/* -------------------------------------------- */
/**
* Memory allocations for the Adaptive Background Shader
* @type {string}
*/
static SHADER_HEADER = `
${this.FRAGMENT_UNIFORMS}
${this.VERTEX_FRAGMENT_VARYINGS}
${this.FRAGMENT_FUNCTIONS}
${this.CONSTANTS}
`;
/* -------------------------------------------- */
/** @inheritdoc */
static fragmentShader = `
${this.SHADER_HEADER}
${this.PERCEIVED_BRIGHTNESS}
void main() {
${this.FRAGMENT_BEGIN}
finalColor *= (mix(color, color * 0.33, darknessLevel) * colorationAlpha);
${this.FRAGMENT_END}
}`;
}

View File

@@ -0,0 +1,81 @@
/**
* Bewitching Wave animation illumination shader
*/
class BewitchingWaveIlluminationShader extends AdaptiveIlluminationShader {
static fragmentShader = `
${this.SHADER_HEADER}
${this.PRNG}
${this.NOISE}
${this.FBM(4, 1.0)}
${this.PERCEIVED_BRIGHTNESS}
// Transform UV
vec2 transform(in vec2 uv, in float dist) {
float t = time * 0.25;
mat2 rotmat = mat2(cos(t), -sin(t), sin(t), cos(t));
mat2 scalemat = mat2(2.5, 0.0, 0.0, 2.5);
uv -= vec2(0.5);
uv *= rotmat * scalemat;
uv += vec2(0.5);
return uv;
}
float bwave(in float dist) {
vec2 uv = transform(vUvs, dist);
float motion = fbm(uv + time * 0.25);
float distortion = mix(1.0, motion, clamp(1.0 - dist, 0.0, 1.0));
float sinWave = 0.5 * (sin(-time * 6.0 + dist * 10.0 * intensity * distortion) + 1.0);
return 0.3 * sinWave + 0.8;
}
void main() {
${this.FRAGMENT_BEGIN}
${this.TRANSITION}
finalColor *= bwave(dist);
${this.ADJUSTMENTS}
${this.FALLOFF}
${this.FRAGMENT_END}
}`;
}
/* -------------------------------------------- */
/**
* Bewitching Wave animation coloration shader
*/
class BewitchingWaveColorationShader extends AdaptiveColorationShader {
static fragmentShader = `
${this.SHADER_HEADER}
${this.PRNG}
${this.NOISE}
${this.FBM(4, 1.0)}
${this.PERCEIVED_BRIGHTNESS}
// Transform UV
vec2 transform(in vec2 uv, in float dist) {
float t = time * 0.25;
mat2 rotmat = mat2(cos(t), -sin(t), sin(t), cos(t));
mat2 scalemat = mat2(2.5, 0.0, 0.0, 2.5);
uv -= vec2(0.5);
uv *= rotmat * scalemat;
uv += vec2(0.5);
return uv;
}
float bwave(in float dist) {
vec2 uv = transform(vUvs, dist);
float motion = fbm(uv + time * 0.25);
float distortion = mix(1.0, motion, clamp(1.0 - dist, 0.0, 1.0));
float sinWave = 0.5 * (sin(-time * 6.0 + dist * 10.0 * intensity * distortion) + 1.0);
return 0.55 * sinWave + 0.8;
}
void main() {
${this.FRAGMENT_BEGIN}
finalColor = color * bwave(dist) * colorationAlpha;
${this.COLORATION_TECHNIQUES}
${this.ADJUSTMENTS}
${this.FALLOFF}
${this.FRAGMENT_END}
}`;
}

View File

@@ -0,0 +1,41 @@
/**
* Black Hole animation illumination shader
*/
class BlackHoleDarknessShader extends AdaptiveDarknessShader {
/* -------------------------------------------- */
/* GLSL Statics */
/* -------------------------------------------- */
/** @inheritdoc */
static fragmentShader = `
${this.SHADER_HEADER}
${this.PRNG}
${this.NOISE}
${this.FBMHQ()}
${this.PERCEIVED_BRIGHTNESS}
// create an emanation composed of n beams, n = intensity
vec3 beamsEmanation(in vec2 uv, in float dist, in vec3 pCol) {
float angle = atan(uv.x, uv.y) * INVTWOPI;
// Create the beams
float dad = mix(0.33, 5.0, dist);
float beams = fract(angle + sin(dist * 30.0 * (intensity * 0.2) - time + fbm(uv * 10.0 + time * 0.25, 1.0) * dad));
// Compose the final beams and reverse beams, to get a nice gradient on EACH side of the beams.
beams = max(beams, 1.0 - beams);
// Creating the effect
return smoothstep(0.0, 1.1 + (intensity * 0.1), beams * pCol);
}
void main() {
${this.FRAGMENT_BEGIN}
vec2 uvs = (2.0 * vUvs) - 1.0;
finalColor *= (mix(color, color * 0.66, darknessLevel) * colorationAlpha);
float rd = pow(1.0 - dist, 3.0);
finalColor = beamsEmanation(uvs, rd, finalColor);
${this.FRAGMENT_END}
}`;
}

View File

@@ -0,0 +1,25 @@
/**
* Chroma animation coloration shader
*/
class ChromaColorationShader extends AdaptiveColorationShader {
/** @override */
static forceDefaultColor = true;
/** @override */
static fragmentShader = `
${this.SHADER_HEADER}
${this.HSB2RGB}
${this.PERCEIVED_BRIGHTNESS}
void main() {
${this.FRAGMENT_BEGIN}
finalColor = mix( color,
hsb2rgb(vec3(time * 0.25, 1.0, 1.0)),
intensity * 0.1 ) * colorationAlpha;
${this.COLORATION_TECHNIQUES}
${this.ADJUSTMENTS}
${this.FALLOFF}
${this.FRAGMENT_END}
}`;
}

View File

@@ -0,0 +1,38 @@
/**
* Emanation animation coloration shader
*/
class EmanationColorationShader extends AdaptiveColorationShader {
/** @override */
static forceDefaultColor = true;
/** @override */
static fragmentShader = `
${this.SHADER_HEADER}
${this.PERCEIVED_BRIGHTNESS}
// Create an emanation composed of n beams, n = intensity
vec3 beamsEmanation(in vec2 uv, in float dist) {
float angle = atan(uv.x, uv.y) * INVTWOPI;
// create the beams
float beams = fract( angle * intensity + sin(dist * 10.0 - time));
// compose the final beams with max, to get a nice gradient on EACH side of the beams.
beams = max(beams, 1.0 - beams);
// creating the effect : applying color and color correction. saturate the entire output color.
return smoothstep( 0.0, 1.0, beams * color);
}
void main() {
${this.FRAGMENT_BEGIN}
vec2 uvs = (2.0 * vUvs) - 1.0;
// apply beams emanation, fade and alpha
finalColor = beamsEmanation(uvs, dist) * colorationAlpha;
${this.COLORATION_TECHNIQUES}
${this.ADJUSTMENTS}
${this.FALLOFF}
${this.FRAGMENT_END}
}`;
}

View File

@@ -0,0 +1,77 @@
/**
* Energy field animation coloration shader
*/
class EnergyFieldColorationShader extends AdaptiveColorationShader {
/** @override */
static forceDefaultColor = true;
/** @override */
static fragmentShader = `
${this.SHADER_HEADER}
${this.PRNG3D}
${this.PERCEIVED_BRIGHTNESS}
// classic 3d voronoi (with some bug fixes)
vec3 voronoi3d(const in vec3 x) {
vec3 p = floor(x);
vec3 f = fract(x);
float id = 0.0;
vec2 res = vec2(100.0);
for (int k = -1; k <= 1; k++) {
for (int j = -1; j <= 1; j++) {
for (int i = -1; i <= 1; i++) {
vec3 b = vec3(float(i), float(j), float(k));
vec3 r = vec3(b) - f + random(p + b);
float d = dot(r, r);
float cond = max(sign(res.x - d), 0.0);
float nCond = 1.0 - cond;
float cond2 = nCond * max(sign(res.y - d), 0.0);
float nCond2 = 1.0 - cond2;
id = (dot(p + b, vec3(1.0, 67.0, 142.0)) * cond) + (id * nCond);
res = vec2(d, res.x) * cond + res * nCond;
res.y = cond2 * d + nCond2 * res.y;
}
}
}
// replaced abs(id) by pow( abs(id + 10.0), 0.01)
// needed to remove artifacts in some specific configuration
return vec3( sqrt(res), pow( abs(id + 10.0), 0.01) );
}
void main() {
${this.FRAGMENT_BEGIN}
vec2 uv = vUvs;
// Hemispherize and scaling the uv
float f = (1.0 - sqrt(1.0 - dist)) / dist;
uv -= vec2(0.5);
uv *= f * 4.0 * intensity;
uv += vec2(0.5);
// time and uv motion variables
float t = time * 0.4;
float uvx = cos(uv.x - t);
float uvy = cos(uv.y + t);
float uvxt = cos(uv.x + sin(t));
float uvyt = sin(uv.y + cos(t));
// creating the voronoi 3D sphere, applying motion
vec3 c = voronoi3d(vec3(uv.x - uvx + uvyt,
mix(uv.x, uv.y, 0.5) + uvxt - uvyt + uvx,
uv.y + uvxt - uvx));
// applying color and contrast, to create sharp black areas.
finalColor = c.x * c.x * c.x * color * colorationAlpha;
${this.COLORATION_TECHNIQUES}
${this.ADJUSTMENTS}
${this.FALLOFF}
${this.FRAGMENT_END}
}`;
}

View File

@@ -0,0 +1,95 @@
/**
* Fairy light animation coloration shader
*/
class FairyLightColorationShader extends AdaptiveColorationShader {
/** @override */
static forceDefaultColor = true;
/** @override */
static fragmentShader = `
${this.SHADER_HEADER}
${this.HSB2RGB}
${this.PRNG}
${this.NOISE}
${this.FBM(3, 1.0)}
${this.PERCEIVED_BRIGHTNESS}
void main() {
${this.FRAGMENT_BEGIN}
// Creating distortion with vUvs and fbm
float distortion1 = fbm(vec2(
fbm(vUvs * 3.0 + time * 0.50),
fbm((-vUvs + vec2(1.)) * 5.0 + time * INVTHREE)));
float distortion2 = fbm(vec2(
fbm(-vUvs * 3.0 + time * 0.50),
fbm((-vUvs + vec2(1.)) * 5.0 - time * INVTHREE)));
vec2 uv = vUvs;
// time related var
float t = time * 0.5;
float tcos = 0.5 * (0.5 * (cos(t)+1.0)) + 0.25;
float tsin = 0.5 * (0.5 * (sin(t)+1.0)) + 0.25;
// Creating distortions with cos and sin : create fluidity
uv -= PIVOT;
uv *= tcos * distortion1;
uv *= tsin * distortion2;
uv *= fbm(vec2(time + distortion1, time + distortion2));
uv += PIVOT;
// Creating the rainbow
float intens = intensity * 0.1;
vec2 nuv = vUvs * 2.0 - 1.0;
vec2 puv = vec2(atan(nuv.x, nuv.y) * INVTWOPI + 0.5, length(nuv));
vec3 rainbow = hsb2rgb(vec3(puv.x + puv.y - time * 0.2, 1.0, 1.0));
vec3 mixedColor = mix(color, rainbow, smoothstep(0.0, 1.5 - intens, dist));
finalColor = distortion1 * distortion1 *
distortion2 * distortion2 *
mixedColor * colorationAlpha * (1.0 - dist * dist * dist) *
mix( uv.x + distortion1 * 4.5 * (intensity * 0.4),
uv.y + distortion2 * 4.5 * (intensity * 0.4), tcos);
${this.COLORATION_TECHNIQUES}
${this.ADJUSTMENTS}
${this.FALLOFF}
${this.FRAGMENT_END}
}`;
}
/* -------------------------------------------- */
/**
* Fairy light animation illumination shader
*/
class FairyLightIlluminationShader extends AdaptiveIlluminationShader {
static fragmentShader = `
${this.SHADER_HEADER}
${this.PERCEIVED_BRIGHTNESS}
${this.PRNG}
${this.NOISE}
${this.FBM(3, 1.0)}
void main() {
${this.FRAGMENT_BEGIN}
// Creating distortion with vUvs and fbm
float distortion1 = fbm(vec2(
fbm(vUvs * 3.0 - time * 0.50),
fbm((-vUvs + vec2(1.)) * 5.0 + time * INVTHREE)));
float distortion2 = fbm(vec2(
fbm(-vUvs * 3.0 - time * 0.50),
fbm((-vUvs + vec2(1.)) * 5.0 - time * INVTHREE)));
// linear interpolation motion
float motionWave = 0.5 * (0.5 * (cos(time * 0.5) + 1.0)) + 0.25;
${this.TRANSITION}
finalColor *= mix(distortion1, distortion2, motionWave);
${this.ADJUSTMENTS}
${this.FALLOFF}
${this.FRAGMENT_END}
}`;
}

View File

@@ -0,0 +1,82 @@
/**
* Alternative torch illumination shader
*/
class FlameIlluminationShader extends AdaptiveIlluminationShader {
static fragmentShader = `
${this.SHADER_HEADER}
${this.PERCEIVED_BRIGHTNESS}
void main() {
${this.FRAGMENT_BEGIN}
${this.TRANSITION}
finalColor *= brightnessPulse;
${this.ADJUSTMENTS}
${this.FALLOFF}
${this.FRAGMENT_END}
}`;
/** @inheritdoc */
static defaultUniforms = ({...super.defaultUniforms, brightnessPulse: 1});
}
/* -------------------------------------------- */
/**
* Alternative torch coloration shader
*/
class FlameColorationShader extends AdaptiveColorationShader {
static fragmentShader = `
${this.SHADER_HEADER}
${this.PRNG}
${this.NOISE}
${this.FBMHQ(3)}
${this.PERCEIVED_BRIGHTNESS}
vec2 scale(in vec2 uv, in float scale) {
mat2 scalemat = mat2(scale, 0.0, 0.0, scale);
uv -= PIVOT;
uv *= scalemat;
uv += PIVOT;
return uv;
}
void main() {
${this.FRAGMENT_BEGIN}
vec2 uv = scale(vUvs, 10.0 * ratio);
float intens = pow(0.1 * intensity, 2.0);
float fratioInner = ratio * (intens * 0.5) -
(0.005 *
fbm( vec2(
uv.x + time * 8.01,
uv.y + time * 10.72), 1.0));
float fratioOuter = ratio - (0.007 *
fbm( vec2(
uv.x + time * 7.04,
uv.y + time * 9.51), 2.0));
float fdist = max(dist - fratioInner * intens, 0.0);
float flameDist = smoothstep(clamp(0.97 - fratioInner, 0.0, 1.0),
clamp(1.03 - fratioInner, 0.0, 1.0),
1.0 - fdist);
float flameDistInner = smoothstep(clamp(0.95 - fratioOuter, 0.0, 1.0),
clamp(1.05 - fratioOuter, 0.0, 1.0),
1.0 - fdist);
vec3 flameColor = color * 8.0;
vec3 flameFlickerColor = color * 1.2;
finalColor = mix(mix(color, flameFlickerColor, flameDistInner),
flameColor,
flameDist) * brightnessPulse * colorationAlpha;
${this.COLORATION_TECHNIQUES}
${this.ADJUSTMENTS}
${this.FALLOFF}
${this.FRAGMENT_END}
}
`;
/** @inheritdoc */
static defaultUniforms = ({ ...super.defaultUniforms, brightnessPulse: 1});
}

View File

@@ -0,0 +1,53 @@
/**
* Fog animation coloration shader
*/
class FogColorationShader extends AdaptiveColorationShader {
/** @override */
static forceDefaultColor = true;
/** @override */
static fragmentShader = `
${this.SHADER_HEADER}
${this.PRNG}
${this.NOISE}
${this.FBM(4, 1.0)}
${this.PERCEIVED_BRIGHTNESS}
vec3 fog() {
// constructing the palette
vec3 c1 = color * 0.60;
vec3 c2 = color * 0.95;
vec3 c3 = color * 0.50;
vec3 c4 = color * 0.75;
vec3 c5 = vec3(0.3);
vec3 c6 = color;
// creating the deformation
vec2 uv = vUvs;
vec2 p = uv.xy * 8.0;
// time motion fbm and palette mixing
float q = fbm(p - time * 0.1);
vec2 r = vec2(fbm(p + q - time * 0.5 - p.x - p.y),
fbm(p + q - time * 0.3));
vec3 c = clamp(mix(c1,
c2,
fbm(p + r)) + mix(c3, c4, r.x)
- mix(c5, c6, r.y),
vec3(0.0), vec3(1.0));
// returning the color
return c;
}
void main() {
${this.FRAGMENT_BEGIN}
float intens = intensity * 0.2;
// applying fog
finalColor = fog() * intens * colorationAlpha;
${this.COLORATION_TECHNIQUES}
${this.ADJUSTMENTS}
${this.FALLOFF}
${this.FRAGMENT_END}
}`;
}

View File

@@ -0,0 +1,87 @@
/**
* A futuristic Force Grid animation.
*/
class ForceGridColorationShader extends AdaptiveColorationShader {
/** @override */
static forceDefaultColor = true;
/** @override */
static fragmentShader = `
${this.SHADER_HEADER}
${this.PERCEIVED_BRIGHTNESS}
const float MAX_INTENSITY = 1.2;
const float MIN_INTENSITY = 0.8;
vec2 hspherize(in vec2 uv, in float dist) {
float f = (1.0 - sqrt(1.0 - dist)) / dist;
uv -= vec2(0.50);
uv *= f * 5.0;
uv += vec2(0.5);
return uv;
}
float wave(in float dist) {
float sinWave = 0.5 * (sin(time * 6.0 + pow(1.0 - dist, 0.10) * 35.0 * intensity) + 1.0);
return ((MAX_INTENSITY - MIN_INTENSITY) * sinWave) + MIN_INTENSITY;
}
float fpert(in float d, in float p) {
return max(0.3 -
mod(p + time + d * 0.3, 3.5),
0.0) * intensity * 2.0;
}
float pert(in vec2 uv, in float dist, in float d, in float w) {
uv -= vec2(0.5);
float f = fpert(d, min( uv.y, uv.x)) +
fpert(d, min(-uv.y, uv.x)) +
fpert(d, min(-uv.y, -uv.x)) +
fpert(d, min( uv.y, -uv.x));
f *= f;
return max(f, 3.0 - f) * w;
}
vec3 forcegrid(vec2 suv, in float dist) {
vec2 uv = suv - vec2(0.2075, 0.2075);
vec2 cid2 = floor(uv);
float cid = (cid2.y + cid2.x);
uv = fract(uv);
float r = 0.3;
float d = 1.0;
float e;
float c;
for( int i = 0; i < 5; i++ ) {
e = uv.x - r;
c = clamp(1.0 - abs(e * 0.75), 0.0, 1.0);
d += pow(c, 200.0) * (1.0 - dist);
if ( e > 0.0 ) {
uv.x = (uv.x - r) / (2.0 - r);
}
uv = uv.yx;
}
float w = wave(dist);
vec3 col = vec3(max(d - 1.0, 0.0)) * 1.8;
col *= pert(suv, dist * intensity * 4.0, d, w);
col += color * 0.30 * w;
return col * color;
}
void main() {
${this.FRAGMENT_BEGIN}
vec2 uvs = vUvs;
uvs -= PIVOT;
uvs *= intensity * 0.2;
uvs += PIVOT;
vec2 suvs = hspherize(uvs, dist);
finalColor = forcegrid(suvs, dist) * colorationAlpha;
${this.COLORATION_TECHNIQUES}
${this.ADJUSTMENTS}
${this.FALLOFF}
${this.FRAGMENT_END}
}
`;
}

View File

@@ -0,0 +1,86 @@
/**
* Ghost light animation illumination shader
*/
class GhostLightIlluminationShader extends AdaptiveIlluminationShader {
static fragmentShader = `
${this.SHADER_HEADER}
${this.PERCEIVED_BRIGHTNESS}
${this.PRNG}
${this.NOISE}
${this.FBM(3, 1.0)}
void main() {
${this.FRAGMENT_BEGIN}
// Creating distortion with vUvs and fbm
float distortion1 = fbm(vec2(
fbm(vUvs * 5.0 - time * 0.50),
fbm((-vUvs - vec2(0.01)) * 5.0 + time * INVTHREE)));
float distortion2 = fbm(vec2(
fbm(-vUvs * 5.0 - time * 0.50),
fbm((-vUvs + vec2(0.01)) * 5.0 + time * INVTHREE)));
vec2 uv = vUvs;
// time related var
float t = time * 0.5;
float tcos = 0.5 * (0.5 * (cos(t)+1.0)) + 0.25;
${this.TRANSITION}
finalColor *= mix( distortion1 * 1.5 * (intensity * 0.2),
distortion2 * 1.5 * (intensity * 0.2), tcos);
${this.ADJUSTMENTS}
${this.FALLOFF}
${this.FRAGMENT_END}
}`;
}
/* -------------------------------------------- */
/**
* Ghost light animation coloration shader
*/
class GhostLightColorationShader extends AdaptiveColorationShader {
static fragmentShader = `
${this.SHADER_HEADER}
${this.PRNG}
${this.NOISE}
${this.FBM(3, 1.0)}
${this.PERCEIVED_BRIGHTNESS}
void main() {
${this.FRAGMENT_BEGIN}
// Creating distortion with vUvs and fbm
float distortion1 = fbm(vec2(
fbm(vUvs * 3.0 + time * 0.50),
fbm((-vUvs + vec2(1.)) * 5.0 + time * INVTHREE)));
float distortion2 = fbm(vec2(
fbm(-vUvs * 3.0 + time * 0.50),
fbm((-vUvs + vec2(1.)) * 5.0 - time * INVTHREE)));
vec2 uv = vUvs;
// time related var
float t = time * 0.5;
float tcos = 0.5 * (0.5 * (cos(t)+1.0)) + 0.25;
float tsin = 0.5 * (0.5 * (sin(t)+1.0)) + 0.25;
// Creating distortions with cos and sin : create fluidity
uv -= PIVOT;
uv *= tcos * distortion1;
uv *= tsin * distortion2;
uv *= fbm(vec2(time + distortion1, time + distortion2));
uv += PIVOT;
finalColor = distortion1 * distortion1 *
distortion2 * distortion2 *
color * pow(1.0 - dist, dist)
* colorationAlpha * mix( uv.x + distortion1 * 4.5 * (intensity * 0.2),
uv.y + distortion2 * 4.5 * (intensity * 0.2), tcos);
${this.COLORATION_TECHNIQUES}
${this.ADJUSTMENTS}
${this.FALLOFF}
${this.FRAGMENT_END}
}`;
}

View File

@@ -0,0 +1,83 @@
/**
* Hexagonal dome animation coloration shader
*/
class HexaDomeColorationShader extends AdaptiveColorationShader {
/** @override */
static forceDefaultColor = true;
/** @override */
static fragmentShader = `
${this.SHADER_HEADER}
${this.PERCEIVED_BRIGHTNESS}
// rotate and scale uv
vec2 transform(in vec2 uv, in float dist) {
float hspherize = (1.0 - sqrt(1.0 - dist)) / dist;
float t = -time * 0.20;
float scale = 10.0 / (11.0 - intensity);
float cost = cos(t);
float sint = sin(t);
mat2 rotmat = mat2(cost, -sint, sint, cost);
mat2 scalemat = mat2(scale, 0.0, 0.0, scale);
uv -= PIVOT;
uv *= rotmat * scalemat * hspherize;
uv += PIVOT;
return uv;
}
// Adapted classic hexa algorithm
float hexDist(in vec2 uv) {
vec2 p = abs(uv);
float c = dot(p, normalize(vec2(1.0, 1.73)));
c = max(c, p.x);
return c;
}
vec4 hexUvs(in vec2 uv) {
const vec2 r = vec2(1.0, 1.73);
const vec2 h = r*0.5;
vec2 a = mod(uv, r) - h;
vec2 b = mod(uv - h, r) - h;
vec2 gv = dot(a, a) < dot(b,b) ? a : b;
float x = atan(gv.x, gv.y);
float y = 0.55 - hexDist(gv);
vec2 id = uv - gv;
return vec4(x, y, id.x, id.y);
}
vec3 hexa(in vec2 uv) {
float t = time;
vec2 uv1 = uv + vec2(0.0, sin(uv.y) * 0.25);
vec2 uv2 = 0.5 * uv1 + 0.5 * uv + vec2(0.55, 0);
float a = 0.2;
float c = 0.5;
float s = -1.0;
uv2 *= mat2(c, -s, s, c);
vec3 col = color;
float hexy = hexUvs(uv2 * 10.0).y;
float hexa = smoothstep( 3.0 * (cos(t)) + 4.5, 12.0, hexy * 20.0) * 3.0;
col *= mix(hexa, 1.0 - hexa, min(hexy, 1.0 - hexy));
col += color * fract(smoothstep(1.0, 2.0, hexy * 20.0)) * 0.65;
return col;
}
void main() {
${this.FRAGMENT_BEGIN}
// Rotate, magnify and hemispherize the uvs
vec2 uv = transform(vUvs, dist);
// Hexaify the uv (hemisphere) and apply fade and alpha
finalColor = hexa(uv) * pow(1.0 - dist, 0.18) * colorationAlpha;
${this.COLORATION_TECHNIQUES}
${this.ADJUSTMENTS}
${this.FALLOFF}
${this.FRAGMENT_END}
}`;
}

View File

@@ -0,0 +1,57 @@
/**
* Light dome animation coloration shader
*/
class LightDomeColorationShader extends AdaptiveColorationShader {
/** @override */
static forceDefaultColor = true;
/** @override */
static fragmentShader = `
${this.SHADER_HEADER}
${this.PRNG}
${this.NOISE}
${this.FBM(2)}
${this.PERCEIVED_BRIGHTNESS}
// Rotate and scale uv
vec2 transform(in vec2 uv, in float dist) {
float hspherize = (1.0 - sqrt(1.0 - dist)) / dist;
float t = time * 0.02;
mat2 rotmat = mat2(cos(t), -sin(t), sin(t), cos(t));
mat2 scalemat = mat2(8.0 * intensity, 0.0, 0.0, 8.0 * intensity);
uv -= PIVOT;
uv *= rotmat * scalemat * hspherize;
uv += PIVOT;
return uv;
}
vec3 ripples(in vec2 uv) {
// creating the palette
vec3 c1 = color * 0.550;
vec3 c2 = color * 0.020;
vec3 c3 = color * 0.3;
vec3 c4 = color;
vec3 c5 = color * 0.025;
vec3 c6 = color * 0.200;
vec2 p = uv + vec2(5.0);
float q = 2.0 * fbm(p + time * 0.2);
vec2 r = vec2(fbm(p + q + ( time ) - p.x - p.y), fbm(p * 2.0 + ( time )));
return clamp( mix( c1, c2, abs(fbm(p + r)) ) + mix( c3, c4, abs(r.x * r.x * r.x) ) - mix( c5, c6, abs(r.y * r.y)), vec3(0.0), vec3(1.0));
}
void main() {
${this.FRAGMENT_BEGIN}
// to hemispherize, rotate and magnify
vec2 uv = transform(vUvs, dist);
finalColor = ripples(uv) * pow(1.0 - dist, 0.25) * colorationAlpha;
${this.COLORATION_TECHNIQUES}
${this.ADJUSTMENTS}
${this.FALLOFF}
${this.FRAGMENT_END}
}`;
}

View File

@@ -0,0 +1,101 @@
/**
* Creates a gloomy ring of pure darkness.
*/
class MagicalGloomDarknessShader extends AdaptiveDarknessShader {
/* -------------------------------------------- */
/* GLSL Statics */
/* -------------------------------------------- */
/** @inheritdoc */
static fragmentShader = `
${this.SHADER_HEADER}
${this.PERCEIVED_BRIGHTNESS}
${this.PRNG}
${this.NOISE}
${this.FBMHQ()}
vec3 colorScale(in float t) {
return vec3(1.0 + 0.8 * t) * t;
}
vec2 radialProjection(in vec2 uv, in float s, in float i) {
uv = vec2(0.5) - uv;
float px = 1.0 - fract(atan(uv.y, uv.x) / TWOPI + 0.25) + s;
float py = (length(uv) * (1.0 + i * 2.0) - i) * 2.0;
return vec2(px, py);
}
float interference(in vec2 n) {
float noise1 = noise(n);
float noise2 = noise(n * 2.1) * 0.6;
float noise3 = noise(n * 5.4) * 0.42;
return noise1 + noise2 + noise3;
}
float illuminate(in vec2 uv) {
float t = time;
// Adjust x-coordinate based on time and y-value
float xOffset = uv.y < 0.5
? 23.0 + t * 0.035
: -11.0 + t * 0.03;
uv.x += xOffset;
// Shift y-coordinate to range [0, 0.5]
uv.y = abs(uv.y - 0.5);
// Scale x-coordinate
uv.x *= (10.0 + 80.0 * intensity * 0.2);
// Compute interferences
float q = interference(uv - t * 0.013) * 0.5;
vec2 r = vec2(interference(uv + q * 0.5 + t - uv.x - uv.y), interference(uv + q - t));
// Compute final shade value
float sh = (r.y + r.y) * max(0.0, uv.y) + 0.1;
return sh * sh * sh;
}
vec3 voidHalf(in float intensity) {
float minThreshold = 0.35;
// Alter gradient
intensity = pow(intensity, 0.75);
// Compute the gradient
vec3 color = colorScale(intensity);
// Normalize the color by the sum of m2 and the color values
color /= (1.0 + max(vec3(0), color));
return color;
}
vec3 voidRing(in vec2 uvs) {
vec2 uv = (uvs - 0.5) / (borderDistance * 1.06) + 0.5;
float r = 3.6;
float ff = 1.0 - uv.y;
vec2 uv2 = uv;
uv2.y = 1.0 - uv2.y;
// Calculate color for upper half
vec3 colorUpper = voidHalf(illuminate(radialProjection(uv, 1.0, r))) * ff;
// Calculate color for lower half
vec3 colorLower = voidHalf(illuminate(radialProjection(uv2, 1.9, r))) * (1.0 - ff);
// Return upper and lower half combined
return colorUpper + colorLower;
}
void main() {
${this.FRAGMENT_BEGIN}
float lumBase = perceivedBrightness(finalColor);
lumBase = mix(lumBase, lumBase * 0.33, darknessLevel);
vec3 voidRingColor = voidRing(vUvs);
float lum = pow(perceivedBrightness(voidRingColor), 4.0);
vec3 voidRingFinal = vec3(perceivedBrightness(voidRingColor)) * color;
finalColor = voidRingFinal * lumBase * colorationAlpha;
${this.FRAGMENT_END}
}`;
}

View File

@@ -0,0 +1,44 @@
/**
* Pulse animation illumination shader
*/
class PulseIlluminationShader extends AdaptiveIlluminationShader {
static fragmentShader = `
${this.SHADER_HEADER}
${this.PERCEIVED_BRIGHTNESS}
void main() {
${this.FRAGMENT_BEGIN}
float fading = pow(abs(1.0 - dist * dist), 1.01 - ratio);
${this.TRANSITION}
finalColor *= fading;
${this.FALLOFF}
${this.FRAGMENT_END}
}`;
}
/* -------------------------------------------- */
/**
* Pulse animation coloration shader
*/
class PulseColorationShader extends AdaptiveColorationShader {
static fragmentShader = `
${this.SHADER_HEADER}
${this.PERCEIVED_BRIGHTNESS}
float pfade(in float dist, in float pulse) {
return 1.0 - smoothstep(pulse * 0.5, 1.0, dist);
}
void main() {
${this.FRAGMENT_BEGIN}
finalColor = color * pfade(dist, pulse) * colorationAlpha;
${this.COLORATION_TECHNIQUES}
${this.ADJUSTMENTS}
${this.FALLOFF}
${this.FRAGMENT_END}
}`;
/** @inheritdoc */
static defaultUniforms = ({...super.defaultUniforms, pulse: 0});
}

View File

@@ -0,0 +1,30 @@
/**
* Radial rainbow animation coloration shader
*/
class RadialRainbowColorationShader extends AdaptiveColorationShader {
/** @override */
static forceDefaultColor = true;
/** @override */
static fragmentShader = `
${this.SHADER_HEADER}
${this.HSB2RGB}
${this.PERCEIVED_BRIGHTNESS}
void main() {
${this.FRAGMENT_BEGIN}
float intens = intensity * 0.1;
vec2 nuv = vUvs * 2.0 - 1.0;
vec2 puv = vec2(atan(nuv.x, nuv.y) * INVTWOPI + 0.5, length(nuv));
vec3 rainbow = hsb2rgb(vec3(puv.y - time * 0.2, 1.0, 1.0));
finalColor = mix(color, rainbow, smoothstep(0.0, 1.5 - intens, dist))
* (1.0 - dist * dist * dist);
${this.COLORATION_TECHNIQUES}
${this.ADJUSTMENTS}
${this.FALLOFF}
${this.FRAGMENT_END}
}`;
}

View File

@@ -0,0 +1,40 @@
/**
* Revolving animation coloration shader
*/
class RevolvingColorationShader extends AdaptiveColorationShader {
/** @override */
static forceDefaultColor = true;
/** @override */
static fragmentShader = `
${this.SHADER_HEADER}
uniform float gradientFade;
uniform float beamLength;
${this.PERCEIVED_BRIGHTNESS}
${this.PIE}
${this.ROTATION}
void main() {
${this.FRAGMENT_BEGIN}
vec2 ncoord = vUvs * 2.0 - 1.0;
float angularIntensity = mix(PI, PI * 0.5, intensity * 0.1);
ncoord *= rot(angle + time);
float angularCorrection = pie(ncoord, angularIntensity, gradientFade, beamLength);
finalColor = color * colorationAlpha * angularCorrection;
${this.COLORATION_TECHNIQUES}
${this.ADJUSTMENTS}
${this.FALLOFF}
${this.FRAGMENT_END}
}
`;
/** @inheritdoc */
static defaultUniforms = {
...super.defaultUniforms,
angle: 0,
gradientFade: 0.15,
beamLength: 1
};
}

View File

@@ -0,0 +1,64 @@
/**
* Roling mass illumination shader - intended primarily for darkness
*/
class RoilingDarknessShader extends AdaptiveDarknessShader {
static fragmentShader = `
${this.SHADER_HEADER}
${this.PERCEIVED_BRIGHTNESS}
${this.PRNG}
${this.NOISE}
${this.FBM(3)}
void main() {
${this.FRAGMENT_BEGIN}
// Creating distortion with vUvs and fbm
float distortion1 = fbm( vec2(
fbm( vUvs * 2.5 + time * 0.5),
fbm( (-vUvs - vec2(0.01)) * 5.0 + time * INVTHREE)));
float distortion2 = fbm( vec2(
fbm( -vUvs * 5.0 + time * 0.5),
fbm( (vUvs + vec2(0.01)) * 2.5 + time * INVTHREE)));
// Timed values
float t = -time * 0.5;
float cost = cos(t);
float sint = sin(t);
// Rotation matrix
mat2 rotmat = mat2(cost, -sint, sint, cost);
vec2 uv = vUvs;
// Applying rotation before distorting
uv -= vec2(0.5);
uv *= rotmat;
uv += vec2(0.5);
// Amplify distortions
vec2 dstpivot = vec2( sin(min(distortion1 * 0.1, distortion2 * 0.1)),
cos(min(distortion1 * 0.1, distortion2 * 0.1)) ) * INVTHREE
- vec2( cos(max(distortion1 * 0.1, distortion2 * 0.1)),
sin(max(distortion1 * 0.1, distortion2 * 0.1)) ) * INVTHREE ;
vec2 apivot = PIVOT - dstpivot;
uv -= apivot;
uv *= 1.13 + 1.33 * (cos(sqrt(max(distortion1, distortion2)) + 1.0) * 0.5);
uv += apivot;
// distorted distance
float ddist = clamp(distance(uv, PIVOT) * 2.0, 0.0, 1.0);
// R'lyeh Ftagnh !
float smooth = smoothstep(borderDistance, borderDistance * 1.2, ddist);
float inSmooth = min(smooth, 1.0 - smooth) * 2.0;
// Creating the spooky membrane around the bright area
vec3 membraneColor = vec3(1.0 - inSmooth);
finalColor *= (mix(color, color * 0.33, darknessLevel) * colorationAlpha);
finalColor = mix(finalColor,
vec3(0.0),
1.0 - smoothstep(0.25, 0.30 + (intensity * 0.2), ddist));
finalColor *= membraneColor;
${this.FRAGMENT_END}
}`;
}

View File

@@ -0,0 +1,74 @@
/**
* Siren light animation coloration shader
*/
class SirenColorationShader extends AdaptiveColorationShader {
static fragmentShader = `
${this.SHADER_HEADER}
uniform float gradientFade;
uniform float beamLength;
${this.PERCEIVED_BRIGHTNESS}
${this.PIE}
${this.ROTATION}
void main() {
${this.FRAGMENT_BEGIN}
vec2 ncoord = vUvs * 2.0 - 1.0;
float angularIntensity = mix(PI, 0.0, intensity * 0.1);
ncoord *= rot(time * 50.0 + angle);
float angularCorrection = pie(ncoord, angularIntensity, clamp(gradientFade * dist, 0.05, 1.0), beamLength);
finalColor = color * brightnessPulse * colorationAlpha * angularCorrection;
${this.COLORATION_TECHNIQUES}
${this.ADJUSTMENTS}
${this.FALLOFF}
${this.FRAGMENT_END}
}
`;
/** @inheritdoc */
static defaultUniforms = ({
...super.defaultUniforms,
ratio: 0,
brightnessPulse: 1,
angle: 0,
gradientFade: 0.15,
beamLength: 1
});
}
/* -------------------------------------------- */
/**
* Siren light animation illumination shader
*/
class SirenIlluminationShader extends AdaptiveIlluminationShader {
static fragmentShader = `
${this.SHADER_HEADER}
uniform float gradientFade;
uniform float beamLength;
${this.PERCEIVED_BRIGHTNESS}
${this.PIE}
${this.ROTATION}
void main() {
${this.FRAGMENT_BEGIN}
${this.TRANSITION}
vec2 ncoord = vUvs * 2.0 - 1.0;
float angularIntensity = mix(PI, 0.0, intensity * 0.1);
ncoord *= rot(time * 50.0 + angle);
float angularCorrection = mix(1.0, pie(ncoord, angularIntensity, clamp(gradientFade * dist, 0.05, 1.0), beamLength), 0.5);
finalColor *= angularCorrection;
${this.ADJUSTMENTS}
${this.FALLOFF}
${this.FRAGMENT_END}
}`;
/** @inheritdoc */
static defaultUniforms = ({
...super.defaultUniforms,
angle: 0,
gradientFade: 0.45,
beamLength: 1
});
}

View File

@@ -0,0 +1,91 @@
/**
* A patch of smoke
*/
class SmokePatchColorationShader extends AdaptiveColorationShader {
static fragmentShader = `
${this.SHADER_HEADER}
${this.PERCEIVED_BRIGHTNESS}
${this.PRNG}
${this.NOISE}
${this.FBMHQ(3)}
vec2 transform(in vec2 uv, in float dist) {
float t = time * 0.1;
float cost = cos(t);
float sint = sin(t);
mat2 rotmat = mat2(cost, -sint, sint, cost);
mat2 scalemat = mat2(10.0, uv.x, uv.y, 10.0);
uv -= PIVOT;
uv *= (rotmat * scalemat);
uv += PIVOT;
return uv;
}
float smokefading(in float dist) {
float t = time * 0.4;
vec2 uv = transform(vUvs, dist);
return pow(1.0 - dist,
mix(fbm(uv, 1.0 + intensity * 0.4),
max(fbm(uv + t, 1.0),
fbm(uv - t, 1.0)),
pow(dist, intensity * 0.5)));
}
void main() {
${this.FRAGMENT_BEGIN}
finalColor = color * smokefading(dist) * colorationAlpha;
${this.COLORATION_TECHNIQUES}
${this.ADJUSTMENTS}
${this.FALLOFF}
${this.FRAGMENT_END}
}
`;
}
/* -------------------------------------------- */
/**
* A patch of smoke
*/
class SmokePatchIlluminationShader extends AdaptiveIlluminationShader {
static fragmentShader = `
${this.SHADER_HEADER}
${this.PERCEIVED_BRIGHTNESS}
${this.PRNG}
${this.NOISE}
${this.FBMHQ(3)}
vec2 transform(in vec2 uv, in float dist) {
float t = time * 0.1;
float cost = cos(t);
float sint = sin(t);
mat2 rotmat = mat2(cost, -sint, sint, cost);
mat2 scalemat = mat2(10.0, uv.x, uv.y, 10.0);
uv -= PIVOT;
uv *= (rotmat * scalemat);
uv += PIVOT;
return uv;
}
float smokefading(in float dist) {
float t = time * 0.4;
vec2 uv = transform(vUvs, dist);
return pow(1.0 - dist,
mix(fbm(uv, 1.0 + intensity * 0.4),
max(fbm(uv + t, 1.0),
fbm(uv - t, 1.0)),
pow(dist, intensity * 0.5)));
}
void main() {
${this.FRAGMENT_BEGIN}
${this.TRANSITION}
finalColor *= smokefading(dist);
${this.ADJUSTMENTS}
${this.FALLOFF}
${this.FRAGMENT_END}
}
`;
}

View File

@@ -0,0 +1,49 @@
/**
* A disco like star light.
*/
class StarLightColorationShader extends AdaptiveColorationShader {
/** @override */
static forceDefaultColor = true;
/** @override */
static fragmentShader = `
${this.SHADER_HEADER}
${this.PERCEIVED_BRIGHTNESS}
${this.PRNG}
${this.NOISE}
${this.FBM(2, 1.0)}
vec2 transform(in vec2 uv, in float dist) {
float t = time * 0.20;
float cost = cos(t);
float sint = sin(t);
mat2 rotmat = mat2(cost, -sint, sint, cost);
uv *= rotmat;
return uv;
}
float makerays(in vec2 uv, in float t) {
vec2 uvn = normalize(uv * (uv + t)) * (5.0 + intensity);
return max(clamp(0.5 * tan(fbm(uvn - t)), 0.0, 2.25),
clamp(3.0 - tan(fbm(uvn + t * 2.0)), 0.0, 2.25));
}
float starlight(in float dist) {
vec2 uv = (vUvs - 0.5);
uv = transform(uv, dist);
float rays = makerays(uv, time * 0.5);
return pow(1.0 - dist, rays) * pow(1.0 - dist, 0.25);
}
void main() {
${this.FRAGMENT_BEGIN}
finalColor = clamp(color * starlight(dist) * colorationAlpha, 0.0, 1.0);
${this.COLORATION_TECHNIQUES}
${this.ADJUSTMENTS}
${this.FALLOFF}
${this.FRAGMENT_END}
}
`;
}

View File

@@ -0,0 +1,87 @@
/**
* Sunburst animation illumination shader
*/
class SunburstIlluminationShader extends AdaptiveIlluminationShader {
static fragmentShader = `
${this.SHADER_HEADER}
${this.PERCEIVED_BRIGHTNESS}
// Smooth back and forth between a and b
float cosTime(in float a, in float b) {
return (a - b) * ((cos(time) + 1.0) * 0.5) + b;
}
// Create the sunburst effect
vec3 sunBurst(in vec3 color, in vec2 uv, in float dist) {
// Pulse calibration
float intensityMod = 1.0 + (intensity * 0.05);
float lpulse = cosTime(1.3 * intensityMod, 0.85 * intensityMod);
// Compute angle
float angle = atan(uv.x, uv.y) * INVTWOPI;
// Creating the beams and the inner light
float beam = fract(angle * 16.0 + time);
float light = lpulse * pow(abs(1.0 - dist), 0.65);
// Max agregation of the central light and the two gradient edges
float sunburst = max(light, max(beam, 1.0 - beam));
// Creating the effect : applying color and color correction. ultra saturate the entire output color.
return color * pow(sunburst, 3.0);
}
void main() {
${this.FRAGMENT_BEGIN}
vec2 uv = (2.0 * vUvs) - 1.0;
finalColor = switchColor(computedBrightColor, computedDimColor, dist);
${this.ADJUSTMENTS}
finalColor = sunBurst(finalColor, uv, dist);
${this.FALLOFF}
${this.FRAGMENT_END}
}`;
}
/**
* Sunburst animation coloration shader
*/
class SunburstColorationShader extends AdaptiveColorationShader {
static fragmentShader = `
${this.SHADER_HEADER}
${this.PERCEIVED_BRIGHTNESS}
// Smooth back and forth between a and b
float cosTime(in float a, in float b) {
return (a - b) * ((cos(time) + 1.0) * 0.5) + b;
}
// Create a sun burst effect
vec3 sunBurst(in vec2 uv, in float dist) {
// pulse calibration
float intensityMod = 1.0 + (intensity * 0.05);
float lpulse = cosTime(1.1 * intensityMod, 0.85 * intensityMod);
// compute angle
float angle = atan(uv.x, uv.y) * INVTWOPI;
// creating the beams and the inner light
float beam = fract(angle * 16.0 + time);
float light = lpulse * pow(abs(1.0 - dist), 0.65);
// agregation of the central light and the two gradient edges to create the sunburst
float sunburst = max(light, max(beam, 1.0 - beam));
// creating the effect : applying color and color correction. saturate the entire output color.
return color * pow(sunburst, 3.0);
}
void main() {
${this.FRAGMENT_BEGIN}
vec2 uvs = (2.0 * vUvs) - 1.0;
finalColor = sunBurst(uvs, dist) * colorationAlpha;
${this.COLORATION_TECHNIQUES}
${this.ADJUSTMENTS}
${this.FALLOFF}
${this.FRAGMENT_END}
}`;
}

View File

@@ -0,0 +1,29 @@
/**
* Swirling rainbow animation coloration shader
*/
class SwirlingRainbowColorationShader extends AdaptiveColorationShader {
/** @override */
static forceDefaultColor = true;
/** @override */
static fragmentShader = `
${this.SHADER_HEADER}
${this.HSB2RGB}
${this.PERCEIVED_BRIGHTNESS}
void main() {
${this.FRAGMENT_BEGIN}
float intens = intensity * 0.1;
vec2 nuv = vUvs * 2.0 - 1.0;
vec2 puv = vec2(atan(nuv.x, nuv.y) * INVTWOPI + 0.5, length(nuv));
vec3 rainbow = hsb2rgb(vec3(puv.x + puv.y - time * 0.2, 1.0, 1.0));
finalColor = mix(color, rainbow, smoothstep(0.0, 1.5 - intens, dist))
* (1.0 - dist * dist * dist);
${this.COLORATION_TECHNIQUES}
${this.ADJUSTMENTS}
${this.FALLOFF}
${this.FRAGMENT_END}
}`;
}

View File

@@ -0,0 +1,40 @@
/**
* Allow coloring of illumination
*/
class TorchIlluminationShader extends AdaptiveIlluminationShader {
static fragmentShader = `
${this.SHADER_HEADER}
${this.PERCEIVED_BRIGHTNESS}
void main() {
${this.FRAGMENT_BEGIN}
${this.TRANSITION}
${this.ADJUSTMENTS}
${this.FALLOFF}
${this.FRAGMENT_END}
}`;
}
/* -------------------------------------------- */
/**
* Torch animation coloration shader
*/
class TorchColorationShader extends AdaptiveColorationShader {
static fragmentShader = `
${this.SHADER_HEADER}
${this.PERCEIVED_BRIGHTNESS}
void main() {
${this.FRAGMENT_BEGIN}
finalColor = color * brightnessPulse * colorationAlpha;
${this.COLORATION_TECHNIQUES}
${this.ADJUSTMENTS}
${this.FALLOFF}
${this.FRAGMENT_END}
}
`;
/** @inheritdoc */
static defaultUniforms = ({...super.defaultUniforms, ratio: 0, brightnessPulse: 1});
}

View File

@@ -0,0 +1,154 @@
/**
* Vortex animation coloration shader
*/
class VortexColorationShader extends AdaptiveColorationShader {
/** @override */
static forceDefaultColor = true;
/** @override */
static fragmentShader = `
${this.SHADER_HEADER}
${this.PRNG}
${this.NOISE}
${this.FBM(4, 1.0)}
${this.PERCEIVED_BRIGHTNESS}
vec2 vortex(in vec2 uv, in float dist, in float radius, in mat2 rotmat) {
float intens = intensity * 0.2;
vec2 uvs = uv - PIVOT;
uv *= rotmat;
if ( dist < radius ) {
float sigma = (radius - dist) / radius;
float theta = sigma * sigma * TWOPI * intens;
float st = sin(theta);
float ct = cos(theta);
uvs = vec2(dot(uvs, vec2(ct, -st)), dot(uvs, vec2(st, ct)));
}
uvs += PIVOT;
return uvs;
}
vec3 spice(in vec2 iuv, in mat2 rotmat) {
// constructing the palette
vec3 c1 = color * 0.55;
vec3 c2 = color * 0.95;
vec3 c3 = color * 0.45;
vec3 c4 = color * 0.75;
vec3 c5 = vec3(0.20);
vec3 c6 = color * 1.2;
// creating the deformation
vec2 uv = iuv;
uv -= PIVOT;
uv *= rotmat;
vec2 p = uv.xy * 6.0;
uv += PIVOT;
// time motion fbm and palette mixing
float q = fbm(p + time);
vec2 r = vec2(fbm(p + q + time * 0.9 - p.x - p.y),
fbm(p + q + time * 0.6));
vec3 c = mix(c1,
c2,
fbm(p + r)) + mix(c3, c4, r.x)
- mix(c5, c6, r.y);
// returning the color
return c;
}
void main() {
${this.FRAGMENT_BEGIN}
// Timed values
float t = time * 0.5;
float cost = cos(t);
float sint = sin(t);
// Rotation matrix
mat2 vortexRotMat = mat2(cost, -sint, sint, cost);
mat2 spiceRotMat = mat2(cost * 2.0, -sint * 2.0, sint * 2.0, cost * 2.0);
// Creating vortex
vec2 vuv = vortex(vUvs, dist, 1.0, vortexRotMat);
// Applying spice
finalColor = spice(vuv, spiceRotMat) * colorationAlpha;
${this.COLORATION_TECHNIQUES}
${this.ADJUSTMENTS}
${this.FALLOFF}
${this.FRAGMENT_END}
}`;
}
/* -------------------------------------------- */
/**
* Vortex animation coloration shader
*/
class VortexIlluminationShader extends AdaptiveIlluminationShader {
static fragmentShader = `
${this.SHADER_HEADER}
${this.PRNG}
${this.NOISE}
${this.FBM(4, 1.0)}
${this.PERCEIVED_BRIGHTNESS}
vec2 vortex(in vec2 uv, in float dist, in float radius, in float angle, in mat2 rotmat) {
vec2 uvs = uv - PIVOT;
uv *= rotmat;
if ( dist < radius ) {
float sigma = (radius - dist) / radius;
float theta = sigma * sigma * angle;
float st = sin(theta);
float ct = cos(theta);
uvs = vec2(dot(uvs, vec2(ct, -st)), dot(uvs, vec2(st, ct)));
}
uvs += PIVOT;
return uvs;
}
vec3 spice(in vec2 iuv, in mat2 rotmat) {
// constructing the palette
vec3 c1 = vec3(0.20);
vec3 c2 = vec3(0.80);
vec3 c3 = vec3(0.15);
vec3 c4 = vec3(0.85);
vec3 c5 = c3;
vec3 c6 = vec3(0.9);
// creating the deformation
vec2 uv = iuv;
uv -= PIVOT;
uv *= rotmat;
vec2 p = uv.xy * 6.0;
uv += PIVOT;
// time motion fbm and palette mixing
float q = fbm(p + time);
vec2 r = vec2(fbm(p + q + time * 0.9 - p.x - p.y), fbm(p + q + time * 0.6));
// Mix the final color
return mix(c1, c2, fbm(p + r)) + mix(c3, c4, r.x) - mix(c5, c6, r.y);
}
vec3 convertToDarknessColors(in vec3 col, in float dist) {
float intens = intensity * 0.20;
float lum = (col.r * 2.0 + col.g * 3.0 + col.b) * 0.5 * INVTHREE;
float colorMod = smoothstep(ratio * 0.99, ratio * 1.01, dist);
return mix(computedDimColor, computedBrightColor * colorMod, 1.0 - smoothstep( 0.80, 1.00, lum)) *
smoothstep( 0.25 * intens, 0.85 * intens, lum);
}
void main() {
${this.FRAGMENT_BEGIN}
${this.TRANSITION}
${this.ADJUSTMENTS}
${this.FALLOFF}
${this.FRAGMENT_END}
}`;
}

View File

@@ -0,0 +1,47 @@
/**
* Wave animation illumination shader
*/
class WaveIlluminationShader extends AdaptiveIlluminationShader {
static fragmentShader = `
${this.SHADER_HEADER}
${this.PERCEIVED_BRIGHTNESS}
float wave(in float dist) {
float sinWave = 0.5 * (sin(-time * 6.0 + dist * 10.0 * intensity) + 1.0);
return 0.3 * sinWave + 0.8;
}
void main() {
${this.FRAGMENT_BEGIN}
${this.TRANSITION}
finalColor *= wave(dist);
${this.ADJUSTMENTS}
${this.FALLOFF}
${this.FRAGMENT_END}
}`;
}
/* -------------------------------------------- */
/**
* Wave animation coloration shader
*/
class WaveColorationShader extends AdaptiveColorationShader {
static fragmentShader = `
${this.SHADER_HEADER}
${this.PERCEIVED_BRIGHTNESS}
float wave(in float dist) {
float sinWave = 0.5 * (sin(-time * 6.0 + dist * 10.0 * intensity) + 1.0);
return 0.55 * sinWave + 0.8;
}
void main() {
${this.FRAGMENT_BEGIN}
finalColor = color * wave(dist) * colorationAlpha;
${this.COLORATION_TECHNIQUES}
${this.ADJUSTMENTS}
${this.FALLOFF}
${this.FRAGMENT_END}
}`;
}

View File

@@ -0,0 +1,129 @@
/**
* The default coloration shader used by standard rendering and animations.
* A fragment shader which creates a solid light source.
*/
class AdaptiveIlluminationShader extends AdaptiveLightingShader {
/** @inheritdoc */
static FRAGMENT_BEGIN = `
${super.FRAGMENT_BEGIN}
vec3 framebufferColor = min(texture2D(framebufferTexture, vSamplerUvs).rgb, computedBackgroundColor);
`;
/** @override */
static FRAGMENT_END = `
gl_FragColor = vec4(mix(framebufferColor, finalColor, depth), 1.0);
`;
/**
* The adjustments made into fragment shaders
* @type {string}
*/
static get ADJUSTMENTS() {
return `
vec3 changedColor = finalColor;\n
${this.SATURATION}
${this.EXPOSURE}
${this.SHADOW}
finalColor = changedColor;\n`;
}
static EXPOSURE = `
// Computing exposure with illumination
if ( exposure > 0.0 ) {
// Diminishing exposure for illumination by a factor 2 (to reduce the "inflating radius" visual problem)
float quartExposure = exposure * 0.25;
float attenuationStrength = attenuation * 0.25;
float lowerEdge = 0.98 - attenuationStrength;
float upperEdge = 1.02 + attenuationStrength;
float finalExposure = quartExposure *
(1.0 - smoothstep(ratio * lowerEdge, clamp(ratio * upperEdge, 0.0001, 1.0), dist)) +
quartExposure;
changedColor *= (1.0 + finalExposure);
}
else if ( exposure != 0.0 ) changedColor *= (1.0 + exposure);
`;
/**
* Memory allocations for the Adaptive Illumination Shader
* @type {string}
*/
static SHADER_HEADER = `
${this.FRAGMENT_UNIFORMS}
${this.VERTEX_FRAGMENT_VARYINGS}
${this.FRAGMENT_FUNCTIONS}
${this.CONSTANTS}
${this.SWITCH_COLOR}
`;
/** @inheritdoc */
static fragmentShader = `
${this.SHADER_HEADER}
${this.PERCEIVED_BRIGHTNESS}
void main() {
${this.FRAGMENT_BEGIN}
${this.TRANSITION}
${this.ADJUSTMENTS}
${this.FALLOFF}
${this.FRAGMENT_END}
}`;
/** @inheritdoc */
static defaultUniforms = {
technique: 1,
shadows: 0,
saturation: 0,
intensity: 5,
attenuation: 0.5,
contrast: 0,
exposure: 0,
ratio: 0.5,
darknessLevel: 0,
color: [1, 1, 1],
colorBackground: [1, 1, 1],
colorDim: [1, 1, 1],
colorBright: [1, 1, 1],
screenDimensions: [1, 1],
time: 0,
useSampler: false,
primaryTexture: null,
framebufferTexture: null,
depthTexture: null,
darknessLevelTexture: null,
depthElevation: 1,
ambientBrightest: [1, 1, 1],
ambientDarkness: [0, 0, 0],
ambientDaylight: [1, 1, 1],
weights: [0, 0, 0, 0],
dimLevelCorrection: 1,
brightLevelCorrection: 2,
computeIllumination: false,
globalLight: false,
globalLightThresholds: [0, 0]
};
static {
const initial = foundry.data.LightData.cleanData();
this.defaultUniforms.technique = initial.coloration;
this.defaultUniforms.contrast = initial.contrast;
this.defaultUniforms.shadows = initial.shadows;
this.defaultUniforms.saturation = initial.saturation;
this.defaultUniforms.intensity = initial.animation.intensity;
this.defaultUniforms.attenuation = initial.attenuation;
}
/**
* Flag whether the illumination shader is currently required.
* @type {boolean}
*/
get isRequired() {
const vs = canvas.visibility.lightingVisibility;
// Checking if disabled
if ( vs.illumination === VisionMode.LIGHTING_VISIBILITY.DISABLED ) return false;
// For the moment, we return everytimes true if we are here
return true;
}
}