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 background shader used for vision sources
*/
class BackgroundVisionShader extends AdaptiveVisionShader {
/** @inheritdoc */
static FRAGMENT_END = `
finalColor *= colorTint;
if ( linkedToDarknessLevel ) finalColor = mix(baseColor.rgb, finalColor, computedDarknessLevel);
${super.FRAGMENT_END}
`;
/**
* Adjust the intensity according to the difference between the pixel darkness level and the scene darkness level.
* Used to see the difference of intensity when computing the background shader which is completeley overlapping
* The surface texture.
* @type {string}
*/
static ADJUST_INTENSITY = `
float darknessLevelDifference = clamp(computedDarknessLevel - darknessLevel, 0.0, 1.0);
finalColor = mix(finalColor, finalColor * 0.5, darknessLevelDifference);
`;
/** @inheritdoc */
static ADJUSTMENTS = `
${this.ADJUST_INTENSITY}
${super.ADJUSTMENTS}
`;
/**
* 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}
${this.ADJUSTMENTS}
${this.BACKGROUND_TECHNIQUES}
${this.FALLOFF}
${this.FRAGMENT_END}
}`;
/** @inheritdoc */
static defaultUniforms = {
technique: 0,
saturation: 0,
contrast: 0,
attenuation: 0.10,
exposure: 0,
darknessLevel: 0,
colorVision: [1, 1, 1],
colorTint: [1, 1, 1],
colorBackground: [1, 1, 1],
screenDimensions: [1, 1],
time: 0,
useSampler: true,
linkedToDarknessLevel: 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,
globalLight: false,
globalLightThresholds: [0, 0]
};
/**
* Flag whether the background shader is currently required.
* If key uniforms are at their default values, we don't need to render the background container.
* @type {boolean}
*/
get isRequired() {
const keys = ["contrast", "saturation", "colorTint", "colorVision"];
return keys.some(k => this.uniforms[k] !== this.constructor.defaultUniforms[k]);
}
}

View File

@@ -0,0 +1,66 @@
/**
* This class defines an interface which all adaptive vision shaders extend.
*/
class AdaptiveVisionShader extends AdaptiveLightingShader {
/** @inheritDoc */
static FRAGMENT_FUNCTIONS = `
${super.FRAGMENT_FUNCTIONS}
vec3 computedVisionColor;
`;
/* -------------------------------------------- */
/** @override */
static EXPOSURE = `
// Computing exposed color for background
if ( exposure != 0.0 ) {
changedColor *= (1.0 + exposure);
}`;
/* -------------------------------------------- */
/** @inheritDoc */
static COMPUTE_ILLUMINATION = `
${super.COMPUTE_ILLUMINATION}
if ( computeIllumination ) computedVisionColor = mix(computedDimColor, computedBrightColor, brightness);
else computedVisionColor = colorVision;
`;
/* -------------------------------------------- */
// FIXME: need to redeclare fragment begin here to take into account COMPUTE_ILLUMINATION
// Do not work without this redeclaration.
/** @override */
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;
`;
/* -------------------------------------------- */
/** @override */
static SHADOW = "";
/* -------------------------------------------- */
/* Shader Techniques for vision */
/* -------------------------------------------- */
/**
* A mapping of available shader techniques
* @type {Record<string, ShaderTechnique>}
*/
static SHADER_TECHNIQUES = {
LEGACY: {
id: 0,
label: "LIGHT.AdaptiveLuminance",
coloration: `
float reflection = perceivedBrightness(baseColor);
finalColor *= reflection;`
}
};
}

View File

@@ -0,0 +1,71 @@
/**
* The default coloration shader used for vision sources.
*/
class ColorationVisionShader extends AdaptiveVisionShader {
/** @override */
static EXPOSURE = "";
/** @override */
static CONTRAST = "";
/**
* Memory allocations for the Adaptive Coloration 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 = colorEffect;
${this.COLORATION_TECHNIQUES}
${this.ADJUSTMENTS}
${this.FALLOFF}
${this.FRAGMENT_END}
}`;
/** @inheritdoc */
static defaultUniforms = {
technique: 0,
saturation: 0,
attenuation: 0,
colorEffect: [0, 0, 0],
colorBackground: [0, 0, 0],
colorTint: [1, 1, 1],
time: 0,
screenDimensions: [1, 1],
useSampler: true,
primaryTexture: null,
linkedToDarknessLevel: true,
depthTexture: null,
depthElevation: 1,
ambientBrightest: [1, 1, 1],
ambientDarkness: [0, 0, 0],
ambientDaylight: [1, 1, 1],
weights: [0, 0, 0, 0],
dimLevelCorrection: 1,
brightLevelCorrection: 2,
globalLight: false,
globalLightThresholds: [0, 0]
};
/**
* Flag whether the coloration shader is currently required.
* If key uniforms are at their default values, we don't need to render the coloration container.
* @type {boolean}
*/
get isRequired() {
const keys = ["saturation", "colorEffect"];
return keys.some(k => this.uniforms[k] !== this.constructor.defaultUniforms[k]);
}
}

View File

@@ -0,0 +1,29 @@
/**
* Shader specialized in light amplification
*/
class AmplificationBackgroundVisionShader extends BackgroundVisionShader {
/** @inheritdoc */
static fragmentShader = `
${this.SHADER_HEADER}
${this.PERCEIVED_BRIGHTNESS}
void main() {
${this.FRAGMENT_BEGIN}
float lum = perceivedBrightness(baseColor.rgb);
vec3 vision = vec3(smoothstep(0.0, 1.0, lum * 1.5)) * colorTint;
finalColor = vision + (vision * (lum + brightness) * 0.1) + (baseColor.rgb * (1.0 - computedDarknessLevel) * 0.125);
${this.ADJUSTMENTS}
${this.BACKGROUND_TECHNIQUES}
${this.FALLOFF}
${this.FRAGMENT_END}
}`;
/** @inheritdoc */
static defaultUniforms = ({...super.defaultUniforms, colorTint: [0.38, 0.8, 0.38], brightness: 0.5});
/** @inheritdoc */
get isRequired() {
return true;
}
}

View File

@@ -0,0 +1,107 @@
/**
* Shader specialized in wave like senses (tremorsenses)
*/
class WaveBackgroundVisionShader extends BackgroundVisionShader {
/** @inheritdoc */
static fragmentShader = `
${this.SHADER_HEADER}
${this.WAVE()}
${this.PERCEIVED_BRIGHTNESS}
void main() {
${this.FRAGMENT_BEGIN}
// Normalize vUvs and compute base time
vec2 uvs = (2.0 * vUvs) - 1.0;
float t = time * -8.0;
// Rotate uvs
float sinX = sin(t * 0.02);
float cosX = cos(t * 0.02);
mat2 rotationMatrix = mat2( cosX, -sinX, sinX, cosX);
vec2 ruv = ((vUvs - 0.5) * rotationMatrix) + 0.5;
// Produce 4 arms smoothed to the edges
float angle = atan(ruv.x * 2.0 - 1.0, ruv.y * 2.0 - 1.0) * INVTWOPI;
float beam = fract(angle * 4.0);
beam = smoothstep(0.3, 1.0, max(beam, 1.0 - beam));
// Construct final color
vec3 grey = vec3(perceivedBrightness(baseColor.rgb));
finalColor = mix(baseColor.rgb, grey * 0.5, sqrt(beam)) * mix(vec3(1.0), colorTint, 0.3);
${this.ADJUSTMENTS}
${this.BACKGROUND_TECHNIQUES}
${this.FALLOFF}
${this.FRAGMENT_END}
}`;
/** @inheritdoc */
static defaultUniforms = ({...super.defaultUniforms, colorTint: [0.8, 0.1, 0.8]});
/** @inheritdoc */
get isRequired() {
return true;
}
}
/* -------------------------------------------- */
/**
* The wave vision shader, used to create waves emanations (ex: tremorsense)
*/
class WaveColorationVisionShader extends ColorationVisionShader {
/** @inheritdoc */
static fragmentShader = `
${this.SHADER_HEADER}
${this.WAVE()}
${this.PERCEIVED_BRIGHTNESS}
void main() {
${this.FRAGMENT_BEGIN}
// Normalize vUvs and compute base time
vec2 uvs = (2.0 * vUvs) - 1.0;
float t = time * -8.0;
// Rotate uvs
float sinX = sin(t * 0.02);
float cosX = cos(t * 0.02);
mat2 rotationMatrix = mat2( cosX, -sinX, sinX, cosX);
vec2 ruv = ((vUvs - 0.5) * rotationMatrix) + 0.5;
// Prepare distance from 4 corners
float dst[4];
dst[0] = distance(vec2(0.0), ruv);
dst[1] = distance(vec2(1.0), ruv);
dst[2] = distance(vec2(1.0,0.0), ruv);
dst[3] = distance(vec2(0.0,1.0), ruv);
// Produce 4 arms smoothed to the edges
float angle = atan(ruv.x * 2.0 - 1.0, ruv.y * 2.0 - 1.0) * INVTWOPI;
float beam = fract(angle * 4.0);
beam = smoothstep(0.3, 1.0, max(beam, 1.0 - beam));
// Computing the 4 corner waves
float multiWaves = 0.0;
for ( int i = 0; i <= 3 ; i++) {
multiWaves += smoothstep(0.6, 1.0, max(multiWaves, wcos(-10.0, 1.30 - dst[i], dst[i] * 120.0, t)));
}
// Computing the central wave
multiWaves += smoothstep(0.6, 1.0, max(multiWaves, wcos(-10.0, 1.35 - dist, dist * 120.0, -t)));
// Construct final color
finalColor = vec3(mix(multiWaves, 0.0, sqrt(beam))) * colorEffect;
${this.COLORATION_TECHNIQUES}
${this.ADJUSTMENTS}
${this.FALLOFF}
${this.FRAGMENT_END}
}`;
/** @inheritdoc */
static defaultUniforms = ({...super.defaultUniforms, colorEffect: [0.8, 0.1, 0.8]});
/** @inheritdoc */
get isRequired() {
return true;
}
}

View File

@@ -0,0 +1,89 @@
/**
* The default illumination shader used for vision sources
*/
class IlluminationVisionShader extends AdaptiveVisionShader {
/** @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);
`;
/**
* Transition between bright and dim colors, if requested
* @type {string}
*/
static VISION_COLOR = `
finalColor = computedVisionColor;
`;
/**
* The adjustments made into fragment shaders
* @type {string}
*/
static get ADJUSTMENTS() {
return `
vec3 changedColor = finalColor;\n
${this.SATURATION}
finalColor = changedColor;\n`;
}
/**
* Memory allocations for the Adaptive Illumination 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}
${this.VISION_COLOR}
${this.ILLUMINATION_TECHNIQUES}
${this.ADJUSTMENTS}
${this.FALLOFF}
${this.FRAGMENT_END}
}`;
/** @inheritdoc */
static defaultUniforms = {
technique: foundry.data.LightData.cleanData().initial,
attenuation: 0,
exposure: 0,
saturation: 0,
darknessLevel: 0,
colorVision: [1, 1, 1],
colorTint: [1, 1, 1],
colorBackground: [1, 1, 1],
screenDimensions: [1, 1],
time: 0,
useSampler: false,
linkedToDarknessLevel: true,
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,
globalLight: false,
globalLightThresholds: [0, 0]
};
}