diff --git a/index.html b/index.html index a35234e..28ae0f3 100644 --- a/index.html +++ b/index.html @@ -46,6 +46,7 @@

3. Render the GIF

+ diff --git a/js/fetchers.js b/js/fetchers.js new file mode 100644 index 0000000..f73b83a --- /dev/null +++ b/js/fetchers.js @@ -0,0 +1,103 @@ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + if (typeof b !== "function" && b !== null) + throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +var FileFetcher = (function () { + function FileFetcher(directory, file, extension) { + var validDirRegex = /\/?[A-Za-z\-\_\.]+\/?/; + var validFileRegex = /[A-Za-z\-\_\.]+/; + var validExtensionRegex = /\.?[A-Za-z]+/; + if (!validDirRegex.test(directory)) { + throw new Error("Invalid Directory String:\"" + directory + "\""); + } + if (!validFileRegex.test(file)) { + throw new Error("Invalid File String:\"" + directory + "\""); + } + if (!validExtensionRegex.test(extension)) { + throw new Error("Invalid Extension String:\"" + directory + "\""); + } + if (!directory.endsWith("/")) { + directory += "/"; + } + if (!extension.startsWith(".")) { + extension = "." + extension; + } + this.path = directory + file + extension; + } + FileFetcher.prototype.FetchFile = function () { + var req = new XMLHttpRequest(); + req.open("GET", this.path, false); + req.send(null); + return { + response: req.response, + status: req.status, + type: req.responseType + }; + }; + FileFetcher.prototype.FetchFileAsync = function () { + return fetch(this.path); + }; + return FileFetcher; +}()); +var VertexShaderFetcher = (function (_super) { + __extends(VertexShaderFetcher, _super); + function VertexShaderFetcher(shaderName) { + return _super.call(this, "shaders", shaderName, ".vert") || this; + } + VertexShaderFetcher.prototype.GetShader = function () { + var response = this.FetchFile(); + if (response.status != 200) { + throw new Error("Request returned with code: " + response.status); + } + if (response.type != "text" && response.type != "") { + throw new Error("Response type error: Expected \"text\" but got \"" + response.type + "\""); + } + return response.response; + }; + VertexShaderFetcher.prototype.GetShaderAsync = function () { + return this.FetchFileAsync().then(function (value) { + if (!value.ok) { + Promise.reject("Response was not OK"); + } + return value.text(); + }); + }; + return VertexShaderFetcher; +}(FileFetcher)); +var FragmentShaderFetcher = (function (_super) { + __extends(FragmentShaderFetcher, _super); + function FragmentShaderFetcher(shaderName) { + return _super.call(this, "shaders", shaderName, ".frag") || this; + } + FragmentShaderFetcher.prototype.GetShader = function () { + var response = this.FetchFile(); + if (response.status != 200) { + throw new Error("Request returned with code: " + response.status); + } + if (response.type != "text" && response.type != "") { + throw new Error("Response type error: Expected \"text\" but got \"" + response.type + "\""); + } + return response.response; + }; + FragmentShaderFetcher.prototype.GetShaderAsync = function () { + return this.FetchFileAsync().then(function (value) { + if (!value.ok) { + Promise.reject("Response was not OK"); + } + return value.text(); + }); + }; + return FragmentShaderFetcher; +}(FileFetcher)); diff --git a/js/filters.js b/js/filters.js index a60a6e0..570ebb6 100644 --- a/js/filters.js +++ b/js/filters.js @@ -45,20 +45,20 @@ var filters = { "step": 1.0, } }, - "vertex": "#version 100\nprecision mediump float;\n\nattribute vec2 meshPosition;\nuniform float time;\nuniform vec2 emoteSize;\n\nuniform float interval;\nuniform float ground;\nuniform float scale;\nuniform float jump_height;\nuniform float hops;\n\nvarying vec2 uv;\n\nfloat sliding_from_left_to_right(float time_interval) {\n return (mod(time, time_interval) - time_interval * 0.5) / (time_interval * 0.5);\n}\n\nfloat flipping_directions(float time_interval) {\n return 1.0 - 2.0 * mod(floor(time / time_interval), 2.0);\n}\n\nvoid main() {\n float x_time_interval = interval;\n float y_time_interval = x_time_interval / (2.0 * hops);\n vec2 offset = vec2(\n sliding_from_left_to_right(x_time_interval) * flipping_directions(x_time_interval) * (1.0 - scale),\n ((sliding_from_left_to_right(y_time_interval) * flipping_directions(y_time_interval) + 1.0) / jump_height) - ground);\n\n gl_Position = vec4(\n meshPosition * scale + offset,\n 0.0,\n 1.0);\n\n uv = (meshPosition + vec2(1.0, 1.0)) / 2.0;\n\n uv.x = (flipping_directions(x_time_interval) + 1.0) / 2.0 - uv.x * flipping_directions(x_time_interval);\n}\n", - "fragment": "#version 100\n\nprecision mediump float;\n\nuniform vec2 resolution;\nuniform float time;\n\nuniform sampler2D emote;\n\nvarying vec2 uv;\n\nvoid main() {\n gl_FragColor = texture2D(emote, vec2(uv.x, 1.0 - uv.y));\n gl_FragColor.w = floor(gl_FragColor.w + 0.5);\n}\n" + "vertex": new VertexShaderFetcher("Hop"), + "fragment": new FragmentShaderFetcher("Hop"), }, "Hopper": { "transparent": 0x00FF00 + "", "duration": "0.85", - "vertex": "#version 100\nprecision mediump float;\n\nattribute vec2 meshPosition;\nuniform float time;\n\nvarying vec2 uv;\n\nfloat sliding_from_left_to_right(float time_interval) {\n return (mod(time, time_interval) - time_interval * 0.5) / (time_interval * 0.5);\n}\n\nfloat flipping_directions(float time_interval) {\n return 1.0 - 2.0 * mod(floor(time / time_interval), 2.0);\n}\n\nvoid main() {\n float scale = 0.40;\n float hops = 2.0;\n float x_time_interval = 0.85 / 2.0;\n float y_time_interval = x_time_interval / (2.0 * hops);\n float height = 0.5;\n vec2 offset = vec2(\n sliding_from_left_to_right(x_time_interval) * flipping_directions(x_time_interval) * (1.0 - scale),\n ((sliding_from_left_to_right(y_time_interval) * flipping_directions(y_time_interval) + 1.0) / 4.0) - height);\n\n gl_Position = vec4(\n meshPosition * scale + offset,\n 0.0,\n 1.0);\n\n uv = (meshPosition + vec2(1.0, 1.0)) / 2.0;\n\n uv.x = (flipping_directions(x_time_interval) + 1.0) / 2.0 - uv.x * flipping_directions(x_time_interval);\n}\n", - "fragment": "#version 100\n\nprecision mediump float;\n\nuniform vec2 resolution;\nuniform float time;\n\nuniform sampler2D emote;\n\nvarying vec2 uv;\n\nvoid main() {\n gl_FragColor = texture2D(emote, vec2(uv.x, 1.0 - uv.y));\n gl_FragColor.w = floor(gl_FragColor.w + 0.5);\n}\n" + "vertex": new VertexShaderFetcher("Hopper"), + "fragment": new FragmentShaderFetcher("Hopper"), }, "Overheat": { "transparent": 0x00FF00 + "", "duration": "0.85 / 8.0 * 2.0", - "vertex": "#version 100\nprecision mediump float;\n\nattribute vec2 meshPosition;\nuniform float time;\n\nvarying vec2 uv;\n\nfloat sliding_from_left_to_right(float time_interval) {\n return (mod(time, time_interval) - time_interval * 0.5) / (time_interval * 0.5);\n}\n\nfloat flipping_directions(float time_interval) {\n return 1.0 - 2.0 * mod(floor(time / time_interval), 2.0);\n}\n\nvoid main() {\n float scale = 0.40;\n float hops = 2.0;\n float x_time_interval = 0.85 / 8.0;\n float y_time_interval = x_time_interval / (2.0 * hops);\n float height = 0.5;\n vec2 offset = vec2(\n sliding_from_left_to_right(x_time_interval) * flipping_directions(x_time_interval) * (1.0 - scale),\n ((sliding_from_left_to_right(y_time_interval) * flipping_directions(y_time_interval) + 1.0) / 4.0) - height);\n\n gl_Position = vec4(\n meshPosition * scale + offset,\n 0.0,\n 1.0);\n\n uv = (meshPosition + vec2(1.0, 1.0)) / 2.0;\n\n uv.x = (flipping_directions(x_time_interval) + 1.0) / 2.0 - uv.x * flipping_directions(x_time_interval);\n}\n", - "fragment": "#version 100\n\nprecision mediump float;\n\nuniform vec2 resolution;\nuniform float time;\n\nuniform sampler2D emote;\n\nvarying vec2 uv;\n\nvoid main() {\n gl_FragColor = texture2D(emote, vec2(uv.x, 1.0 - uv.y)) * vec4(1.0, 0.0, 0.0, 1.0);\n gl_FragColor.w = floor(gl_FragColor.w + 0.5);\n}\n" + "vertex": new VertexShaderFetcher("Overheat"), + "fragment": new FragmentShaderFetcher("Overheat"), }, "Bounce": { "transparent": 0x00FF00 + "", @@ -79,56 +79,56 @@ var filters = { "step": 0.01, } }, - "vertex": "#version 100\nprecision mediump float;\n\nattribute vec2 meshPosition;\n\nuniform vec2 resolution;\nuniform float time;\n\nuniform float period;\nuniform float scale;\n\nvarying vec2 uv;\n\nvoid main() {\n vec2 offset = vec2(0.0, (2.0 * abs(sin(time * period)) - 1.0) * (1.0 - scale));\n gl_Position = vec4(meshPosition * scale + offset, 0.0, 1.0);\n uv = (meshPosition + 1.0) / 2.0;\n}\n", - "fragment": "\n#version 100\n\nprecision mediump float;\n\nuniform vec2 resolution;\nuniform float time;\n\nuniform sampler2D emote;\n\nvarying vec2 uv;\n\nvoid main() {\n gl_FragColor = texture2D(emote, vec2(uv.x, 1.0 - uv.y));\n gl_FragColor.w = floor(gl_FragColor.w + 0.5);\n}\n", + "vertex": new VertexShaderFetcher("Bounce"), + "fragment": new FragmentShaderFetcher("Bounce"), }, "Circle": { "transparent": 0x00FF00 + "", "duration": "Math.PI / 4.0", - "vertex": "#version 100\nprecision mediump float;\n\nattribute vec2 meshPosition;\n\nuniform vec2 resolution;\nuniform float time;\n\nvarying vec2 uv;\n\nvec2 rotate(vec2 v, float a) {\n\tfloat s = sin(a);\n\tfloat c = cos(a);\n\tmat2 m = mat2(c, -s, s, c);\n\treturn m * v;\n}\n\nvoid main() {\n float scale = 0.30;\n float period_interval = 8.0;\n float pi = 3.141592653589793238;\n vec2 outer_circle = vec2(cos(period_interval * time), sin(period_interval * time)) * (1.0 - scale);\n vec2 inner_circle = rotate(meshPosition * scale, (-period_interval * time) + pi / 2.0);\n gl_Position = vec4(\n inner_circle + outer_circle,\n 0.0,\n 1.0);\n uv = (meshPosition + 1.0) / 2.0;\n}\n", - "fragment": "\n#version 100\n\nprecision mediump float;\n\nuniform vec2 resolution;\nuniform float time;\n\nuniform sampler2D emote;\n\nvarying vec2 uv;\n\nvoid main() {\n float speed = 1.0;\n gl_FragColor = texture2D(emote, vec2(uv.x, 1.0 - uv.y));\n gl_FragColor.w = floor(gl_FragColor.w + 0.5);\n}\n", + "vertex": new VertexShaderFetcher("Circle"), + "fragment": new FragmentShaderFetcher("Circle"), }, "Slide": { "transparent": 0x00FF00 + "", "duration": "0.85 * 2", - "vertex": "#version 100\nprecision mediump float;\n\nattribute vec2 meshPosition;\nuniform float time;\n\nvarying vec2 uv;\n\nfloat sliding_from_left_to_right(float time_interval) {\n return (mod(time, time_interval) - time_interval * 0.5) / (time_interval * 0.5);\n}\n\nfloat flipping_directions(float time_interval) {\n return 1.0 - 2.0 * mod(floor(time / time_interval), 2.0);\n}\n\nvoid main() {\n float scale = 0.40;\n float hops = 2.0;\n float x_time_interval = 0.85;\n float y_time_interval = x_time_interval / (2.0 * hops);\n float height = 0.5;\n vec2 offset = vec2(\n sliding_from_left_to_right(x_time_interval) * flipping_directions(x_time_interval) * (1.0 - scale),\n - height);\n\n gl_Position = vec4(\n meshPosition * scale + offset,\n 0.0,\n 1.0);\n\n uv = (meshPosition + vec2(1.0, 1.0)) / 2.0;\n\n uv.x = (flipping_directions(x_time_interval) + 1.0) / 2.0 - uv.x * flipping_directions(x_time_interval);\n}\n", - "fragment": "#version 100\n\nprecision mediump float;\n\nuniform vec2 resolution;\nuniform float time;\n\nuniform sampler2D emote;\n\nvarying vec2 uv;\n\nvoid main() {\n gl_FragColor = texture2D(emote, vec2(uv.x, 1.0 - uv.y));\n gl_FragColor.w = floor(gl_FragColor.w + 0.5);\n}\n" + "vertex": new VertexShaderFetcher("Slide"), + "fragment": new FragmentShaderFetcher("Slide"), }, "Laughing": { "transparent": 0x00FF00 + "", "duration": "Math.PI / 12.0", - "vertex": "#version 100\nprecision mediump float;\n\nattribute vec2 meshPosition;\nuniform float time;\n\nvarying vec2 uv;\n\nvoid main() {\n float a = 0.3;\n float t = (sin(24.0 * time) * a + a) / 2.0;\n\n gl_Position = vec4(\n meshPosition - vec2(0.0, t),\n 0.0,\n 1.0);\n uv = (meshPosition + vec2(1.0, 1.0)) / 2.0;\n}\n", - "fragment": "#version 100\n\nprecision mediump float;\n\nuniform vec2 resolution;\nuniform float time;\n\nuniform sampler2D emote;\n\nvarying vec2 uv;\n\nvoid main() {\n gl_FragColor = texture2D(emote, vec2(uv.x, 1.0 - uv.y));\n gl_FragColor.w = floor(gl_FragColor.w + 0.5);\n}\n" + "vertex": new VertexShaderFetcher("Laughing"), + "fragment": new FragmentShaderFetcher("Laughing"), }, "Blob": { "transparent": 0x00FF00 + "", "duration": "Math.PI / 3", - "vertex": "#version 100\n\nprecision mediump float;\n\nattribute vec2 meshPosition;\n\nuniform vec2 resolution;\nuniform float time;\n\nvarying vec2 uv;\n\nvoid main() {\n float stretch = sin(6.0 * time) * 0.5 + 1.0;\n\n vec2 offset = vec2(0.0, 1.0 - stretch);\n gl_Position = vec4(\n meshPosition * vec2(stretch, 2.0 - stretch) + offset,\n 0.0,\n 1.0);\n uv = (meshPosition + vec2(1.0, 1.0)) / 2.0;\n}\n", - "fragment": "#version 100\n\nprecision mediump float;\n\nuniform vec2 resolution;\nuniform float time;\n\nuniform sampler2D emote;\n\nvarying vec2 uv;\n\nvoid main() {\n gl_FragColor = texture2D(emote, vec2(uv.x, 1.0 - uv.y));\n gl_FragColor.w = floor(gl_FragColor.w + 0.5);\n}\n" + "vertex": new VertexShaderFetcher("Blob"), + "fragment": new FragmentShaderFetcher("Blob"), }, "Go": { "transparent": 0x00FF00 + "", "duration": "1 / 4", - "vertex": "#version 100\nprecision mediump float;\n\nattribute vec2 meshPosition;\n\nuniform vec2 resolution;\nuniform float time;\n\nvarying vec2 uv;\n\nvoid main() {\n gl_Position = vec4(meshPosition, 0.0, 1.0);\n uv = (meshPosition + 1.0) / 2.0;\n}\n", - "fragment": "\n#version 100\n\nprecision mediump float;\n\nuniform vec2 resolution;\nuniform float time;\n\nuniform sampler2D emote;\n\nvarying vec2 uv;\n\nfloat slide(float speed, float value) {\n return mod(value - speed * time, 1.0);\n}\n\nvoid main() {\n float speed = 4.0;\n gl_FragColor = texture2D(emote, vec2(slide(speed, uv.x), 1.0 - uv.y));\n gl_FragColor.w = floor(gl_FragColor.w + 0.5);\n}\n", + "vertex": new VertexShaderFetcher("Go"), + "fragment": new FragmentShaderFetcher("Go"), }, "Elevator": { "transparent": 0x00FF00 + "", "duration": "1 / 4", - "vertex": "#version 100\nprecision mediump float;\n\nattribute vec2 meshPosition;\n\nuniform vec2 resolution;\nuniform float time;\n\nvarying vec2 uv;\n\nvoid main() {\n gl_Position = vec4(meshPosition, 0.0, 1.0);\n uv = (meshPosition + 1.0) / 2.0;\n}\n", - "fragment": "\n#version 100\n\nprecision mediump float;\n\nuniform vec2 resolution;\nuniform float time;\n\nuniform sampler2D emote;\n\nvarying vec2 uv;\n\nfloat slide(float speed, float value) {\n return mod(value - speed * time, 1.0);\n}\n\nvoid main() {\n float speed = 4.0;\n gl_FragColor = texture2D(\n emote,\n vec2(uv.x, slide(speed, 1.0 - uv.y)));\n gl_FragColor.w = floor(gl_FragColor.w + 0.5);\n}\n", + "vertex": new VertexShaderFetcher("Elevator"), + "fragment": new FragmentShaderFetcher("Elevator"), }, "Rain": { "transparent": 0x00FF00 + "", "duration": "1", - "vertex": "#version 100\nprecision mediump float;\n\nattribute vec2 meshPosition;\n\nuniform vec2 resolution;\nuniform float time;\n\nvarying vec2 uv;\n\nvoid main() {\n gl_Position = vec4(meshPosition, 0.0, 1.0);\n uv = (meshPosition + 1.0) / 2.0;\n}\n", - "fragment": "\n#version 100\n\nprecision mediump float;\n\nuniform vec2 resolution;\nuniform float time;\n\nuniform sampler2D emote;\n\nvarying vec2 uv;\n\nfloat slide(float speed, float value) {\n return mod(value - speed * time, 1.0);\n}\n\nvoid main() {\n float speed = 1.0;\n gl_FragColor = texture2D(\n emote,\n vec2(mod(4.0 * slide(speed, uv.x), 1.0),\n mod(4.0 * slide(speed, 1.0 - uv.y), 1.0)));\n gl_FragColor.w = floor(gl_FragColor.w + 0.5);\n}\n", + "vertex": new VertexShaderFetcher("Rain"), + "fragment": new FragmentShaderFetcher("Rain"), }, "Pride": { "transparent": null, "duration": "2.0", - "vertex": "#version 100\nprecision mediump float;\n\nattribute vec2 meshPosition;\n\nuniform vec2 resolution;\nuniform float time;\n\nvarying vec2 uv;\n\nvoid main() {\n gl_Position = vec4(meshPosition, 0.0, 1.0);\n uv = (meshPosition + 1.0) / 2.0;\n}\n", - "fragment": "\n#version 100\n\nprecision mediump float;\n\nuniform vec2 resolution;\nuniform float time;\n\nuniform sampler2D emote;\n\nvarying vec2 uv;\n\nvec3 hsl2rgb(vec3 c) {\n vec3 rgb = clamp(abs(mod(c.x*6.0+vec3(0.0,4.0,2.0),6.0)-3.0)-1.0, 0.0, 1.0);\n return c.z + c.y * (rgb-0.5)*(1.0-abs(2.0*c.z-1.0));\n}\n\nvoid main() {\n float speed = 1.0;\n\n vec4 pixel = texture2D(emote, vec2(uv.x, 1.0 - uv.y));\n pixel.w = floor(pixel.w + 0.5);\n pixel = vec4(mix(vec3(1.0), pixel.xyz, pixel.w), 1.0);\n vec4 rainbow = vec4(hsl2rgb(vec3((time - uv.x - uv.y) * 0.5, 1.0, 0.80)), 1.0);\n gl_FragColor = pixel * rainbow;\n}\n", + "vertex": new VertexShaderFetcher("Pride"), + "fragment": new FragmentShaderFetcher("Pride"), }, "Hard": { "transparent": 0x00FF00 + "", @@ -156,26 +156,26 @@ var filters = { "step": 0.001, }, }, - "vertex": "#version 100\nprecision mediump float;\n\nattribute vec2 meshPosition;\n\nuniform vec2 resolution;\nuniform float time;\n\nuniform float zoom;\nuniform float intensity;\nuniform float amplitude;\n\nvarying vec2 uv;\n\nvoid main() {\n vec2 shaking = vec2(cos(intensity * time), sin(intensity * time)) * amplitude;\n gl_Position = vec4(meshPosition * zoom + shaking, 0.0, 1.0);\n uv = (meshPosition + 1.0) / 2.0;\n}\n", - "fragment": "\n#version 100\n\nprecision mediump float;\n\nuniform vec2 resolution;\nuniform float time;\n\nuniform sampler2D emote;\n\nvarying vec2 uv;\n\nvoid main() {\n gl_FragColor = texture2D(emote, vec2(uv.x, 1.0 - uv.y));\n gl_FragColor.w = floor(gl_FragColor.w + 0.5);\n}\n", + "vertex": new VertexShaderFetcher("Hard"), + "fragment": new FragmentShaderFetcher("Hard"), }, "Peek": { "transparent": 0x00FF00 + "", "duration": "2.0 * Math.PI", - "vertex": "#version 100\nprecision mediump float;\n\nattribute vec2 meshPosition;\n\nuniform vec2 resolution;\nuniform float time;\n\nvarying vec2 uv;\n\nvoid main() {\n float time_clipped= mod(time * 2.0, (4.0 * 3.14));\n\n float s1 = float(time_clipped < (2.0 * 3.14));\n float s2 = 1.0 - s1;\n\n float hold1 = float(time_clipped > (0.5 * 3.14) && time_clipped < (2.0 * 3.14));\n float hold2 = 1.0 - float(time_clipped > (2.5 * 3.14) && time_clipped < (4.0 * 3.14));\n\n float cycle_1 = 1.0 - ((s1 * sin(time_clipped) * (1.0 - hold1)) + hold1);\n float cycle_2 = s2 * hold2 * (sin(time_clipped) - 1.0); \n\n gl_Position = vec4(meshPosition.x + 1.0 + cycle_1 + cycle_2 , meshPosition.y, 0.0, 1.0);\n uv = (meshPosition + 1.0) / 2.0;\n}\n", - "fragment": "\n#version 100\n\nprecision mediump float;\n\nuniform vec2 resolution;\nuniform float time;\n\nuniform sampler2D emote;\n\nvarying vec2 uv;\n\nvoid main() {\n gl_FragColor = texture2D(emote, vec2(uv.x, 1.0 - uv.y));\n gl_FragColor.w = floor(gl_FragColor.w + 0.5);\n}\n", + "vertex": new VertexShaderFetcher("Peek"), + "fragment": new FragmentShaderFetcher("Peek"), }, "Matrix": { "transparent": null, "duration": "3.0", - "vertex": "\n #version 100\n precision mediump float;\n\n attribute vec2 meshPosition;\n\n uniform vec2 resolution;\n uniform float time;\n\n varying vec2 _uv;\n\n void main()\n {\n _uv = (meshPosition + 1.0) / 2.0;\n gl_Position = vec4(meshPosition.x, meshPosition.y, 0.0, 1.0);\n }\n ", - "fragment": "\n #version 100\n precision mediump float;\n\n uniform vec2 resolution;\n uniform float time;\n uniform sampler2D emote;\n\n varying vec2 _uv;\n\n float clamp01(float value)\n {\n return clamp(value, 0.0, 1.0);\n }\n\n float sdf_zero(vec2 uv)\n {\n float inside = step(0.15, abs(uv.x)) + step(0.3, abs(uv.y));\n float outside = step(0.35, abs(uv.x)) + step(0.4, abs(uv.y));\n return clamp01(inside) - clamp01(outside);\n }\n\n float sdf_one(vec2 uv)\n {\n float top = step(0.25, -uv.y) * step(0.0, uv.x);\n float inside = (step(0.2, uv.x) + top);\n float outside = step(0.35, abs(uv.x)) + step(0.4, abs(uv.y));\n return clamp01(clamp01(inside) - clamp01(outside));\n }\n\n // Random float. No precomputed gradients mean this works for any number of grid coordinates\n float random01(vec2 n)\n {\n float random = 2920.0 * sin(n.x * 21942.0 + n.y * 171324.0 + 8912.0) *\n cos(n.x * 23157.0 * n.y * 217832.0 + 9758.0);\n \n return (sin(random) + 1.0) / 2.0;\n }\n\n float loop_time(float time_frame)\n {\n float times = floor(time / time_frame);\n return time - (times * time_frame);\n }\n\n void main()\n {\n vec2 uv = _uv;\n uv.y = 1.0 - _uv.y;\n \n float number_of_numbers = 8.0;\n float number_change_rate = 2.0;\n float amount_of_numbers = 0.6; // from 0 - 1\n \n vec4 texture_color = texture2D(emote, uv);\n vec4 number_color = vec4(0, 0.7, 0, 1);\n\n float looped_time = loop_time(3.0); \n\n vec2 translation = vec2(0, looped_time * -8.0);\n\n vec2 pos_idx = floor(uv * number_of_numbers + translation);\n float rnd_number = step(0.5, random01(pos_idx + floor(looped_time * number_change_rate)));\n float rnd_show = step(1.0 - amount_of_numbers, random01(pos_idx + vec2(99,99)));\n\n vec2 nuv = uv * number_of_numbers + translation;\n nuv = fract(nuv);\n\n float one = sdf_one(nuv - 0.5) * rnd_number;\n float zero = sdf_zero(nuv - 0.5) * (1.0 - rnd_number);\n float number = (one + zero) * rnd_show;\n\n float is_texture = 1.0 - number;\n float is_number = number;\n\n vec4 col = (texture_color * is_texture) + (number_color * is_number);\n\n gl_FragColor = col;\n gl_FragColor.w = 1.0;\n }\n " + "vertex": new VertexShaderFetcher("Matrix"), + "fragment": new FragmentShaderFetcher("Matrix"), }, "Flag": { "transparent": 0x00FF00 + "", "duration": "Math.PI", - "vertex": "\n #version 100\n precision mediump float;\n\n attribute vec2 meshPosition;\n\n uniform vec2 resolution;\n uniform float time;\n\n varying vec2 _uv;\n\n void main()\n {\n _uv = (meshPosition + 1.0) / 2.0;\n _uv.y = 1.0 - _uv.y;\n gl_Position = vec4(meshPosition.x, meshPosition.y, 0.0, 1.0);\n }\n ", - "fragment": "\n #version 100\n precision mediump float;\n\n varying vec2 _uv;\n uniform sampler2D emote;\n uniform float time;\n\n float sin01(float value)\n {\n return (sin(value) + 1.0) / 2.0;\n }\n\n //pos is left bottom point.\n float sdf_rect(vec2 pos, vec2 size, vec2 uv)\n {\n float left = pos.x;\n float right = pos.x + size.x;\n float bottom = pos.y;\n float top = pos.y + size.y;\n return (step(bottom, uv.y) - step(top, uv.y)) * (step(left, uv.x) - step(right, uv.x)); \n }\n\n void main() {\n float stick_width = 0.1;\n float flag_height = 0.75;\n float wave_size = 0.08;\n vec4 stick_color = vec4(107.0 / 256.0, 59.0 / 256.0, 9.0 / 256.0,1);\n \n vec2 flag_uv = _uv;\n flag_uv.x = (1.0 / (1.0 - stick_width)) * (flag_uv.x - stick_width);\n flag_uv.y *= 1.0 / flag_height;\n\n float flag_close_to_stick = smoothstep(0.0, 0.5, flag_uv.x);\n flag_uv.y += sin((-time * 2.0) + (flag_uv.x * 8.0)) * flag_close_to_stick * wave_size;\n\n float is_flag = sdf_rect(vec2(0,0), vec2(1.0, 1.0), flag_uv);\n float is_flag_stick = sdf_rect(vec2(0.0, 0.0), vec2(stick_width, 1), _uv);\n\n vec4 emote_color = texture2D(emote, flag_uv);\n vec4 texture_color = (emote_color * is_flag) + (stick_color * is_flag_stick);\n\n gl_FragColor = texture_color;\n }\n " + "vertex": new VertexShaderFetcher("Flag"), + "fragment": new FragmentShaderFetcher("Flag"), }, "Thanosed": { "transparent": 0x00FF00 + "", @@ -203,8 +203,8 @@ var filters = { "step": 1.0, }, }, - "vertex": "#version 100\nprecision mediump float;\n\nattribute vec2 meshPosition;\n\nuniform vec2 resolution;\nuniform float time;\n\nvarying vec2 uv;\n\nvoid main() {\n gl_Position = vec4(meshPosition, 0.0, 1.0);\n uv = (meshPosition + 1.0) / 2.0;\n}\n", - "fragment": "\n#version 100\n\nprecision mediump float;\n\nuniform vec2 resolution;\nuniform float time;\nuniform float duration;\nuniform float delay;\nuniform float pixelization;\n\nuniform sampler2D emote;\n\nvarying vec2 uv;\n\n// https://www.aussiedwarf.com/2017/05/09/Random10Bit.html\nfloat rand(vec2 co){\n vec3 product = vec3( sin( dot(co, vec2(0.129898,0.78233))),\n sin( dot(co, vec2(0.689898,0.23233))),\n sin( dot(co, vec2(0.434198,0.51833))) );\n vec3 weighting = vec3(4.37585453723, 2.465973, 3.18438);\n return fract(dot(weighting, product));\n}\n\nvoid main() {\n float pixelated_resolution = 112.0 / pixelization;\n vec2 pixelated_uv = floor(uv * pixelated_resolution);\n float noise = (rand(pixelated_uv) + 1.0) / 2.0;\n float slope = (0.2 + noise * 0.8) * (1.0 - (0.0 + uv.x * 0.5));\n float time_interval = 1.1 + delay * 2.0;\n float progress = 0.2 + delay + slope - mod(time_interval * time / duration, time_interval);\n float mask = progress > 0.1 ? 1.0 : 0.0;\n vec4 pixel = texture2D(emote, vec2(uv.x * (progress > 0.5 ? 1.0 : progress * 2.0), 1.0 - uv.y));\n pixel.w = floor(pixel.w + 0.5);\n gl_FragColor = pixel * vec4(vec3(1.0), mask);\n}\n", + "vertex": new VertexShaderFetcher("Thanosed"), + "fragment": new FragmentShaderFetcher("Thanosed"), }, "Ripple": { "transparent": 0x00FF00 + "", @@ -235,7 +235,7 @@ var filters = { "step": 0.01, } }, - "vertex": "#version 100\nprecision mediump float;\n\nattribute vec2 meshPosition;\n\nuniform vec2 resolution;\nuniform float time;\n\nvarying vec2 uv;\n\nvoid main() {\n gl_Position = vec4(meshPosition, 0.0, 1.0);\n uv = (meshPosition + 1.0) / 2.0;\n}\n", - "fragment": "#version 100\n\nprecision mediump float;\n\nuniform vec2 resolution;\nuniform float time;\n\nuniform sampler2D emote;\n\nuniform float a;\nuniform float b;\nuniform float c;\n\nvarying vec2 uv;\n\nvoid main() {\n vec2 pos = vec2(uv.x, 1.0 - uv.y);\n vec2 center = vec2(0.5);\n vec2 dir = pos - center;\n float x = length(dir);\n float y = sin(x + time);\n vec4 pixel = texture2D(emote, pos + cos(x*a - time*b)*c*(dir/x));\n gl_FragColor = pixel;\n gl_FragColor.w = floor(gl_FragColor.w + 0.5);\n}\n", + "vertex": new VertexShaderFetcher("Ripple"), + "fragment": new FragmentShaderFetcher("Ripple"), } }; diff --git a/js/index.js b/js/index.js index de6ae23..8493664 100644 --- a/js/index.js +++ b/js/index.js @@ -62,8 +62,10 @@ function createTextureFromImage(gl, image) { } function loadFilterProgram(gl, filter, vertexAttribs) { var _a; - var vertexShader = compileShaderSource(gl, filter.vertex, gl.VERTEX_SHADER); - var fragmentShader = compileShaderSource(gl, filter.fragment, gl.FRAGMENT_SHADER); + var vertexShaderSource = filter.vertex instanceof VertexShaderFetcher ? filter.vertex.GetShader() : filter.vertex; + var fragmentShaderSource = filter.fragment instanceof FragmentShaderFetcher ? filter.fragment.GetShader() : filter.fragment; + var vertexShader = compileShaderSource(gl, vertexShaderSource, gl.VERTEX_SHADER); + var fragmentShader = compileShaderSource(gl, fragmentShaderSource, gl.FRAGMENT_SHADER); var id = linkShaderProgram(gl, [vertexShader, fragmentShader], vertexAttribs); gl.deleteShader(vertexShader); gl.deleteShader(fragmentShader); diff --git a/shaders/Blob.frag b/shaders/Blob.frag new file mode 100644 index 0000000..b26b997 --- /dev/null +++ b/shaders/Blob.frag @@ -0,0 +1,15 @@ +#version 100 + +precision mediump float; + +uniform vec2 resolution; +uniform float time; + +uniform sampler2D emote; + +varying vec2 uv; + +void main() { + gl_FragColor = texture2D(emote, vec2(uv.x, 1.0 - uv.y)); + gl_FragColor.w = floor(gl_FragColor.w + 0.5); +} diff --git a/shaders/Blob.vert b/shaders/Blob.vert new file mode 100644 index 0000000..f5551ea --- /dev/null +++ b/shaders/Blob.vert @@ -0,0 +1,21 @@ +#version 100 + +precision mediump float; + +attribute vec2 meshPosition; + +uniform vec2 resolution; +uniform float time; + +varying vec2 uv; + +void main() { + float stretch = sin(6.0 * time) * 0.5 + 1.0; + + vec2 offset = vec2(0.0, 1.0 - stretch); + gl_Position = vec4( + meshPosition * vec2(stretch, 2.0 - stretch) + offset, + 0.0, + 1.0); + uv = (meshPosition + vec2(1.0, 1.0)) / 2.0; +} diff --git a/shaders/Bounce.frag b/shaders/Bounce.frag new file mode 100644 index 0000000..512f782 --- /dev/null +++ b/shaders/Bounce.frag @@ -0,0 +1,16 @@ + +#version 100 + +precision mediump float; + +uniform vec2 resolution; +uniform float time; + +uniform sampler2D emote; + +varying vec2 uv; + +void main() { + gl_FragColor = texture2D(emote, vec2(uv.x, 1.0 - uv.y)); + gl_FragColor.w = floor(gl_FragColor.w + 0.5); +} diff --git a/shaders/Bounce.vert b/shaders/Bounce.vert new file mode 100644 index 0000000..544b9ca --- /dev/null +++ b/shaders/Bounce.vert @@ -0,0 +1,18 @@ +#version 100 +precision mediump float; + +attribute vec2 meshPosition; + +uniform vec2 resolution; +uniform float time; + +uniform float period; +uniform float scale; + +varying vec2 uv; + +void main() { + vec2 offset = vec2(0.0, (2.0 * abs(sin(time * period)) - 1.0) * (1.0 - scale)); + gl_Position = vec4(meshPosition * scale + offset, 0.0, 1.0); + uv = (meshPosition + 1.0) / 2.0; +} diff --git a/shaders/Circle.frag b/shaders/Circle.frag new file mode 100644 index 0000000..5847af3 --- /dev/null +++ b/shaders/Circle.frag @@ -0,0 +1,17 @@ + +#version 100 + +precision mediump float; + +uniform vec2 resolution; +uniform float time; + +uniform sampler2D emote; + +varying vec2 uv; + +void main() { + float speed = 1.0; + gl_FragColor = texture2D(emote, vec2(uv.x, 1.0 - uv.y)); + gl_FragColor.w = floor(gl_FragColor.w + 0.5); +} diff --git a/shaders/Circle.vert b/shaders/Circle.vert new file mode 100644 index 0000000..291b493 --- /dev/null +++ b/shaders/Circle.vert @@ -0,0 +1,29 @@ +#version 100 +precision mediump float; + +attribute vec2 meshPosition; + +uniform vec2 resolution; +uniform float time; + +varying vec2 uv; + +vec2 rotate(vec2 v, float a) { + float s = sin(a); + float c = cos(a); + mat2 m = mat2(c, -s, s, c); + return m * v; +} + +void main() { + float scale = 0.30; + float period_interval = 8.0; + float pi = 3.141592653589793238; + vec2 outer_circle = vec2(cos(period_interval * time), sin(period_interval * time)) * (1.0 - scale); + vec2 inner_circle = rotate(meshPosition * scale, (-period_interval * time) + pi / 2.0); + gl_Position = vec4( + inner_circle + outer_circle, + 0.0, + 1.0); + uv = (meshPosition + 1.0) / 2.0; +} diff --git a/shaders/Elevator.frag b/shaders/Elevator.frag new file mode 100644 index 0000000..122031b --- /dev/null +++ b/shaders/Elevator.frag @@ -0,0 +1,23 @@ + +#version 100 + +precision mediump float; + +uniform vec2 resolution; +uniform float time; + +uniform sampler2D emote; + +varying vec2 uv; + +float slide(float speed, float value) { + return mod(value - speed * time, 1.0); +} + +void main() { + float speed = 4.0; + gl_FragColor = texture2D( + emote, + vec2(uv.x, slide(speed, 1.0 - uv.y))); + gl_FragColor.w = floor(gl_FragColor.w + 0.5); +} diff --git a/shaders/Elevator.vert b/shaders/Elevator.vert new file mode 100644 index 0000000..721a2f4 --- /dev/null +++ b/shaders/Elevator.vert @@ -0,0 +1,14 @@ +#version 100 +precision mediump float; + +attribute vec2 meshPosition; + +uniform vec2 resolution; +uniform float time; + +varying vec2 uv; + +void main() { + gl_Position = vec4(meshPosition, 0.0, 1.0); + uv = (meshPosition + 1.0) / 2.0; +} diff --git a/shaders/Flag.frag b/shaders/Flag.frag new file mode 100644 index 0000000..68b44cd --- /dev/null +++ b/shaders/Flag.frag @@ -0,0 +1,45 @@ + + #version 100 + precision mediump float; + + varying vec2 _uv; + uniform sampler2D emote; + uniform float time; + + float sin01(float value) + { + return (sin(value) + 1.0) / 2.0; + } + + //pos is left bottom point. + float sdf_rect(vec2 pos, vec2 size, vec2 uv) + { + float left = pos.x; + float right = pos.x + size.x; + float bottom = pos.y; + float top = pos.y + size.y; + return (step(bottom, uv.y) - step(top, uv.y)) * (step(left, uv.x) - step(right, uv.x)); + } + + void main() { + float stick_width = 0.1; + float flag_height = 0.75; + float wave_size = 0.08; + vec4 stick_color = vec4(107.0 / 256.0, 59.0 / 256.0, 9.0 / 256.0,1); + + vec2 flag_uv = _uv; + flag_uv.x = (1.0 / (1.0 - stick_width)) * (flag_uv.x - stick_width); + flag_uv.y *= 1.0 / flag_height; + + float flag_close_to_stick = smoothstep(0.0, 0.5, flag_uv.x); + flag_uv.y += sin((-time * 2.0) + (flag_uv.x * 8.0)) * flag_close_to_stick * wave_size; + + float is_flag = sdf_rect(vec2(0,0), vec2(1.0, 1.0), flag_uv); + float is_flag_stick = sdf_rect(vec2(0.0, 0.0), vec2(stick_width, 1), _uv); + + vec4 emote_color = texture2D(emote, flag_uv); + vec4 texture_color = (emote_color * is_flag) + (stick_color * is_flag_stick); + + gl_FragColor = texture_color; + } + \ No newline at end of file diff --git a/shaders/Flag.vert b/shaders/Flag.vert new file mode 100644 index 0000000..6ca3e80 --- /dev/null +++ b/shaders/Flag.vert @@ -0,0 +1,18 @@ + + #version 100 + precision mediump float; + + attribute vec2 meshPosition; + + uniform vec2 resolution; + uniform float time; + + varying vec2 _uv; + + void main() + { + _uv = (meshPosition + 1.0) / 2.0; + _uv.y = 1.0 - _uv.y; + gl_Position = vec4(meshPosition.x, meshPosition.y, 0.0, 1.0); + } + \ No newline at end of file diff --git a/shaders/Go.frag b/shaders/Go.frag new file mode 100644 index 0000000..1c8644d --- /dev/null +++ b/shaders/Go.frag @@ -0,0 +1,21 @@ + +#version 100 + +precision mediump float; + +uniform vec2 resolution; +uniform float time; + +uniform sampler2D emote; + +varying vec2 uv; + +float slide(float speed, float value) { + return mod(value - speed * time, 1.0); +} + +void main() { + float speed = 4.0; + gl_FragColor = texture2D(emote, vec2(slide(speed, uv.x), 1.0 - uv.y)); + gl_FragColor.w = floor(gl_FragColor.w + 0.5); +} diff --git a/shaders/Go.vert b/shaders/Go.vert new file mode 100644 index 0000000..721a2f4 --- /dev/null +++ b/shaders/Go.vert @@ -0,0 +1,14 @@ +#version 100 +precision mediump float; + +attribute vec2 meshPosition; + +uniform vec2 resolution; +uniform float time; + +varying vec2 uv; + +void main() { + gl_Position = vec4(meshPosition, 0.0, 1.0); + uv = (meshPosition + 1.0) / 2.0; +} diff --git a/shaders/Hard.frag b/shaders/Hard.frag new file mode 100644 index 0000000..512f782 --- /dev/null +++ b/shaders/Hard.frag @@ -0,0 +1,16 @@ + +#version 100 + +precision mediump float; + +uniform vec2 resolution; +uniform float time; + +uniform sampler2D emote; + +varying vec2 uv; + +void main() { + gl_FragColor = texture2D(emote, vec2(uv.x, 1.0 - uv.y)); + gl_FragColor.w = floor(gl_FragColor.w + 0.5); +} diff --git a/shaders/Hard.vert b/shaders/Hard.vert new file mode 100644 index 0000000..d4b08b1 --- /dev/null +++ b/shaders/Hard.vert @@ -0,0 +1,19 @@ +#version 100 +precision mediump float; + +attribute vec2 meshPosition; + +uniform vec2 resolution; +uniform float time; + +uniform float zoom; +uniform float intensity; +uniform float amplitude; + +varying vec2 uv; + +void main() { + vec2 shaking = vec2(cos(intensity * time), sin(intensity * time)) * amplitude; + gl_Position = vec4(meshPosition * zoom + shaking, 0.0, 1.0); + uv = (meshPosition + 1.0) / 2.0; +} diff --git a/shaders/Hop.frag b/shaders/Hop.frag new file mode 100644 index 0000000..b26b997 --- /dev/null +++ b/shaders/Hop.frag @@ -0,0 +1,15 @@ +#version 100 + +precision mediump float; + +uniform vec2 resolution; +uniform float time; + +uniform sampler2D emote; + +varying vec2 uv; + +void main() { + gl_FragColor = texture2D(emote, vec2(uv.x, 1.0 - uv.y)); + gl_FragColor.w = floor(gl_FragColor.w + 0.5); +} diff --git a/shaders/Hop.vert b/shaders/Hop.vert new file mode 100644 index 0000000..1e668e6 --- /dev/null +++ b/shaders/Hop.vert @@ -0,0 +1,39 @@ +#version 100 +precision mediump float; + +attribute vec2 meshPosition; +uniform float time; +uniform vec2 emoteSize; + +uniform float interval; +uniform float ground; +uniform float scale; +uniform float jump_height; +uniform float hops; + +varying vec2 uv; + +float sliding_from_left_to_right(float time_interval) { + return (mod(time, time_interval) - time_interval * 0.5) / (time_interval * 0.5); +} + +float flipping_directions(float time_interval) { + return 1.0 - 2.0 * mod(floor(time / time_interval), 2.0); +} + +void main() { + float x_time_interval = interval; + float y_time_interval = x_time_interval / (2.0 * hops); + vec2 offset = vec2( + sliding_from_left_to_right(x_time_interval) * flipping_directions(x_time_interval) * (1.0 - scale), + ((sliding_from_left_to_right(y_time_interval) * flipping_directions(y_time_interval) + 1.0) / jump_height) - ground); + + gl_Position = vec4( + meshPosition * scale + offset, + 0.0, + 1.0); + + uv = (meshPosition + vec2(1.0, 1.0)) / 2.0; + + uv.x = (flipping_directions(x_time_interval) + 1.0) / 2.0 - uv.x * flipping_directions(x_time_interval); +} diff --git a/shaders/Hopper.frag b/shaders/Hopper.frag new file mode 100644 index 0000000..b26b997 --- /dev/null +++ b/shaders/Hopper.frag @@ -0,0 +1,15 @@ +#version 100 + +precision mediump float; + +uniform vec2 resolution; +uniform float time; + +uniform sampler2D emote; + +varying vec2 uv; + +void main() { + gl_FragColor = texture2D(emote, vec2(uv.x, 1.0 - uv.y)); + gl_FragColor.w = floor(gl_FragColor.w + 0.5); +} diff --git a/shaders/Hopper.vert b/shaders/Hopper.vert new file mode 100644 index 0000000..2d03bb8 --- /dev/null +++ b/shaders/Hopper.vert @@ -0,0 +1,35 @@ +#version 100 +precision mediump float; + +attribute vec2 meshPosition; +uniform float time; + +varying vec2 uv; + +float sliding_from_left_to_right(float time_interval) { + return (mod(time, time_interval) - time_interval * 0.5) / (time_interval * 0.5); +} + +float flipping_directions(float time_interval) { + return 1.0 - 2.0 * mod(floor(time / time_interval), 2.0); +} + +void main() { + float scale = 0.40; + float hops = 2.0; + float x_time_interval = 0.85 / 2.0; + float y_time_interval = x_time_interval / (2.0 * hops); + float height = 0.5; + vec2 offset = vec2( + sliding_from_left_to_right(x_time_interval) * flipping_directions(x_time_interval) * (1.0 - scale), + ((sliding_from_left_to_right(y_time_interval) * flipping_directions(y_time_interval) + 1.0) / 4.0) - height); + + gl_Position = vec4( + meshPosition * scale + offset, + 0.0, + 1.0); + + uv = (meshPosition + vec2(1.0, 1.0)) / 2.0; + + uv.x = (flipping_directions(x_time_interval) + 1.0) / 2.0 - uv.x * flipping_directions(x_time_interval); +} diff --git a/shaders/Laughing.frag b/shaders/Laughing.frag new file mode 100644 index 0000000..b26b997 --- /dev/null +++ b/shaders/Laughing.frag @@ -0,0 +1,15 @@ +#version 100 + +precision mediump float; + +uniform vec2 resolution; +uniform float time; + +uniform sampler2D emote; + +varying vec2 uv; + +void main() { + gl_FragColor = texture2D(emote, vec2(uv.x, 1.0 - uv.y)); + gl_FragColor.w = floor(gl_FragColor.w + 0.5); +} diff --git a/shaders/Laughing.vert b/shaders/Laughing.vert new file mode 100644 index 0000000..5607b41 --- /dev/null +++ b/shaders/Laughing.vert @@ -0,0 +1,18 @@ +#version 100 +precision mediump float; + +attribute vec2 meshPosition; +uniform float time; + +varying vec2 uv; + +void main() { + float a = 0.3; + float t = (sin(24.0 * time) * a + a) / 2.0; + + gl_Position = vec4( + meshPosition - vec2(0.0, t), + 0.0, + 1.0); + uv = (meshPosition + vec2(1.0, 1.0)) / 2.0; +} diff --git a/shaders/Matrix.frag b/shaders/Matrix.frag new file mode 100644 index 0000000..6ece924 --- /dev/null +++ b/shaders/Matrix.frag @@ -0,0 +1,81 @@ + + #version 100 + precision mediump float; + + uniform vec2 resolution; + uniform float time; + uniform sampler2D emote; + + varying vec2 _uv; + + float clamp01(float value) + { + return clamp(value, 0.0, 1.0); + } + + float sdf_zero(vec2 uv) + { + float inside = step(0.15, abs(uv.x)) + step(0.3, abs(uv.y)); + float outside = step(0.35, abs(uv.x)) + step(0.4, abs(uv.y)); + return clamp01(inside) - clamp01(outside); + } + + float sdf_one(vec2 uv) + { + float top = step(0.25, -uv.y) * step(0.0, uv.x); + float inside = (step(0.2, uv.x) + top); + float outside = step(0.35, abs(uv.x)) + step(0.4, abs(uv.y)); + return clamp01(clamp01(inside) - clamp01(outside)); + } + + // Random float. No precomputed gradients mean this works for any number of grid coordinates + float random01(vec2 n) + { + float random = 2920.0 * sin(n.x * 21942.0 + n.y * 171324.0 + 8912.0) * + cos(n.x * 23157.0 * n.y * 217832.0 + 9758.0); + + return (sin(random) + 1.0) / 2.0; + } + + float loop_time(float time_frame) + { + float times = floor(time / time_frame); + return time - (times * time_frame); + } + + void main() + { + vec2 uv = _uv; + uv.y = 1.0 - _uv.y; + + float number_of_numbers = 8.0; + float number_change_rate = 2.0; + float amount_of_numbers = 0.6; // from 0 - 1 + + vec4 texture_color = texture2D(emote, uv); + vec4 number_color = vec4(0, 0.7, 0, 1); + + float looped_time = loop_time(3.0); + + vec2 translation = vec2(0, looped_time * -8.0); + + vec2 pos_idx = floor(uv * number_of_numbers + translation); + float rnd_number = step(0.5, random01(pos_idx + floor(looped_time * number_change_rate))); + float rnd_show = step(1.0 - amount_of_numbers, random01(pos_idx + vec2(99,99))); + + vec2 nuv = uv * number_of_numbers + translation; + nuv = fract(nuv); + + float one = sdf_one(nuv - 0.5) * rnd_number; + float zero = sdf_zero(nuv - 0.5) * (1.0 - rnd_number); + float number = (one + zero) * rnd_show; + + float is_texture = 1.0 - number; + float is_number = number; + + vec4 col = (texture_color * is_texture) + (number_color * is_number); + + gl_FragColor = col; + gl_FragColor.w = 1.0; + } + \ No newline at end of file diff --git a/shaders/Matrix.vert b/shaders/Matrix.vert new file mode 100644 index 0000000..950d9dd --- /dev/null +++ b/shaders/Matrix.vert @@ -0,0 +1,17 @@ + + #version 100 + precision mediump float; + + attribute vec2 meshPosition; + + uniform vec2 resolution; + uniform float time; + + varying vec2 _uv; + + void main() + { + _uv = (meshPosition + 1.0) / 2.0; + gl_Position = vec4(meshPosition.x, meshPosition.y, 0.0, 1.0); + } + \ No newline at end of file diff --git a/shaders/Overheat.frag b/shaders/Overheat.frag new file mode 100644 index 0000000..8aaeb12 --- /dev/null +++ b/shaders/Overheat.frag @@ -0,0 +1,15 @@ +#version 100 + +precision mediump float; + +uniform vec2 resolution; +uniform float time; + +uniform sampler2D emote; + +varying vec2 uv; + +void main() { + gl_FragColor = texture2D(emote, vec2(uv.x, 1.0 - uv.y)) * vec4(1.0, 0.0, 0.0, 1.0); + gl_FragColor.w = floor(gl_FragColor.w + 0.5); +} diff --git a/shaders/Overheat.vert b/shaders/Overheat.vert new file mode 100644 index 0000000..7d8daaa --- /dev/null +++ b/shaders/Overheat.vert @@ -0,0 +1,35 @@ +#version 100 +precision mediump float; + +attribute vec2 meshPosition; +uniform float time; + +varying vec2 uv; + +float sliding_from_left_to_right(float time_interval) { + return (mod(time, time_interval) - time_interval * 0.5) / (time_interval * 0.5); +} + +float flipping_directions(float time_interval) { + return 1.0 - 2.0 * mod(floor(time / time_interval), 2.0); +} + +void main() { + float scale = 0.40; + float hops = 2.0; + float x_time_interval = 0.85 / 8.0; + float y_time_interval = x_time_interval / (2.0 * hops); + float height = 0.5; + vec2 offset = vec2( + sliding_from_left_to_right(x_time_interval) * flipping_directions(x_time_interval) * (1.0 - scale), + ((sliding_from_left_to_right(y_time_interval) * flipping_directions(y_time_interval) + 1.0) / 4.0) - height); + + gl_Position = vec4( + meshPosition * scale + offset, + 0.0, + 1.0); + + uv = (meshPosition + vec2(1.0, 1.0)) / 2.0; + + uv.x = (flipping_directions(x_time_interval) + 1.0) / 2.0 - uv.x * flipping_directions(x_time_interval); +} diff --git a/shaders/Peek.frag b/shaders/Peek.frag new file mode 100644 index 0000000..512f782 --- /dev/null +++ b/shaders/Peek.frag @@ -0,0 +1,16 @@ + +#version 100 + +precision mediump float; + +uniform vec2 resolution; +uniform float time; + +uniform sampler2D emote; + +varying vec2 uv; + +void main() { + gl_FragColor = texture2D(emote, vec2(uv.x, 1.0 - uv.y)); + gl_FragColor.w = floor(gl_FragColor.w + 0.5); +} diff --git a/shaders/Peek.vert b/shaders/Peek.vert new file mode 100644 index 0000000..cf96f2c --- /dev/null +++ b/shaders/Peek.vert @@ -0,0 +1,25 @@ +#version 100 +precision mediump float; + +attribute vec2 meshPosition; + +uniform vec2 resolution; +uniform float time; + +varying vec2 uv; + +void main() { + float time_clipped= mod(time * 2.0, (4.0 * 3.14)); + + float s1 = float(time_clipped < (2.0 * 3.14)); + float s2 = 1.0 - s1; + + float hold1 = float(time_clipped > (0.5 * 3.14) && time_clipped < (2.0 * 3.14)); + float hold2 = 1.0 - float(time_clipped > (2.5 * 3.14) && time_clipped < (4.0 * 3.14)); + + float cycle_1 = 1.0 - ((s1 * sin(time_clipped) * (1.0 - hold1)) + hold1); + float cycle_2 = s2 * hold2 * (sin(time_clipped) - 1.0); + + gl_Position = vec4(meshPosition.x + 1.0 + cycle_1 + cycle_2 , meshPosition.y, 0.0, 1.0); + uv = (meshPosition + 1.0) / 2.0; +} diff --git a/shaders/Pride.frag b/shaders/Pride.frag new file mode 100644 index 0000000..b7017c7 --- /dev/null +++ b/shaders/Pride.frag @@ -0,0 +1,26 @@ + +#version 100 + +precision mediump float; + +uniform vec2 resolution; +uniform float time; + +uniform sampler2D emote; + +varying vec2 uv; + +vec3 hsl2rgb(vec3 c) { + vec3 rgb = clamp(abs(mod(c.x*6.0+vec3(0.0,4.0,2.0),6.0)-3.0)-1.0, 0.0, 1.0); + return c.z + c.y * (rgb-0.5)*(1.0-abs(2.0*c.z-1.0)); +} + +void main() { + float speed = 1.0; + + vec4 pixel = texture2D(emote, vec2(uv.x, 1.0 - uv.y)); + pixel.w = floor(pixel.w + 0.5); + pixel = vec4(mix(vec3(1.0), pixel.xyz, pixel.w), 1.0); + vec4 rainbow = vec4(hsl2rgb(vec3((time - uv.x - uv.y) * 0.5, 1.0, 0.80)), 1.0); + gl_FragColor = pixel * rainbow; +} diff --git a/shaders/Pride.vert b/shaders/Pride.vert new file mode 100644 index 0000000..721a2f4 --- /dev/null +++ b/shaders/Pride.vert @@ -0,0 +1,14 @@ +#version 100 +precision mediump float; + +attribute vec2 meshPosition; + +uniform vec2 resolution; +uniform float time; + +varying vec2 uv; + +void main() { + gl_Position = vec4(meshPosition, 0.0, 1.0); + uv = (meshPosition + 1.0) / 2.0; +} diff --git a/shaders/Rain.frag b/shaders/Rain.frag new file mode 100644 index 0000000..cf44544 --- /dev/null +++ b/shaders/Rain.frag @@ -0,0 +1,24 @@ + +#version 100 + +precision mediump float; + +uniform vec2 resolution; +uniform float time; + +uniform sampler2D emote; + +varying vec2 uv; + +float slide(float speed, float value) { + return mod(value - speed * time, 1.0); +} + +void main() { + float speed = 1.0; + gl_FragColor = texture2D( + emote, + vec2(mod(4.0 * slide(speed, uv.x), 1.0), + mod(4.0 * slide(speed, 1.0 - uv.y), 1.0))); + gl_FragColor.w = floor(gl_FragColor.w + 0.5); +} diff --git a/shaders/Rain.vert b/shaders/Rain.vert new file mode 100644 index 0000000..721a2f4 --- /dev/null +++ b/shaders/Rain.vert @@ -0,0 +1,14 @@ +#version 100 +precision mediump float; + +attribute vec2 meshPosition; + +uniform vec2 resolution; +uniform float time; + +varying vec2 uv; + +void main() { + gl_Position = vec4(meshPosition, 0.0, 1.0); + uv = (meshPosition + 1.0) / 2.0; +} diff --git a/shaders/Ripple.frag b/shaders/Ripple.frag new file mode 100644 index 0000000..b91db6b --- /dev/null +++ b/shaders/Ripple.frag @@ -0,0 +1,25 @@ +#version 100 + +precision mediump float; + +uniform vec2 resolution; +uniform float time; + +uniform sampler2D emote; + +uniform float a; +uniform float b; +uniform float c; + +varying vec2 uv; + +void main() { + vec2 pos = vec2(uv.x, 1.0 - uv.y); + vec2 center = vec2(0.5); + vec2 dir = pos - center; + float x = length(dir); + float y = sin(x + time); + vec4 pixel = texture2D(emote, pos + cos(x*a - time*b)*c*(dir/x)); + gl_FragColor = pixel; + gl_FragColor.w = floor(gl_FragColor.w + 0.5); +} \ No newline at end of file diff --git a/shaders/Ripple.vert b/shaders/Ripple.vert new file mode 100644 index 0000000..6932ea0 --- /dev/null +++ b/shaders/Ripple.vert @@ -0,0 +1,14 @@ +#version 100 +precision mediump float; + +attribute vec2 meshPosition; + +uniform vec2 resolution; +uniform float time; + +varying vec2 uv; + +void main() { + gl_Position = vec4(meshPosition, 0.0, 1.0); + uv = (meshPosition + 1.0) / 2.0; +} \ No newline at end of file diff --git a/shaders/Slide.frag b/shaders/Slide.frag new file mode 100644 index 0000000..b26b997 --- /dev/null +++ b/shaders/Slide.frag @@ -0,0 +1,15 @@ +#version 100 + +precision mediump float; + +uniform vec2 resolution; +uniform float time; + +uniform sampler2D emote; + +varying vec2 uv; + +void main() { + gl_FragColor = texture2D(emote, vec2(uv.x, 1.0 - uv.y)); + gl_FragColor.w = floor(gl_FragColor.w + 0.5); +} diff --git a/shaders/Slide.vert b/shaders/Slide.vert new file mode 100644 index 0000000..25acf2b --- /dev/null +++ b/shaders/Slide.vert @@ -0,0 +1,35 @@ +#version 100 +precision mediump float; + +attribute vec2 meshPosition; +uniform float time; + +varying vec2 uv; + +float sliding_from_left_to_right(float time_interval) { + return (mod(time, time_interval) - time_interval * 0.5) / (time_interval * 0.5); +} + +float flipping_directions(float time_interval) { + return 1.0 - 2.0 * mod(floor(time / time_interval), 2.0); +} + +void main() { + float scale = 0.40; + float hops = 2.0; + float x_time_interval = 0.85; + float y_time_interval = x_time_interval / (2.0 * hops); + float height = 0.5; + vec2 offset = vec2( + sliding_from_left_to_right(x_time_interval) * flipping_directions(x_time_interval) * (1.0 - scale), + - height); + + gl_Position = vec4( + meshPosition * scale + offset, + 0.0, + 1.0); + + uv = (meshPosition + vec2(1.0, 1.0)) / 2.0; + + uv.x = (flipping_directions(x_time_interval) + 1.0) / 2.0 - uv.x * flipping_directions(x_time_interval); +} diff --git a/shaders/Thanosed.frag b/shaders/Thanosed.frag new file mode 100644 index 0000000..a7dce43 --- /dev/null +++ b/shaders/Thanosed.frag @@ -0,0 +1,36 @@ + +#version 100 + +precision mediump float; + +uniform vec2 resolution; +uniform float time; +uniform float duration; +uniform float delay; +uniform float pixelization; + +uniform sampler2D emote; + +varying vec2 uv; + +// https://www.aussiedwarf.com/2017/05/09/Random10Bit.html +float rand(vec2 co){ + vec3 product = vec3( sin( dot(co, vec2(0.129898,0.78233))), + sin( dot(co, vec2(0.689898,0.23233))), + sin( dot(co, vec2(0.434198,0.51833))) ); + vec3 weighting = vec3(4.37585453723, 2.465973, 3.18438); + return fract(dot(weighting, product)); +} + +void main() { + float pixelated_resolution = 112.0 / pixelization; + vec2 pixelated_uv = floor(uv * pixelated_resolution); + float noise = (rand(pixelated_uv) + 1.0) / 2.0; + float slope = (0.2 + noise * 0.8) * (1.0 - (0.0 + uv.x * 0.5)); + float time_interval = 1.1 + delay * 2.0; + float progress = 0.2 + delay + slope - mod(time_interval * time / duration, time_interval); + float mask = progress > 0.1 ? 1.0 : 0.0; + vec4 pixel = texture2D(emote, vec2(uv.x * (progress > 0.5 ? 1.0 : progress * 2.0), 1.0 - uv.y)); + pixel.w = floor(pixel.w + 0.5); + gl_FragColor = pixel * vec4(vec3(1.0), mask); +} diff --git a/shaders/Thanosed.vert b/shaders/Thanosed.vert new file mode 100644 index 0000000..721a2f4 --- /dev/null +++ b/shaders/Thanosed.vert @@ -0,0 +1,14 @@ +#version 100 +precision mediump float; + +attribute vec2 meshPosition; + +uniform vec2 resolution; +uniform float time; + +varying vec2 uv; + +void main() { + gl_Position = vec4(meshPosition, 0.0, 1.0); + uv = (meshPosition + 1.0) / 2.0; +} diff --git a/ts/fetchers.ts b/ts/fetchers.ts new file mode 100644 index 0000000..c96f21f --- /dev/null +++ b/ts/fetchers.ts @@ -0,0 +1,141 @@ + +interface XMLHttpResponse +{ + response: any; + status: number; + type: XMLHttpRequestResponseType +} + +class FileFetcher +{ + path: string; + + constructor(directory: string, file: string, extension: string) + { + + const validDirRegex: RegExp = /\/?[A-Za-z\-\_\.]+\/?/; + const validFileRegex: RegExp = /[A-Za-z\-\_\.]+/; + const validExtensionRegex: RegExp = /\.?[A-Za-z]+/; + + if(!validDirRegex.test(directory)) + { + throw new Error("Invalid Directory String:\""+directory+"\""); + } + + if(!validFileRegex.test(file)) + { + throw new Error("Invalid File String:\""+directory+"\""); + } + + if(!validExtensionRegex.test(extension)) + { + throw new Error("Invalid Extension String:\""+directory+"\""); + } + + if (!directory.endsWith("/")) + { + directory +="/" + } + + if(!extension.startsWith(".")) + { + extension = "." + extension; + } + + this.path = directory + file + extension; + } + + FetchFile() : XMLHttpResponse + { + let req : XMLHttpRequest = new XMLHttpRequest(); + req.open("GET", this.path, false); + req.send(null); + + return { + response: req.response, + status: req.status, + type: req.responseType + }; + } + + FetchFileAsync() : Promise + { + return fetch(this.path); + } +} + +class VertexShaderFetcher extends FileFetcher +{ + constructor(shaderName: string) + { + super("shaders",shaderName,".vert"); + } + + GetShader(): string + { + let response : XMLHttpResponse = this.FetchFile(); + + if(response.status != 200) + { + throw new Error(`Request returned with code: ${response.status}`); + } + + if (response.type != "text" && response.type != "") + { + throw new Error("Response type error: Expected \"text\" but got \"" + response.type + "\""); + } + + return (response.response as string); + } + + GetShaderAsync(): Promise + { + return this.FetchFileAsync().then( + (value: Response) => { + if (!value.ok) + { + Promise.reject("Response was not OK"); + } + return value.text(); + } + ); + } +} + +class FragmentShaderFetcher extends FileFetcher +{ + constructor(shaderName: string) + { + super("shaders",shaderName,".frag"); + } + + GetShader(): string + { + let response : XMLHttpResponse = this.FetchFile(); + + if(response.status != 200) + { + throw new Error(`Request returned with code: ${response.status}`); + } + + if (response.type != "text" && response.type != "") + { + throw new Error("Response type error: Expected \"text\" but got \"" + response.type + "\""); + } + + return (response.response as string); + } + + GetShaderAsync(): Promise + { + return this.FetchFileAsync().then( + (value: Response) => { + if (!value.ok) + { + Promise.reject("Response was not OK"); + } + return value.text(); + } + ); + } +} \ No newline at end of file diff --git a/ts/filters.ts b/ts/filters.ts index 0351601..da8683a 100644 --- a/ts/filters.ts +++ b/ts/filters.ts @@ -13,8 +13,8 @@ interface Filter { params?: { [name: string]: Param }, - vertex: string, - fragment: string + vertex: string | VertexShaderFetcher, + fragment: string | FragmentShaderFetcher } // TODO(#58): add params to all of the filters @@ -69,174 +69,20 @@ const filters: {[name: string]: Filter} = { "step": 1.0, } }, - "vertex": `#version 100 -precision mediump float; - -attribute vec2 meshPosition; -uniform float time; -uniform vec2 emoteSize; - -uniform float interval; -uniform float ground; -uniform float scale; -uniform float jump_height; -uniform float hops; - -varying vec2 uv; - -float sliding_from_left_to_right(float time_interval) { - return (mod(time, time_interval) - time_interval * 0.5) / (time_interval * 0.5); -} - -float flipping_directions(float time_interval) { - return 1.0 - 2.0 * mod(floor(time / time_interval), 2.0); -} - -void main() { - float x_time_interval = interval; - float y_time_interval = x_time_interval / (2.0 * hops); - vec2 offset = vec2( - sliding_from_left_to_right(x_time_interval) * flipping_directions(x_time_interval) * (1.0 - scale), - ((sliding_from_left_to_right(y_time_interval) * flipping_directions(y_time_interval) + 1.0) / jump_height) - ground); - - gl_Position = vec4( - meshPosition * scale + offset, - 0.0, - 1.0); - - uv = (meshPosition + vec2(1.0, 1.0)) / 2.0; - - uv.x = (flipping_directions(x_time_interval) + 1.0) / 2.0 - uv.x * flipping_directions(x_time_interval); -} -`, - "fragment": `#version 100 - -precision mediump float; - -uniform vec2 resolution; -uniform float time; - -uniform sampler2D emote; - -varying vec2 uv; - -void main() { - gl_FragColor = texture2D(emote, vec2(uv.x, 1.0 - uv.y)); - gl_FragColor.w = floor(gl_FragColor.w + 0.5); -} -` + "vertex": new VertexShaderFetcher("Hop"), + "fragment": new FragmentShaderFetcher("Hop"), }, "Hopper": { "transparent": 0x00FF00 + "", "duration": "0.85", - "vertex": `#version 100 -precision mediump float; - -attribute vec2 meshPosition; -uniform float time; - -varying vec2 uv; - -float sliding_from_left_to_right(float time_interval) { - return (mod(time, time_interval) - time_interval * 0.5) / (time_interval * 0.5); -} - -float flipping_directions(float time_interval) { - return 1.0 - 2.0 * mod(floor(time / time_interval), 2.0); -} - -void main() { - float scale = 0.40; - float hops = 2.0; - float x_time_interval = 0.85 / 2.0; - float y_time_interval = x_time_interval / (2.0 * hops); - float height = 0.5; - vec2 offset = vec2( - sliding_from_left_to_right(x_time_interval) * flipping_directions(x_time_interval) * (1.0 - scale), - ((sliding_from_left_to_right(y_time_interval) * flipping_directions(y_time_interval) + 1.0) / 4.0) - height); - - gl_Position = vec4( - meshPosition * scale + offset, - 0.0, - 1.0); - - uv = (meshPosition + vec2(1.0, 1.0)) / 2.0; - - uv.x = (flipping_directions(x_time_interval) + 1.0) / 2.0 - uv.x * flipping_directions(x_time_interval); -} -`, - "fragment": `#version 100 - -precision mediump float; - -uniform vec2 resolution; -uniform float time; - -uniform sampler2D emote; - -varying vec2 uv; - -void main() { - gl_FragColor = texture2D(emote, vec2(uv.x, 1.0 - uv.y)); - gl_FragColor.w = floor(gl_FragColor.w + 0.5); -} -` + "vertex": new VertexShaderFetcher("Hopper"), + "fragment": new FragmentShaderFetcher("Hopper"), }, "Overheat": { "transparent": 0x00FF00 + "", "duration": "0.85 / 8.0 * 2.0", - "vertex": `#version 100 -precision mediump float; - -attribute vec2 meshPosition; -uniform float time; - -varying vec2 uv; - -float sliding_from_left_to_right(float time_interval) { - return (mod(time, time_interval) - time_interval * 0.5) / (time_interval * 0.5); -} - -float flipping_directions(float time_interval) { - return 1.0 - 2.0 * mod(floor(time / time_interval), 2.0); -} - -void main() { - float scale = 0.40; - float hops = 2.0; - float x_time_interval = 0.85 / 8.0; - float y_time_interval = x_time_interval / (2.0 * hops); - float height = 0.5; - vec2 offset = vec2( - sliding_from_left_to_right(x_time_interval) * flipping_directions(x_time_interval) * (1.0 - scale), - ((sliding_from_left_to_right(y_time_interval) * flipping_directions(y_time_interval) + 1.0) / 4.0) - height); - - gl_Position = vec4( - meshPosition * scale + offset, - 0.0, - 1.0); - - uv = (meshPosition + vec2(1.0, 1.0)) / 2.0; - - uv.x = (flipping_directions(x_time_interval) + 1.0) / 2.0 - uv.x * flipping_directions(x_time_interval); -} -`, - "fragment": `#version 100 - -precision mediump float; - -uniform vec2 resolution; -uniform float time; - -uniform sampler2D emote; - -varying vec2 uv; - -void main() { - gl_FragColor = texture2D(emote, vec2(uv.x, 1.0 - uv.y)) * vec4(1.0, 0.0, 0.0, 1.0); - gl_FragColor.w = floor(gl_FragColor.w + 0.5); -} -` + "vertex": new VertexShaderFetcher("Overheat"), + "fragment": new FragmentShaderFetcher("Overheat"), }, "Bounce": { "transparent": 0x00FF00 + "", @@ -257,405 +103,56 @@ void main() { "step": 0.01, } }, - "vertex": `#version 100 -precision mediump float; - -attribute vec2 meshPosition; - -uniform vec2 resolution; -uniform float time; - -uniform float period; -uniform float scale; - -varying vec2 uv; - -void main() { - vec2 offset = vec2(0.0, (2.0 * abs(sin(time * period)) - 1.0) * (1.0 - scale)); - gl_Position = vec4(meshPosition * scale + offset, 0.0, 1.0); - uv = (meshPosition + 1.0) / 2.0; -} -`, - "fragment": ` -#version 100 - -precision mediump float; - -uniform vec2 resolution; -uniform float time; - -uniform sampler2D emote; - -varying vec2 uv; - -void main() { - gl_FragColor = texture2D(emote, vec2(uv.x, 1.0 - uv.y)); - gl_FragColor.w = floor(gl_FragColor.w + 0.5); -} -`, + "vertex": new VertexShaderFetcher("Bounce"), + "fragment": new FragmentShaderFetcher("Bounce"), }, "Circle": { "transparent": 0x00FF00 + "", "duration": "Math.PI / 4.0", - "vertex": `#version 100 -precision mediump float; - -attribute vec2 meshPosition; - -uniform vec2 resolution; -uniform float time; - -varying vec2 uv; - -vec2 rotate(vec2 v, float a) { - float s = sin(a); - float c = cos(a); - mat2 m = mat2(c, -s, s, c); - return m * v; -} - -void main() { - float scale = 0.30; - float period_interval = 8.0; - float pi = 3.141592653589793238; - vec2 outer_circle = vec2(cos(period_interval * time), sin(period_interval * time)) * (1.0 - scale); - vec2 inner_circle = rotate(meshPosition * scale, (-period_interval * time) + pi / 2.0); - gl_Position = vec4( - inner_circle + outer_circle, - 0.0, - 1.0); - uv = (meshPosition + 1.0) / 2.0; -} -`, - "fragment": ` -#version 100 - -precision mediump float; - -uniform vec2 resolution; -uniform float time; - -uniform sampler2D emote; - -varying vec2 uv; - -void main() { - float speed = 1.0; - gl_FragColor = texture2D(emote, vec2(uv.x, 1.0 - uv.y)); - gl_FragColor.w = floor(gl_FragColor.w + 0.5); -} -`, + "vertex": new VertexShaderFetcher("Circle"), + "fragment": new FragmentShaderFetcher("Circle"), }, "Slide": { "transparent": 0x00FF00 + "", "duration": "0.85 * 2", - "vertex": `#version 100 -precision mediump float; - -attribute vec2 meshPosition; -uniform float time; - -varying vec2 uv; - -float sliding_from_left_to_right(float time_interval) { - return (mod(time, time_interval) - time_interval * 0.5) / (time_interval * 0.5); -} - -float flipping_directions(float time_interval) { - return 1.0 - 2.0 * mod(floor(time / time_interval), 2.0); -} - -void main() { - float scale = 0.40; - float hops = 2.0; - float x_time_interval = 0.85; - float y_time_interval = x_time_interval / (2.0 * hops); - float height = 0.5; - vec2 offset = vec2( - sliding_from_left_to_right(x_time_interval) * flipping_directions(x_time_interval) * (1.0 - scale), - - height); - - gl_Position = vec4( - meshPosition * scale + offset, - 0.0, - 1.0); - - uv = (meshPosition + vec2(1.0, 1.0)) / 2.0; - - uv.x = (flipping_directions(x_time_interval) + 1.0) / 2.0 - uv.x * flipping_directions(x_time_interval); -} -`, - "fragment": `#version 100 - -precision mediump float; - -uniform vec2 resolution; -uniform float time; - -uniform sampler2D emote; - -varying vec2 uv; - -void main() { - gl_FragColor = texture2D(emote, vec2(uv.x, 1.0 - uv.y)); - gl_FragColor.w = floor(gl_FragColor.w + 0.5); -} -` + "vertex": new VertexShaderFetcher("Slide"), + "fragment": new FragmentShaderFetcher("Slide"), }, "Laughing": { "transparent": 0x00FF00 + "", "duration": "Math.PI / 12.0", - "vertex": `#version 100 -precision mediump float; - -attribute vec2 meshPosition; -uniform float time; - -varying vec2 uv; - -void main() { - float a = 0.3; - float t = (sin(24.0 * time) * a + a) / 2.0; - - gl_Position = vec4( - meshPosition - vec2(0.0, t), - 0.0, - 1.0); - uv = (meshPosition + vec2(1.0, 1.0)) / 2.0; -} -`, - "fragment": `#version 100 - -precision mediump float; - -uniform vec2 resolution; -uniform float time; - -uniform sampler2D emote; - -varying vec2 uv; - -void main() { - gl_FragColor = texture2D(emote, vec2(uv.x, 1.0 - uv.y)); - gl_FragColor.w = floor(gl_FragColor.w + 0.5); -} -` + "vertex": new VertexShaderFetcher("Laughing"), + "fragment": new FragmentShaderFetcher("Laughing"), }, "Blob": { "transparent": 0x00FF00 + "", "duration": "Math.PI / 3", - "vertex": `#version 100 - -precision mediump float; - -attribute vec2 meshPosition; - -uniform vec2 resolution; -uniform float time; - -varying vec2 uv; - -void main() { - float stretch = sin(6.0 * time) * 0.5 + 1.0; - - vec2 offset = vec2(0.0, 1.0 - stretch); - gl_Position = vec4( - meshPosition * vec2(stretch, 2.0 - stretch) + offset, - 0.0, - 1.0); - uv = (meshPosition + vec2(1.0, 1.0)) / 2.0; -} -`, - "fragment": `#version 100 - -precision mediump float; - -uniform vec2 resolution; -uniform float time; - -uniform sampler2D emote; - -varying vec2 uv; - -void main() { - gl_FragColor = texture2D(emote, vec2(uv.x, 1.0 - uv.y)); - gl_FragColor.w = floor(gl_FragColor.w + 0.5); -} -` + "vertex": new VertexShaderFetcher("Blob"), + "fragment": new FragmentShaderFetcher("Blob"), }, "Go": { "transparent": 0x00FF00 + "", "duration": "1 / 4", - "vertex": `#version 100 -precision mediump float; - -attribute vec2 meshPosition; - -uniform vec2 resolution; -uniform float time; - -varying vec2 uv; - -void main() { - gl_Position = vec4(meshPosition, 0.0, 1.0); - uv = (meshPosition + 1.0) / 2.0; -} -`, - "fragment": ` -#version 100 - -precision mediump float; - -uniform vec2 resolution; -uniform float time; - -uniform sampler2D emote; - -varying vec2 uv; - -float slide(float speed, float value) { - return mod(value - speed * time, 1.0); -} - -void main() { - float speed = 4.0; - gl_FragColor = texture2D(emote, vec2(slide(speed, uv.x), 1.0 - uv.y)); - gl_FragColor.w = floor(gl_FragColor.w + 0.5); -} -`, + "vertex": new VertexShaderFetcher("Go"), + "fragment": new FragmentShaderFetcher("Go"), }, "Elevator": { "transparent": 0x00FF00 + "", "duration": "1 / 4", - "vertex": `#version 100 -precision mediump float; - -attribute vec2 meshPosition; - -uniform vec2 resolution; -uniform float time; - -varying vec2 uv; - -void main() { - gl_Position = vec4(meshPosition, 0.0, 1.0); - uv = (meshPosition + 1.0) / 2.0; -} -`, - "fragment": ` -#version 100 - -precision mediump float; - -uniform vec2 resolution; -uniform float time; - -uniform sampler2D emote; - -varying vec2 uv; - -float slide(float speed, float value) { - return mod(value - speed * time, 1.0); -} - -void main() { - float speed = 4.0; - gl_FragColor = texture2D( - emote, - vec2(uv.x, slide(speed, 1.0 - uv.y))); - gl_FragColor.w = floor(gl_FragColor.w + 0.5); -} -`, + "vertex": new VertexShaderFetcher("Elevator"), + "fragment": new FragmentShaderFetcher("Elevator"), }, "Rain": { "transparent": 0x00FF00 + "", "duration": "1", - "vertex": `#version 100 -precision mediump float; - -attribute vec2 meshPosition; - -uniform vec2 resolution; -uniform float time; - -varying vec2 uv; - -void main() { - gl_Position = vec4(meshPosition, 0.0, 1.0); - uv = (meshPosition + 1.0) / 2.0; -} -`, - "fragment": ` -#version 100 - -precision mediump float; - -uniform vec2 resolution; -uniform float time; - -uniform sampler2D emote; - -varying vec2 uv; - -float slide(float speed, float value) { - return mod(value - speed * time, 1.0); -} - -void main() { - float speed = 1.0; - gl_FragColor = texture2D( - emote, - vec2(mod(4.0 * slide(speed, uv.x), 1.0), - mod(4.0 * slide(speed, 1.0 - uv.y), 1.0))); - gl_FragColor.w = floor(gl_FragColor.w + 0.5); -} -`, + "vertex": new VertexShaderFetcher("Rain"), + "fragment": new FragmentShaderFetcher("Rain"), }, "Pride": { "transparent": null, "duration": "2.0", - "vertex": `#version 100 -precision mediump float; - -attribute vec2 meshPosition; - -uniform vec2 resolution; -uniform float time; - -varying vec2 uv; - -void main() { - gl_Position = vec4(meshPosition, 0.0, 1.0); - uv = (meshPosition + 1.0) / 2.0; -} -`, - "fragment": ` -#version 100 - -precision mediump float; - -uniform vec2 resolution; -uniform float time; - -uniform sampler2D emote; - -varying vec2 uv; - -vec3 hsl2rgb(vec3 c) { - vec3 rgb = clamp(abs(mod(c.x*6.0+vec3(0.0,4.0,2.0),6.0)-3.0)-1.0, 0.0, 1.0); - return c.z + c.y * (rgb-0.5)*(1.0-abs(2.0*c.z-1.0)); -} - -void main() { - float speed = 1.0; - - vec4 pixel = texture2D(emote, vec2(uv.x, 1.0 - uv.y)); - pixel.w = floor(pixel.w + 0.5); - pixel = vec4(mix(vec3(1.0), pixel.xyz, pixel.w), 1.0); - vec4 rainbow = vec4(hsl2rgb(vec3((time - uv.x - uv.y) * 0.5, 1.0, 0.80)), 1.0); - gl_FragColor = pixel * rainbow; -} -`, + "vertex": new VertexShaderFetcher("Pride"), + "fragment": new FragmentShaderFetcher("Pride"), }, "Hard": { "transparent": 0x00FF00 + "", @@ -683,259 +180,26 @@ void main() { "step": 0.001, }, }, - "vertex": `#version 100 -precision mediump float; - -attribute vec2 meshPosition; - -uniform vec2 resolution; -uniform float time; - -uniform float zoom; -uniform float intensity; -uniform float amplitude; - -varying vec2 uv; - -void main() { - vec2 shaking = vec2(cos(intensity * time), sin(intensity * time)) * amplitude; - gl_Position = vec4(meshPosition * zoom + shaking, 0.0, 1.0); - uv = (meshPosition + 1.0) / 2.0; -} -`, - "fragment": ` -#version 100 - -precision mediump float; - -uniform vec2 resolution; -uniform float time; - -uniform sampler2D emote; - -varying vec2 uv; - -void main() { - gl_FragColor = texture2D(emote, vec2(uv.x, 1.0 - uv.y)); - gl_FragColor.w = floor(gl_FragColor.w + 0.5); -} -`, + "vertex": new VertexShaderFetcher("Hard"), + "fragment": new FragmentShaderFetcher("Hard"), }, "Peek":{ "transparent": 0x00FF00 + "", "duration": "2.0 * Math.PI" , - "vertex": `#version 100 -precision mediump float; - -attribute vec2 meshPosition; - -uniform vec2 resolution; -uniform float time; - -varying vec2 uv; - -void main() { - float time_clipped= mod(time * 2.0, (4.0 * 3.14)); - - float s1 = float(time_clipped < (2.0 * 3.14)); - float s2 = 1.0 - s1; - - float hold1 = float(time_clipped > (0.5 * 3.14) && time_clipped < (2.0 * 3.14)); - float hold2 = 1.0 - float(time_clipped > (2.5 * 3.14) && time_clipped < (4.0 * 3.14)); - - float cycle_1 = 1.0 - ((s1 * sin(time_clipped) * (1.0 - hold1)) + hold1); - float cycle_2 = s2 * hold2 * (sin(time_clipped) - 1.0); - - gl_Position = vec4(meshPosition.x + 1.0 + cycle_1 + cycle_2 , meshPosition.y, 0.0, 1.0); - uv = (meshPosition + 1.0) / 2.0; -} -`, - "fragment": ` -#version 100 - -precision mediump float; - -uniform vec2 resolution; -uniform float time; - -uniform sampler2D emote; - -varying vec2 uv; - -void main() { - gl_FragColor = texture2D(emote, vec2(uv.x, 1.0 - uv.y)); - gl_FragColor.w = floor(gl_FragColor.w + 0.5); -} -`, + "vertex": new VertexShaderFetcher("Peek"), + "fragment": new FragmentShaderFetcher("Peek"), }, "Matrix": { "transparent": null, "duration": "3.0", - "vertex":` - #version 100 - precision mediump float; - - attribute vec2 meshPosition; - - uniform vec2 resolution; - uniform float time; - - varying vec2 _uv; - - void main() - { - _uv = (meshPosition + 1.0) / 2.0; - gl_Position = vec4(meshPosition.x, meshPosition.y, 0.0, 1.0); - } - `, - "fragment": ` - #version 100 - precision mediump float; - - uniform vec2 resolution; - uniform float time; - uniform sampler2D emote; - - varying vec2 _uv; - - float clamp01(float value) - { - return clamp(value, 0.0, 1.0); - } - - float sdf_zero(vec2 uv) - { - float inside = step(0.15, abs(uv.x)) + step(0.3, abs(uv.y)); - float outside = step(0.35, abs(uv.x)) + step(0.4, abs(uv.y)); - return clamp01(inside) - clamp01(outside); - } - - float sdf_one(vec2 uv) - { - float top = step(0.25, -uv.y) * step(0.0, uv.x); - float inside = (step(0.2, uv.x) + top); - float outside = step(0.35, abs(uv.x)) + step(0.4, abs(uv.y)); - return clamp01(clamp01(inside) - clamp01(outside)); - } - - // Random float. No precomputed gradients mean this works for any number of grid coordinates - float random01(vec2 n) - { - float random = 2920.0 * sin(n.x * 21942.0 + n.y * 171324.0 + 8912.0) * - cos(n.x * 23157.0 * n.y * 217832.0 + 9758.0); - - return (sin(random) + 1.0) / 2.0; - } - - float loop_time(float time_frame) - { - float times = floor(time / time_frame); - return time - (times * time_frame); - } - - void main() - { - vec2 uv = _uv; - uv.y = 1.0 - _uv.y; - - float number_of_numbers = 8.0; - float number_change_rate = 2.0; - float amount_of_numbers = 0.6; // from 0 - 1 - - vec4 texture_color = texture2D(emote, uv); - vec4 number_color = vec4(0, 0.7, 0, 1); - - float looped_time = loop_time(3.0); - - vec2 translation = vec2(0, looped_time * -8.0); - - vec2 pos_idx = floor(uv * number_of_numbers + translation); - float rnd_number = step(0.5, random01(pos_idx + floor(looped_time * number_change_rate))); - float rnd_show = step(1.0 - amount_of_numbers, random01(pos_idx + vec2(99,99))); - - vec2 nuv = uv * number_of_numbers + translation; - nuv = fract(nuv); - - float one = sdf_one(nuv - 0.5) * rnd_number; - float zero = sdf_zero(nuv - 0.5) * (1.0 - rnd_number); - float number = (one + zero) * rnd_show; - - float is_texture = 1.0 - number; - float is_number = number; - - vec4 col = (texture_color * is_texture) + (number_color * is_number); - - gl_FragColor = col; - gl_FragColor.w = 1.0; - } - ` + "vertex": new VertexShaderFetcher("Matrix"), + "fragment": new FragmentShaderFetcher("Matrix"), }, "Flag":{ "transparent": 0x00FF00 + "", "duration": "Math.PI", - "vertex":` - #version 100 - precision mediump float; - - attribute vec2 meshPosition; - - uniform vec2 resolution; - uniform float time; - - varying vec2 _uv; - - void main() - { - _uv = (meshPosition + 1.0) / 2.0; - _uv.y = 1.0 - _uv.y; - gl_Position = vec4(meshPosition.x, meshPosition.y, 0.0, 1.0); - } - `, - "fragment" :` - #version 100 - precision mediump float; - - varying vec2 _uv; - uniform sampler2D emote; - uniform float time; - - float sin01(float value) - { - return (sin(value) + 1.0) / 2.0; - } - - //pos is left bottom point. - float sdf_rect(vec2 pos, vec2 size, vec2 uv) - { - float left = pos.x; - float right = pos.x + size.x; - float bottom = pos.y; - float top = pos.y + size.y; - return (step(bottom, uv.y) - step(top, uv.y)) * (step(left, uv.x) - step(right, uv.x)); - } - - void main() { - float stick_width = 0.1; - float flag_height = 0.75; - float wave_size = 0.08; - vec4 stick_color = vec4(107.0 / 256.0, 59.0 / 256.0, 9.0 / 256.0,1); - - vec2 flag_uv = _uv; - flag_uv.x = (1.0 / (1.0 - stick_width)) * (flag_uv.x - stick_width); - flag_uv.y *= 1.0 / flag_height; - - float flag_close_to_stick = smoothstep(0.0, 0.5, flag_uv.x); - flag_uv.y += sin((-time * 2.0) + (flag_uv.x * 8.0)) * flag_close_to_stick * wave_size; - - float is_flag = sdf_rect(vec2(0,0), vec2(1.0, 1.0), flag_uv); - float is_flag_stick = sdf_rect(vec2(0.0, 0.0), vec2(stick_width, 1), _uv); - - vec4 emote_color = texture2D(emote, flag_uv); - vec4 texture_color = (emote_color * is_flag) + (stick_color * is_flag_stick); - - gl_FragColor = texture_color; - } - ` + "vertex": new VertexShaderFetcher("Flag"), + "fragment": new FragmentShaderFetcher("Flag"), }, "Thanosed": { "transparent": 0x00FF00 + "", @@ -963,58 +227,8 @@ void main() { "step": 1.0, }, }, - "vertex": `#version 100 -precision mediump float; - -attribute vec2 meshPosition; - -uniform vec2 resolution; -uniform float time; - -varying vec2 uv; - -void main() { - gl_Position = vec4(meshPosition, 0.0, 1.0); - uv = (meshPosition + 1.0) / 2.0; -} -`, - "fragment": ` -#version 100 - -precision mediump float; - -uniform vec2 resolution; -uniform float time; -uniform float duration; -uniform float delay; -uniform float pixelization; - -uniform sampler2D emote; - -varying vec2 uv; - -// https://www.aussiedwarf.com/2017/05/09/Random10Bit.html -float rand(vec2 co){ - vec3 product = vec3( sin( dot(co, vec2(0.129898,0.78233))), - sin( dot(co, vec2(0.689898,0.23233))), - sin( dot(co, vec2(0.434198,0.51833))) ); - vec3 weighting = vec3(4.37585453723, 2.465973, 3.18438); - return fract(dot(weighting, product)); -} - -void main() { - float pixelated_resolution = 112.0 / pixelization; - vec2 pixelated_uv = floor(uv * pixelated_resolution); - float noise = (rand(pixelated_uv) + 1.0) / 2.0; - float slope = (0.2 + noise * 0.8) * (1.0 - (0.0 + uv.x * 0.5)); - float time_interval = 1.1 + delay * 2.0; - float progress = 0.2 + delay + slope - mod(time_interval * time / duration, time_interval); - float mask = progress > 0.1 ? 1.0 : 0.0; - vec4 pixel = texture2D(emote, vec2(uv.x * (progress > 0.5 ? 1.0 : progress * 2.0), 1.0 - uv.y)); - pixel.w = floor(pixel.w + 0.5); - gl_FragColor = pixel * vec4(vec3(1.0), mask); -} -`, + "vertex": new VertexShaderFetcher("Thanosed"), + "fragment": new FragmentShaderFetcher("Thanosed"), }, "Ripple": { "transparent": 0x00FF00 + "", @@ -1045,46 +259,7 @@ void main() { "step": 0.01, } }, - "vertex": `#version 100 -precision mediump float; - -attribute vec2 meshPosition; - -uniform vec2 resolution; -uniform float time; - -varying vec2 uv; - -void main() { - gl_Position = vec4(meshPosition, 0.0, 1.0); - uv = (meshPosition + 1.0) / 2.0; -} -`, - "fragment": `#version 100 - -precision mediump float; - -uniform vec2 resolution; -uniform float time; - -uniform sampler2D emote; - -uniform float a; -uniform float b; -uniform float c; - -varying vec2 uv; - -void main() { - vec2 pos = vec2(uv.x, 1.0 - uv.y); - vec2 center = vec2(0.5); - vec2 dir = pos - center; - float x = length(dir); - float y = sin(x + time); - vec4 pixel = texture2D(emote, pos + cos(x*a - time*b)*c*(dir/x)); - gl_FragColor = pixel; - gl_FragColor.w = floor(gl_FragColor.w + 0.5); -} -`, + "vertex": new VertexShaderFetcher("Ripple"), + "fragment": new FragmentShaderFetcher("Ripple"), } }; diff --git a/ts/index.ts b/ts/index.ts index 4c8abf2..277da4e 100644 --- a/ts/index.ts +++ b/ts/index.ts @@ -102,9 +102,13 @@ interface Snapshot { } // TODO(#54): pre-load all of the filters and just switch between them without loading/unloading them constantly +// TODO Deprecate string and move to fetchers +// TODO move to async version of fetchers function loadFilterProgram(gl: WebGLRenderingContext, filter: Filter, vertexAttribs: VertexAttribs): CompiledFilter { - let vertexShader = compileShaderSource(gl, filter.vertex, gl.VERTEX_SHADER); - let fragmentShader = compileShaderSource(gl, filter.fragment, gl.FRAGMENT_SHADER); + let vertexShaderSource = filter.vertex instanceof VertexShaderFetcher ? filter.vertex.GetShader() : filter.vertex; + let fragmentShaderSource = filter.fragment instanceof FragmentShaderFetcher ? filter.fragment.GetShader() : filter.fragment; + let vertexShader = compileShaderSource(gl, vertexShaderSource, gl.VERTEX_SHADER); + let fragmentShader = compileShaderSource(gl, fragmentShaderSource, gl.FRAGMENT_SHADER); let id = linkShaderProgram(gl, [vertexShader, fragmentShader], vertexAttribs); gl.deleteShader(vertexShader); gl.deleteShader(fragmentShader);