@lightningjs/renderer
Version:
Lightning 3 Renderer
149 lines (137 loc) • 3.84 kB
text/typescript
import {
ShaderEffect,
type DefaultEffectProps,
type ShaderEffectUniforms,
} from './ShaderEffect.js';
export interface GlitchEffectProps extends DefaultEffectProps {
/**
* Amplitude determines the intensity of the horizontal shift that happens in the glitch effect.
*
* @default 0.2
*/
amplitude?: number;
/**
* Narrowness of the horizontal shift
*
* @default 4.0
*/
narrowness?: number;
/**
* Blockiness of the horizontal shift
*
* @default 2.0
*/
blockiness?: number;
/**
* Minimzer of the horizontal shift
*
* @default 8.0
*/
minimizer?: number;
/**
* Used for the time loop of the horizontal shift
*
* @default Date.now()
*/
time?: number;
}
/**
* Renders a Glitch effect using the incoming texture
*/
export class GlitchEffect extends ShaderEffect {
static z$__type__Props: GlitchEffectProps;
override readonly name = 'glitch';
static override getEffectKey(props: GlitchEffectProps): string {
return `glitch`;
}
static override resolveDefaults(
props: GlitchEffectProps,
): Required<GlitchEffectProps> {
return {
amplitude: props.amplitude ?? 0.2,
narrowness: props.narrowness ?? 4.0,
blockiness: props.blockiness ?? 2.0,
minimizer: props.minimizer ?? 8.0,
time: props.time ?? Date.now(),
};
}
static override uniforms: ShaderEffectUniforms = {
amplitude: {
value: 0,
method: 'uniform1f',
type: 'float',
},
narrowness: {
value: 0,
method: 'uniform1f',
type: 'float',
},
blockiness: {
value: 0,
method: 'uniform1f',
type: 'float',
},
minimizer: {
value: 0,
method: 'uniform1f',
type: 'float',
},
time: {
value: 0,
method: 'uniform1f',
updateOnBind: true,
updateProgramValue: (values) => {
const value = (values.value =
(Date.now() - (values.value as number)) % 1000);
values.programValue = value;
},
type: 'float',
},
};
static override methods: Record<string, string> = {
rand: `
float function(vec2 p, float time) {
float t = floor(time * 20.) / 10.;
return fract(sin(dot(p, vec2(t * 12.9898, t * 78.233))) * 43758.5453);
}
`,
noise: `
float function(vec2 uv, float blockiness, float time) {
vec2 lv = fract(uv);
vec2 id = floor(uv);
float n1 = rand(id, time);
float n2 = rand(id+vec2(1,0), time);
float n3 = rand(id+vec2(0,1), time);
float n4 = rand(id+vec2(1,1), time);
vec2 u = smoothstep(0.0, 1.0 + blockiness, lv);
return mix(mix(n1, n2, u.x), mix(n3, n4, u.x), u.y);
}
`,
fbm: `
float function(vec2 uv, int count, float blockiness, float complexity, float time) {
float val = 0.0;
float amp = 0.5;
const int MAX_ITERATIONS = 10;
for(int i = 0; i < MAX_ITERATIONS; i++) {
if(i >= count) {break;}
val += amp * noise(uv, blockiness, time);
amp *= 0.5;
uv *= complexity;
}
return val;
}
`,
};
static override onColorize = `
vec2 uv = v_textureCoordinate.xy;
float aspect = u_dimensions.x / u_dimensions.y;
vec2 a = vec2(uv.x * aspect , uv.y);
vec2 uv2 = vec2(a.x / u_dimensions.x, exp(a.y));
float shift = amplitude * pow($fbm(uv2, 4, blockiness, narrowness, time), minimizer);
float colR = texture2D(u_texture, vec2(uv.x + shift, uv.y)).r * (1. - shift);
float colG = texture2D(u_texture, vec2(uv.x - shift, uv.y)).g * (1. - shift);
float colB = texture2D(u_texture, vec2(uv.x - shift, uv.y)).b * (1. - shift);
vec3 f = vec3(colR, colG, colB);
return vec4(f, texture2D(u_texture, vec2(uv.x - shift, uv.y)).a);
`;
}