Initial
This commit is contained in:
@@ -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]);
|
||||
}
|
||||
}
|
||||
@@ -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;`
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -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]);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
107
resources/app/client/pixi/webgl/shaders/vision/effects/wave.js
Normal file
107
resources/app/client/pixi/webgl/shaders/vision/effects/wave.js
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -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]
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user