diff --git a/packages/filters/.gitignore b/packages/filters/.gitignore new file mode 100644 index 0000000..1f22b9c --- /dev/null +++ b/packages/filters/.gitignore @@ -0,0 +1,116 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env +.env.test + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v2 +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* diff --git a/packages/filters/build/.flecksrc.js b/packages/filters/build/.flecksrc.js new file mode 100644 index 0000000..1d7a003 --- /dev/null +++ b/packages/filters/build/.flecksrc.js @@ -0,0 +1,7 @@ +module.exports = { + stubs: { + server: [ + /\.(frag|glsl|vert)$/, + ], + }, +}; diff --git a/packages/filters/build/fleck.neutrinorc.js b/packages/filters/build/fleck.neutrinorc.js new file mode 100644 index 0000000..e48d9a4 --- /dev/null +++ b/packages/filters/build/fleck.neutrinorc.js @@ -0,0 +1,12 @@ +module.exports = async (flecks) => { + // eslint-disable-next-line import/no-extraneous-dependencies, global-require + const config = await require('@flecks/fleck/server/build/fleck.neutrinorc')(flecks); + config.use.push(({config}) => { + config.module + .rule('glsl') + .test(/\.(frag|glsl|vert)$/) + .use('glsl') + .loader(require.resolve('webpack-glsl-loader')); + }); + return config; +}; diff --git a/packages/filters/package.json b/packages/filters/package.json new file mode 100644 index 0000000..5259979 --- /dev/null +++ b/packages/filters/package.json @@ -0,0 +1,28 @@ +{ + "name": "@avocado/filters", + "version": "1.0.0", + "scripts": { + "build": "flecks build", + "clean": "flecks clean", + "lint": "flecks lint", + "postversion": "cp package.json dist", + "test": "flecks test" + }, + "files": [ + "build", + "client.js", + "client.js.map", + "server.js", + "server.js.map", + "src", + "test" + ], + "dependencies": { + "@flecks/core": "^1.0.0", + "@pixi/core": "^5.3.9", + "webpack-glsl-loader": "^1.0.1" + }, + "devDependencies": { + "@flecks/fleck": "^1.0.0" + } +} diff --git a/packages/filters/src/client.js b/packages/filters/src/client.js new file mode 100644 index 0000000..38927bb --- /dev/null +++ b/packages/filters/src/client.js @@ -0,0 +1,2 @@ +// eslint-disable-next-line import/prefer-default-export +export {default as HorizontalSine} from './horizontal-sine'; diff --git a/packages/filters/src/horizontal-sine/index.frag b/packages/filters/src/horizontal-sine/index.frag new file mode 100644 index 0000000..a614280 --- /dev/null +++ b/packages/filters/src/horizontal-sine/index.frag @@ -0,0 +1,43 @@ +precision highp float; + +#define PI_D3 1.047197551 + +varying vec2 vTextureCoord; +uniform vec4 filterArea; +uniform sampler2D uSampler; + +uniform float frequency; +uniform bool isPixelated; +uniform float magnitude; +uniform float offset; +uniform float scale; + +vec2 denormalizeCoordinates(vec2 coord) { + return coord * filterArea.xy + filterArea.zw; +} + +vec2 normalizeCoordinates( vec2 coord ) { + return (coord - filterArea.zw) / filterArea.xy; +} + +void main(void) { + // Denormalize coordinates. + vec2 coord = denormalizeCoordinates(vTextureCoord); + // Calculate rotation radians. + float rads = mod( + frequency * ((((isPixelated ? floor(offset) : offset) * scale) + coord.y) / scale), + 6. + ); + if (isPixelated) { + rads = floor(rads / frequency) * frequency; + } + // Apply horizontal shift. + float xOff = scale * magnitude * cos(PI_D3 * rads); + if (isPixelated) { + xOff = floor(xOff / scale) * scale; + } + coord.x += xOff; + // Normalize and apply coordinates. + coord = normalizeCoordinates(coord); + gl_FragColor = texture2D(uSampler, coord); +} diff --git a/packages/filters/src/horizontal-sine/index.js b/packages/filters/src/horizontal-sine/index.js new file mode 100644 index 0000000..134dce3 --- /dev/null +++ b/packages/filters/src/horizontal-sine/index.js @@ -0,0 +1,55 @@ +import {defaultVertex, Filter} from '../imports'; +import frag from './index.frag'; + +export default class HorizontalSine extends Filter { + + constructor() { + super(defaultVertex, frag); + this.frequency = 1; + this.isPixelated = false; + this.magnitude = 0; + this.offset = 0; + this.scale = 1; + } + + get frequency() { + return this.uniforms.frequency; + } + + set frequency(frequency) { + this.uniforms.frequency = frequency; + } + + get isPixelated() { + return this.uniforms.isPixelated; + } + + set isPixelated(isPixelated) { + this.uniforms.isPixelated = isPixelated; + } + + get magnitude() { + return this.uniforms.magnitude; + } + + set magnitude(magnitude) { + this.uniforms.magnitude = magnitude; + } + + get offset() { + return this.uniforms.offset; + } + + set offset(offset) { + this.uniforms.offset = offset; + } + + get scale() { + return this.uniforms.scale; + } + + set scale(scale) { + this.uniforms.scale = scale; + } + +} diff --git a/packages/filters/src/imports.js b/packages/filters/src/imports.js new file mode 100644 index 0000000..b624965 --- /dev/null +++ b/packages/filters/src/imports.js @@ -0,0 +1,12 @@ +let defaultVertex; +let Filter; +if ('web' === process.env.FLECKS_CORE_BUILD_TARGET) { + // eslint-disable-next-line global-require + ({defaultVertex, Filter} = require('@pixi/core')); +} +else { + Filter = class {}; +} + +exports.defaultVertex = defaultVertex; +exports.Filter = Filter; diff --git a/packages/filters/src/server.js b/packages/filters/src/server.js new file mode 100644 index 0000000..6321895 --- /dev/null +++ b/packages/filters/src/server.js @@ -0,0 +1,15 @@ +import {Hooks} from '@flecks/core'; + +export default { + [Hooks]: { + '@flecks/core.build': (target, config) => { + config.use.push(({config}) => { + config.module + .rule('glsl') + .test(/\.(frag|glsl|vert)$/) + .use('glsl') + .loader(require.resolve('webpack-glsl-loader')); + }); + }, + }, +};