├── .editorconfig ├── .eslintrc ├── .gitattributes ├── .gitignore ├── .jshintrc ├── LICENSE ├── README.md ├── TODO.md ├── env.config.js ├── package-lock.json ├── package.json ├── project.json ├── src ├── components │ ├── rgba-material │ │ ├── index.js │ │ ├── rgba.frag │ │ └── rgba.vert │ └── texture-combine │ │ ├── index.js │ │ └── styles.js ├── index.html ├── index.js ├── lib │ ├── component.js │ ├── lit-ref.js │ └── ticker.js └── style │ ├── index.js │ └── mixins.js ├── webpack.config.js └── webpack ├── common.config.js ├── dev.config.js └── prod.config.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 4 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | 15 | [Makefile] 16 | indent_style = tab 17 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "node": true, 4 | "browser": true 5 | }, 6 | 7 | "globals": { 8 | "dmaf": true, 9 | "createjs": true 10 | }, 11 | 12 | "rules": { 13 | "no-comma-dangle": 1, 14 | "no-cond-assign" : 1, 15 | "no-constant-condition": 1, 16 | "no-control-regex": 1, 17 | "no-debugger": 1, 18 | "no-dupe-keys": 1, 19 | "no-empty": 0, 20 | "no-empty-class": 1, 21 | "no-ex-assign": 1, 22 | "no-extra-boolean-cast": 0, 23 | "no-extra-parens": 0, 24 | "no-extra-semi": 1, 25 | "no-func-assign": 1, 26 | "no-inner-declarations": 0, 27 | "no-invalid-regexp": 1, 28 | "no-irregular-whitespace": 1, 29 | "no-negated-in-lhs": 1, 30 | "no-obj-calls": 1, 31 | "no-regex-spaces": 1, 32 | "no-reserved-keys": 1, 33 | "no-sparse-arrays": 1, 34 | "no-unreachable": 1, 35 | "no-use-before-define": 0, 36 | "use-isnan": 1, 37 | "valid-jsdoc": 0, 38 | "valid-typeof": 1, 39 | "space-unary-ops": [1, {"words": true, "nonwords": false}], 40 | 41 | "camelcase": 1, 42 | "curly": 0, 43 | "comma-spacing": [2, {"before": false, "after": true}], 44 | "comma-style": [2, "last"], 45 | "eol-last": 1, 46 | "func-names": 0, 47 | "func-style": 1, 48 | "key-spacing": [2, {"beforeColon": false, "afterColon": true}], 49 | "max-nested-callbacks": 0, 50 | "new-cap": 1, 51 | "new-parens": 1, 52 | "no-array-constructor": 1, 53 | "no-lonely-if": 0, 54 | "no-mixed-spaces-and-tabs": 1, 55 | "no-nested-ternary": 0, 56 | "no-new": 0, 57 | "no-new-object": 1, 58 | "no-space-before-semi": 1, 59 | "no-spaced-func": 1, 60 | "no-ternary": 0, 61 | "no-trailing-spaces": 1, 62 | "no-multiple-empty-lines": [1, {"max": 2}], 63 | "no-underscore-dangle": 0, 64 | "no-wrap-func": 1, 65 | "no-path-concat": 0, 66 | "one-var": 0, 67 | "no-unused-expressions": 0, 68 | "padded-blocks": "never", 69 | "quotes": [2, "single"], 70 | "quote-props": "as-needed", 71 | "semi": 1, 72 | "space-after-keywords": [1, "always"], 73 | "space-before-blocks": [1, "always"], 74 | "space-in-brackets": [2, "never"], 75 | "space-in-parens": [2, "never"], 76 | "space-infix-ops": 1, 77 | "space-return-throw-case": 1, 78 | "spaced-line-comment": ["always", {"exceptions": ["-","+"]}], 79 | "wrap-regex": 0, 80 | "max-params": [1, 3], 81 | "yoda": "never" 82 | } 83 | } -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set the default behavior, in case people don't have core.autocrlf set. 2 | * text eol=lf 3 | # Denote all files that are truly binary and should not be modified. 4 | *.png binary 5 | *.jpg binary 6 | *.gif binary 7 | *.ttf binary 8 | *.woff binary 9 | *.woff2 binary 10 | *.eot binary 11 | *.ico binary 12 | *.mp4 binary 13 | *.m4a binary 14 | *.mp3 binary 15 | *.webm binary 16 | *.ogg binary 17 | *.ogv binary 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .linaria-cache/ 3 | static/build 4 | static/assets 5 | static/index.* 6 | static/index 7 | node_modules/* 8 | npm-debug.log 9 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | // Settings 3 | "passfail" : false, // Stop on first error. 4 | "maxerr" : 100, // Maximum errors before stopping. 5 | 6 | 7 | // Predefined globals whom JSHint will ignore. 8 | "browser" : true, // Standard browser globals e.g. `window`, `document`. 9 | 10 | "node" : true, 11 | 12 | "predef" : [ // Extra globals. 13 | "require", 14 | "TweenLite", 15 | "TimelineMax", 16 | ], 17 | "globals": { 18 | //GSAP Globals 19 | "Back" : false, 20 | "Bounce" : false, 21 | "Circ" : false, 22 | "Cubic" : false, 23 | "Ease" : false, 24 | "EaseLookup" : false, 25 | "Elastic" : false, 26 | "Expo" : false, 27 | "Linear" : false, 28 | "Power0" : false, 29 | "Power1" : false, 30 | "Power2" : false, 31 | "Power3" : false, 32 | "Power3" : false, 33 | "Power4" : false, 34 | "Quad" : false, 35 | "Quart" : false, 36 | "Quint" : false, 37 | "RoughEase" : false, 38 | "Sine" : false, 39 | "SlowMo" : false, 40 | "SteppedEase" : false, 41 | "Strong" : false, 42 | "Draggable" : false, 43 | "SplitText" : false, 44 | "TimelineMax" : false, 45 | "VelocityTracker" : false, 46 | "CSSPlugin" : false, 47 | "ThrowPropsPlugin" : false, 48 | "BezierPlugin" : false 49 | }, 50 | 51 | 52 | // Development. 53 | "debug" : false, // Allow debugger statements e.g. browser breakpoints. 54 | "devel" : true, // Allow development statements e.g. `console.log();`. 55 | 56 | 57 | // EcmaScript 5. 58 | "es5" : true, // Allow EcmaScript 5 syntax. 59 | "strict" : false, // Require `use strict` pragma in every file. 60 | "globalstrict" : false, // Allow global "use strict" (also enables 'strict'). 61 | 62 | 63 | // The Good Parts. 64 | "asi" : false, // Tolerate Automatic Semicolon Insertion (no semicolons). 65 | "laxbreak" : false, // Tolerate unsafe line breaks e.g. `return [\n] x` without semicolons. 66 | "bitwise" : true, // Prohibit bitwise operators (&, |, ^, etc.). 67 | "boss" : false, // Tolerate assignments inside if, for & while. Usually conditions & loops are for comparison, not assignments. 68 | "curly" : false, // Require {} for every new block or scope. 69 | "eqeqeq" : false, // Require triple equals i.e. `===`. 70 | "eqnull" : false, // Tolerate use of `== null`. 71 | "evil" : false, // Tolerate use of `eval`. 72 | "expr" : false, // Tolerate `ExpressionStatement` as Programs. 73 | "forin" : true, // Tolerate `for in` loops without `hasOwnPrototype`. 74 | "immed" : true, // Require immediate invocations to be wrapped in parens e.g. `( function(){}() );` 75 | "latedef" : false, // Prohibit variable use before definition. 76 | "loopfunc" : false, // Allow functions to be defined within loops. 77 | "noarg" : true, // Prohibit use of `arguments.caller` and `arguments.callee`. 78 | "regexp" : true, // Prohibit `.` and `[^...]` in regular expressions. 79 | "regexdash" : false, // Tolerate unescaped last dash i.e. `[-...]`. 80 | "scripturl" : true, // Tolerate script-targeted URLs. 81 | "shadow" : false, // Allows re-define variables later in code e.g. `var x=1; x=2;`. 82 | "supernew" : false, // Tolerate `new function () { ... };` and `new Object;`. 83 | "undef" : true, // Require all non-global variables be declared before they are used. 84 | 85 | 86 | // Persone styling prefrences. 87 | "newcap" : false, // Require capitalization of all constructor functions e.g. `new F()`. 88 | "noempty" : false, // Prohibit use of empty blocks. 89 | "nonew" : false, // Prohibit use of constructors for side-effects. 90 | "nomen" : false, // Prohibit use of initial or trailing underbars in names. 91 | "onevar" : false, // Allow only one `var` statement per function. 92 | "plusplus" : false, // Prohibit use of `++` & `--`. 93 | "sub" : true, // Tolerate all forms of subscript notation besides dot notation e.g. `dict['key']` instead of `dict.key`. 94 | "trailing" : false, // Prohibit trailing whitespaces. 95 | "white" : false // Check against strict whitespace and indentation rules. 96 | } 97 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2020 Florian Morel 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | texture-combine 3 | === 4 | 5 | ### A tool to combine different RGB/A channels into a single texture 6 | 7 | > :warning: WIP dead simple for now, more features (and styling) to come 8 | 9 |  10 | 11 | 12 | ### Usage 13 | ``` 14 | git clone https://github.com/ayamflow/texture-combine 15 | cd texture-combine 16 | npm i 17 | npm start 18 | ``` 19 | 20 | Then drag each image onto their respective square (RGB and optionally an Alpha image, which will use the red channel). 21 | Once done, right click on the result image and select "Save image". -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | Stylelint for emotion 2 | https://github.com/webpack-contrib/stylelint-webpack-plugin 3 | linaria fonts?? 4 | 5 | ES5+ES6 6 | https://philipwalton.com/articles/deploying-es2015-code-in-production-today/ 7 | 8 | Store - Flow/VueX/redux/unistore? 9 | 10 | tweens 11 | https://github.com/juliangarnier/anime 12 | https://github.com/nextapps-de/fat 13 | 14 | ////////// 15 | noise/vhs glitch 16 | 17 | http://www.shaderslab.com/images/tvnoise2.jpg?crc=4021489216 18 | 19 | scratches 20 | http://www.nutty.ca/?page_id=352&link=old_film 21 | 22 | https://www.shadertoy.com/view/4dBGzK 23 | https://www.shadertoy.com/view/ldjGzV 24 | https://www.shadertoy.com/view/MlfSWr 25 | 26 | 1/ logo noise 27 | 2/ loading noise 28 | 3/ dragging noise 29 | 30 | videoTexture webgl1 31 | 32 | 33 | ===== 34 | Features 35 | 36 | Home 37 | === 38 | video states: loading/dragging 39 | - add 2 shaders √ 40 | - video playing logic (match currenttime to text %) 41 | - playing √ 42 | - drag √ 43 | - percent and& text width don't match √ 44 | - fast forward to a diff project OK but jumps back to 0 sometimes 45 | - scroll: debounce/throttle/timeout before actually seeking 46 | - fixing jump between videos 47 | - loading logic 48 | - seeking logic 49 | 50 | - video: draw in POT canvas 51 | 52 | on drag: 53 | - pause 54 | - find video id 55 | 56 | hover during animateIn yields black sphere 57 | 58 | -> by default: loading event 59 | on seek: remove loading, add playing 60 | seeking done: remove playing, add loading 61 | 62 | 63 | limit drag/scroll speed 64 | 65 | Misc 66 | === 67 | Mouse shadow: add trail 68 | - improve mouse velocity (appears/fades too fast) 69 | 70 | on visibility API stop/resume video? 71 | - merge texts geoms? 72 | - gpu detect + tweaks 73 | 74 | 75 | 76 | glitch/vhs 77 | 78 | https://www.shadertoy.com/view/XtyXzW 79 | 80 | https://www.shadertoy.com/view/Md3SRM 81 | 82 | https://www.shadertoy.com/view/MtfSz2 83 | 84 | https://www.shadertoy.com/view/WsBGRW 85 | 86 | 87 | gifs references 88 | https://giphy.com/gifs/glitch-vhs-max-capacity-yugSj8GSC0wXm 89 | https://giphy.com/gifs/lamborghini-lambo-countach-l3UcrZHrGW2CjHXqM 90 | https://giphy.com/gifs/vhs-art-11v8gJRwB2fE3u 91 | https://giphy.com/gifs/dance-power-rangers-hap-ki-do-1M2SPVruuneFO 92 | https://giphy.com/gifs/loop-glitch-art-65mCMJDdABFYs 93 | https://giphy.com/gifs/80s-vhs-4JQsNAUUCU3OU -------------------------------------------------------------------------------- /env.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | dev: { 3 | baseURL: '/', 4 | assetsURL: '/assets/' 5 | }, 6 | prod: { 7 | baseURL: '/', 8 | assetsURL: '/assets/' 9 | }, 10 | staging: { 11 | baseURL: '/eien/v2/', 12 | assetsURL: '/eien/v2/assets/' 13 | } 14 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "texture-combine", 3 | "version": "0.0.1", 4 | "description": "A tool to combine different RGB/A channels into a single texture", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "webpack-dev-server --open --env.development", 8 | "build": "npx webpack --env.production", 9 | "build:staging": "npx webpack --env.env=staging --env.production" 10 | }, 11 | "author": "", 12 | "license": "MIT", 13 | "devDependencies": { 14 | "@babel/cli": "^7.4.4", 15 | "@babel/core": "^7.4.5", 16 | "@babel/node": "^7.4.5", 17 | "@babel/plugin-proposal-function-bind": "^7.2.0", 18 | "@babel/plugin-transform-runtime": "^7.4.4", 19 | "@babel/preset-env": "^7.4.5", 20 | "@babel/register": "^7.4.4", 21 | "@babel/runtime": "^7.4.5", 22 | "babel-loader": "^8.0.6", 23 | "babel-minify": "^0.5.0", 24 | "clean-webpack-plugin": "^1.0.1", 25 | "copy-webpack-plugin": "^5.0.3", 26 | "css-hot-loader": "^1.4.4", 27 | "css-loader": "^2.1.1", 28 | "file-loader": "^3.0.1", 29 | "glslify": "^7.0.0", 30 | "glslify-fancy-imports": "^1.0.1", 31 | "glslify-hex": "^2.1.1", 32 | "glslify-import": "^3.1.0", 33 | "html-loader": "^0.5.5", 34 | "html-webpack-plugin": "^3.2.0", 35 | "ify-loader": "^1.1.0", 36 | "lint-staged": "^8.1.7", 37 | "mini-css-extract-plugin": "^0.5.0", 38 | "prettier": "^1.17.1", 39 | "raw-loader": "^1.0.0", 40 | "url-loader": "^1.1.2", 41 | "webpack": "^4.33.0", 42 | "webpack-bundle-analyzer": "^3.3.2", 43 | "webpack-cli": "^3.3.2", 44 | "webpack-dev-server": "^3.6.0", 45 | "webpack-merge": "^4.2.1" 46 | }, 47 | "dependencies": { 48 | "css-reset": "github:watsondg/css-reset", 49 | "linaria": "^1.3.1", 50 | "lit-element": "^2.1.0", 51 | "lit-html": "^1.1.0", 52 | "ogl": "^0.0.11", 53 | "size": "github:ayamflow/size" 54 | }, 55 | "browserify": { 56 | "transform": [ 57 | "glslify" 58 | ] 59 | }, 60 | "glslify": { 61 | "transform": [ 62 | "glslify-hex", 63 | "glslify-import", 64 | "glslify-fancy-imports" 65 | ] 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /project.json: -------------------------------------------------------------------------------- 1 | { 2 | "meta": { 3 | "title": "Texture Combine", 4 | "description": "Combine custom layers into RGB/A textures", 5 | "twitter": "https://www.twitter.com/ayamflow", 6 | "siteURL": "https://ayamflow.fr" 7 | } 8 | } -------------------------------------------------------------------------------- /src/components/rgba-material/index.js: -------------------------------------------------------------------------------- 1 | import {Program, Texture} from 'ogl' 2 | const glslify = require('glslify') 3 | 4 | const CHANNELS = { 5 | RED: 'r', 6 | GREEN: 'g', 7 | BLUE: 'b', 8 | ALPHA: 'a' 9 | } 10 | 11 | export default class RGBAMaterial extends Program { 12 | constructor(gl) { 13 | super(gl, { 14 | uniforms: { 15 | r: { 16 | value: new Texture(gl) 17 | }, 18 | g: { 19 | value: new Texture(gl) 20 | }, 21 | b: { 22 | value: new Texture(gl) 23 | }, 24 | a: { 25 | value: new Texture(gl) 26 | }, 27 | useAlpha: { 28 | value: 0.0 29 | } 30 | }, 31 | vertex: glslify('./rgba.vert'), 32 | fragment: glslify('./rgba.frag'), 33 | transparent: true 34 | }) 35 | } 36 | 37 | setChannel(channel, image) { 38 | let texture = this.uniforms[channel].value 39 | texture.image = image 40 | } 41 | 42 | toggleAlpha(value) { 43 | this.uniforms.useAlpha = value === true ? 1.0 : 0.0; 44 | } 45 | 46 | set r(image) { 47 | this.setChannel(CHANNELS.RED, image) 48 | } 49 | 50 | set g(image) { 51 | this.setChannel(CHANNELS.GREEN, image) 52 | } 53 | 54 | set b(image) { 55 | this.setChannel(CHANNELS.BLUE, image) 56 | } 57 | 58 | set a(image) { 59 | this.setChannel(CHANNELS.ALPHA, image) 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/components/rgba-material/rgba.frag: -------------------------------------------------------------------------------- 1 | precision highp float; 2 | 3 | uniform sampler2D r; 4 | uniform sampler2D g; 5 | uniform sampler2D b; 6 | uniform sampler2D a; 7 | uniform float useAlpha; 8 | varying vec2 vUv; 9 | 10 | void main() { 11 | gl_FragColor = vec4( 12 | texture2D(r, vUv).r, 13 | texture2D(g, vUv).g, 14 | texture2D(b, vUv).b, 15 | useAlpha == 1.0 ? texture2D(a, vUv).r : 1.0 16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /src/components/rgba-material/rgba.vert: -------------------------------------------------------------------------------- 1 | attribute vec2 position; 2 | attribute vec2 uv; 3 | varying vec2 vUv; 4 | 5 | void main() { 6 | vUv = uv; 7 | gl_Position = vec4(position, 0, 1); 8 | } 9 | -------------------------------------------------------------------------------- /src/components/texture-combine/index.js: -------------------------------------------------------------------------------- 1 | import {Component, html} from 'lib/component' 2 | import {Renderer, Geometry, Mesh } from 'ogl' 3 | import {ref} from 'lib/lit-ref' 4 | import Ticker from 'lib/ticker' 5 | import * as styles from './styles' 6 | import RGBAMaterial from '../rgba-material' 7 | 8 | const RENDER_SIZE = 1024 9 | 10 | export default class TextureCombine extends Component { 11 | init() { 12 | this.onUpdate = this.onUpdate.bind(this) 13 | this.onFileLoaded = this.onFileLoaded.bind(this) 14 | } 15 | 16 | render() { 17 | const layers = [ 18 | { channel: 'r', name: 'red'}, 19 | { channel: 'g', name: 'green'}, 20 | { channel: 'b', name: 'blue'}, 21 | { channel: 'a', name: 'alpha'}, 22 | ] 23 | 24 | return html` 25 |