diff --git a/filters/glitch/src/GlitchFilter.ts b/filters/glitch/src/GlitchFilter.ts index adca1ddc0..387236c91 100644 --- a/filters/glitch/src/GlitchFilter.ts +++ b/filters/glitch/src/GlitchFilter.ts @@ -78,7 +78,7 @@ export class GlitchFilter extends Filter public uniforms: { uSeed: number - uDimensions: PointData, + uDimensions: Float32Array, uAspect: number, uFillMode: number, uOffset: number, @@ -139,6 +139,13 @@ export class GlitchFilter extends Filter name: 'glitch-filter', }); + const canvas = document.createElement('canvas'); + + canvas.width = 4; + canvas.height = options.sampleSize ?? 512; + + const texture = getCanvasTexture(canvas, { style: { scaleMode: 'nearest' } }); + super({ gpuProgram, glProgram, @@ -147,23 +154,22 @@ export class GlitchFilter extends Filter uSeed: { value: options?.seed ?? 0, type: 'f32' }, uDimensions: { value: new Float32Array(2), type: 'vec2' }, uAspect: { value: 1, type: 'f32' }, - uFillMode: { value: options?.fillMode ?? 0, type: 'i32' }, + uFillMode: { value: options?.fillMode ?? 0, type: 'f32' }, uOffset: { value: options?.offset ?? 100, type: 'f32' }, uDirection: { value: options?.direction ?? 0, type: 'f32' }, - uRed: { value: new Float32Array(2), type: 'vec2' }, - uGreen: { value: new Float32Array(2), type: 'vec2' }, - uBlue: { value: new Float32Array(2), type: 'vec2' }, + uRed: { value: options.red, type: 'vec2' }, + uGreen: { value: options.green, type: 'vec2' }, + uBlue: { value: options.blue, type: 'vec2' }, }, - uDisplacementMap: Texture.WHITE, + uDisplacementMap: texture.source, + uDisplacementSampler: texture.source.style, }, }); this.uniforms = this.resources.glitchUniforms.uniforms; - this._canvas = document.createElement('canvas'); - this._canvas.width = 4; - this._canvas.height = this.sampleSize; - this.texture = getCanvasTexture(this._canvas, { style: { scaleMode: 'nearest' } }); + this._canvas = canvas; + this.texture = texture; Object.assign(this, options); } @@ -181,8 +187,8 @@ export class GlitchFilter extends Filter { const { width, height } = input.frame; - this.uniforms.uDimensions.x = width; - this.uniforms.uDimensions.y = height; + this.uniforms.uDimensions[0] = width; + this.uniforms.uDimensions[1] = height; this.uniforms.uAspect = height / width; filterManager.applyFilter(this, input, output, clearMode); @@ -302,7 +308,6 @@ export class GlitchFilter extends Filter } texture.source.update(); - this.resources.uDisplacementMap = texture; } /** diff --git a/filters/glitch/src/glitch.frag b/filters/glitch/src/glitch.frag index a5e3976ca..bf1a4ab8f 100644 --- a/filters/glitch/src/glitch.frag +++ b/filters/glitch/src/glitch.frag @@ -7,7 +7,7 @@ uniform sampler2D uDisplacementMap; uniform float uSeed; uniform vec2 uDimensions; uniform float uAspect; -uniform int uFillMode; +uniform float uFillMode; uniform float uOffset; uniform float uDirection; uniform vec2 uRed; @@ -50,41 +50,43 @@ void main(void) coord = vTextureCoord + vec2(cosDir * displacement, sinDir * displacement * uAspect); - if (uFillMode == CLAMP) { + int fillMode = int(uFillMode); + + if (fillMode == CLAMP) { coord = clamp(coord, uInputClamp.xy, uInputClamp.zw); } else { if( coord.x > uInputClamp.z ) { - if (uFillMode == TRANSPARENT) { + if (fillMode == TRANSPARENT) { discard; - } else if (uFillMode == LOOP) { + } else if (fillMode == LOOP) { coord.x -= uInputClamp.z; - } else if (uFillMode == MIRROR) { + } else if (fillMode == MIRROR) { coord.x = uInputClamp.z * 2.0 - coord.x; } } else if( coord.x < uInputClamp.x ) { - if (uFillMode == TRANSPARENT) { + if (fillMode == TRANSPARENT) { discard; - } else if (uFillMode == LOOP) { + } else if (fillMode == LOOP) { coord.x += uInputClamp.z; - } else if (uFillMode == MIRROR) { + } else if (fillMode == MIRROR) { coord.x *= -uInputClamp.z; } } if( coord.y > uInputClamp.w ) { - if (uFillMode == TRANSPARENT) { + if (fillMode == TRANSPARENT) { discard; - } else if (uFillMode == LOOP) { + } else if (fillMode == LOOP) { coord.y -= uInputClamp.w; - } else if (uFillMode == MIRROR) { + } else if (fillMode == MIRROR) { coord.y = uInputClamp.w * 2.0 - coord.y; } } else if( coord.y < uInputClamp.y ) { - if (uFillMode == TRANSPARENT) { + if (fillMode == TRANSPARENT) { discard; - } else if (uFillMode == LOOP) { + } else if (fillMode == LOOP) { coord.y += uInputClamp.w; - } else if (uFillMode == MIRROR) { + } else if (fillMode == MIRROR) { coord.y *= -uInputClamp.w; } } diff --git a/filters/glitch/src/glitch.wgsl b/filters/glitch/src/glitch.wgsl index 7ea8a6673..6576561c6 100644 --- a/filters/glitch/src/glitch.wgsl +++ b/filters/glitch/src/glitch.wgsl @@ -2,7 +2,7 @@ struct GlitchUniforms { uSeed: f32, uDimensions: vec2, uAspect: f32, - uFillMode: u32, + uFillMode: f32, uOffset: f32, uDirection: f32, uRed: vec2, @@ -24,11 +24,108 @@ struct GlobalFilterUniforms { @group(0) @binding(1) var uTexture: texture_2d; @group(0) @binding(2) var uSampler: sampler; @group(1) @binding(0) var glitchUniforms : GlitchUniforms; +@group(1) @binding(1) var uDisplacementMap: texture_2d; +@group(1) @binding(2) var uDisplacementSampler: sampler; @fragment fn mainFragment( @builtin(position) position: vec4, @location(0) uv : vec2 ) -> @location(0) vec4 { - return vec4(1.0, 0.0, 0.0, 1.0); -} \ No newline at end of file + let uSeed: f32 = glitchUniforms.uSeed; + let uDimensions: vec2 = glitchUniforms.uDimensions; + let uAspect: f32 = glitchUniforms.uAspect; + let uOffset: f32 = glitchUniforms.uOffset; + let uDirection: f32 = glitchUniforms.uDirection; + let uRed: vec2 = glitchUniforms.uRed; + let uGreen: vec2 = glitchUniforms.uGreen; + let uBlue: vec2 = glitchUniforms.uBlue; + + let uInputSize: vec4 = gfu.uInputSize; + let uInputClamp: vec4 = gfu.uInputClamp; + + var discarded: bool = false; + var coord: vec2 = (uv * uInputSize.xy) / uDimensions; + + if (coord.x > 1.0 || coord.y > 1.0) { + discarded = true; + } + + let sinDir: f32 = sin(uDirection); + let cosDir: f32 = cos(uDirection); + + let cx: f32 = coord.x - 0.5; + let cy: f32 = (coord.y - 0.5) * uAspect; + var ny: f32 = (-sinDir * cx + cosDir * cy) / uAspect + 0.5; + + ny = select(select(ny, -ny, ny < 0.0), 2.0 - ny, ny > 1.0); + + let dc: vec4 = textureSample(uDisplacementMap, uDisplacementSampler, vec2(0.5, ny)); + + let displacement: f32 = (dc.r - dc.g) * (uOffset / uInputSize.x); + + coord = uv + vec2(cosDir * displacement, sinDir * displacement * uAspect); + + let fillMode: i32 = i32(glitchUniforms.uFillMode); + + if (fillMode == CLAMP) { + coord = clamp(coord, uInputClamp.xy, uInputClamp.zw); + } else { + if (coord.x > uInputClamp.z) { + if (fillMode == TRANSPARENT) { + discarded = true; + } else if (fillMode == LOOP) { + coord.x = coord.x - uInputClamp.z; + } else if (fillMode == MIRROR) { + coord.x = uInputClamp.z * 2.0 - coord.x; + } + } else if (coord.x < uInputClamp.x) { + if (fillMode == TRANSPARENT) { + discarded = true; + } else if (fillMode == LOOP) { + coord.x = coord.x + uInputClamp.z; + } else if (fillMode == MIRROR) { + coord.x = coord.x * -uInputClamp.z; + } + } + + if (coord.y > uInputClamp.w) { + if (fillMode == TRANSPARENT) { + discarded = true; + } else if (fillMode == LOOP) { + coord.y = coord.y - uInputClamp.w; + } else if (fillMode == MIRROR) { + coord.y = uInputClamp.w * 2.0 - coord.y; + } + } else if (coord.y < uInputClamp.y) { + if (fillMode == TRANSPARENT) { + discarded = true; + } else if (fillMode == LOOP) { + coord.y = coord.y + uInputClamp.w; + } else if (fillMode == MIRROR) { + coord.y = coord.y * -uInputClamp.w; + } + } + } + + let seedR: f32 = 1.0 - uSeed * 0.4; + let seedG: f32 = 1.0 - uSeed * 0.3; + let seedB: f32 = 1.0 - uSeed * 0.2; + + let offsetR: vec2 = vec2(uRed.x * seedR / uInputSize.x, uRed.y * seedR / uInputSize.y); + let offsetG: vec2 = vec2(uGreen.x * seedG / uInputSize.x, uGreen.y * seedG / uInputSize.y); + let offsetB: vec2 = vec2(uBlue.x * seedB / uInputSize.x, uBlue.y * seedB / uInputSize.y); + + let r = textureSample(uTexture, uSampler, coord + offsetR).r; + let g = textureSample(uTexture, uSampler, coord + offsetG).g; + let b = textureSample(uTexture, uSampler, coord + offsetB).b; + let a = textureSample(uTexture, uSampler, coord).a; + + return select(vec4(r, g, b, a), vec4(0.0,0.0,0.0,0.0), discarded); +} + +const TRANSPARENT: i32 = 0; +const ORIGINAL: i32 = 1; +const LOOP: i32 = 2; +const CLAMP: i32 = 3; +const MIRROR: i32 = 4; \ No newline at end of file diff --git a/filters/outline/src/OutlineFilter.ts b/filters/outline/src/OutlineFilter.ts index ffe92e8d9..ee5338371 100644 --- a/filters/outline/src/OutlineFilter.ts +++ b/filters/outline/src/OutlineFilter.ts @@ -135,8 +135,6 @@ export class OutlineFilter extends Filter this.uniforms.uThickness[0] = this.thickness / input.source.width; this.uniforms.uThickness[1] = this.thickness / input.source.height; - this.resources.outlineUniforms.update(); - filterManager.applyFilter(this, input, output, clearMode); } diff --git a/filters/simple-lightmap/src/SimpleLightmapFilter.ts b/filters/simple-lightmap/src/SimpleLightmapFilter.ts index 00fbb744b..53f0c5279 100644 --- a/filters/simple-lightmap/src/SimpleLightmapFilter.ts +++ b/filters/simple-lightmap/src/SimpleLightmapFilter.ts @@ -86,7 +86,8 @@ export class SimpleLightmapFilter extends Filter uAlpha: { value: options.alpha, type: 'f32' }, uDimensions: { value: new Float32Array(2), type: 'vec2' }, }, - uMapTexture: options.lightMap, + uMapTexture: options.lightMap.source, + uMapSampler: options.lightMap.source.style, }, }); @@ -120,6 +121,7 @@ export class SimpleLightmapFilter extends Filter { this._lightMap = value; this.resources.uMapTexture = value.source; + this.resources.uMapSampler = value.source.style; } /** diff --git a/filters/simple-lightmap/src/simple-lightmap.wgsl b/filters/simple-lightmap/src/simple-lightmap.wgsl index 6a393379f..00dd8b6f2 100644 --- a/filters/simple-lightmap/src/simple-lightmap.wgsl +++ b/filters/simple-lightmap/src/simple-lightmap.wgsl @@ -19,6 +19,7 @@ struct GlobalFilterUniforms { @group(0) @binding(2) var uSampler: sampler; @group(1) @binding(0) var simpleLightmapUniforms : SimpleLightmapUniforms; @group(1) @binding(1) var uMapTexture: texture_2d; +@group(1) @binding(2) var uMapSampler: sampler; @fragment fn mainFragment( @@ -31,7 +32,7 @@ fn mainFragment( let diffuseColor: vec4 = textureSample(uTexture, uSampler, uv); let lightCoord: vec2 = (uv * gfu.uInputSize.xy) / simpleLightmapUniforms.uDimensions; - let light: vec4 = textureSample(uMapTexture, uSampler, lightCoord); + let light: vec4 = textureSample(uMapTexture, uMapSampler, lightCoord); let ambient: vec3 = uColor * uAlpha; let intensity: vec3 = ambient + light.rgb; let finalColor: vec3 = diffuseColor.rgb * intensity; diff --git a/tools/demo/src/filters/glitch.js b/tools/demo/src/filters/glitch.js index a5cd49350..876e0c92b 100644 --- a/tools/demo/src/filters/glitch.js +++ b/tools/demo/src/filters/glitch.js @@ -1,5 +1,3 @@ -import { logDebugTexture } from 'pixi.js'; - export default function () { const app = this;