├── .gitignore ├── .npmignore ├── LICENSE.md ├── README.md ├── index.js ├── optimize.js ├── package.json └── test ├── fixture.frag ├── fixture.js └── fixture.vert /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.log 3 | .DS_Store 4 | bundle.js 5 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.log 3 | .DS_Store 4 | bundle.js 5 | test 6 | test.js 7 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | This software is released under the MIT license: 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software is furnished to do so, 8 | subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 15 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 16 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 17 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 18 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # glslify-optimize [![experimental](http://badges.github.io/stability-badges/dist/experimental.svg)](http://github.com/badges/stability-badges) 2 | 3 | A browserify transform stream that optimizes your glslify shaders using 4 | [glsl-optimizer](https://github.com/aras-p/glsl-optimizer), the library 5 | used in Unity for mobile shader optimization. 6 | 7 | ## Usage 8 | 9 | [![NPM](https://nodei.co/npm/glslify-optimize.png)](https://nodei.co/npm/glslify-optimize/) 10 | 11 | Use the `glslify-optimize` transform *after* using `glslify` for it to work 12 | correctly: 13 | 14 | ``` bash 15 | browserify -t glslify -t glslify-optimize 16 | ``` 17 | 18 | ``` javascript 19 | var browserify = require('browserify') 20 | 21 | browserify('index.js') 22 | .transform('glslify') 23 | .transform('glslify-optimize') 24 | .pipe(process.stdout) 25 | ``` 26 | 27 | ## License 28 | 29 | MIT. See [LICENSE.md](http://github.com/hughsk/glslify-optimize/blob/master/LICENSE.md) for details. 30 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var escodegen = require('escodegen') 2 | var optimize = require('./optimize') 3 | var through = require('through2') 4 | var esprima = require('esprima') 5 | var astw = require('astw') 6 | 7 | module.exports = transform 8 | 9 | function debug(){} 10 | if (process.env.DEBUG === 'glslify-optimize') { 11 | debug = console.error 12 | } 13 | 14 | function transform(filename) { 15 | var stream = through(write, flush) 16 | var buffer = [] 17 | 18 | return stream 19 | 20 | function write(chunk, _, next) { 21 | buffer.push(chunk) 22 | next() 23 | } 24 | 25 | function flush() { 26 | var src = buffer.join('') 27 | if (src.indexOf('glslify') === -1) { 28 | this.push(src) 29 | this.push(null) 30 | return 31 | } 32 | 33 | var ast = esprima.parse(src) 34 | var walk = astw(ast) 35 | 36 | debug('Original source:') 37 | debug('\n' + src) 38 | 39 | walk(function(node) { 40 | if (node.type !== 'Literal') return 41 | if (node.value !== 'glslify/adapter.js') return 42 | var parent = node 43 | var callee = node 44 | if (!(parent = parent.parent)) return 45 | if (!(parent = parent.parent)) return 46 | if (!(callee = parent.callee)) return 47 | if (!(callee = callee.callee)) return 48 | if (callee.name !== 'require') return 49 | var args = parent.arguments 50 | if (args.length < 2) return 51 | if (args[0].type !== 'Literal') return 52 | if (args[1].type !== 'Literal') return 53 | 54 | var vert = args[0].value 55 | var frag = args[1].value 56 | 57 | debug('Original fragment shader:') 58 | debug('\n' + frag) 59 | 60 | debug('Original vertex shader:') 61 | debug('\n' + vert) 62 | 63 | frag = optimize.frag(frag) 64 | vert = optimize.vert(vert) 65 | 66 | debug('Optimized vertex shader:') 67 | debug('\n' + vert) 68 | 69 | debug('Optimized fragment shader:') 70 | debug('\n' + frag) 71 | 72 | args[0].value = vert 73 | args[1].value = frag 74 | }) 75 | 76 | this.push(src = escodegen.generate(ast)) 77 | this.push(null) 78 | debug(src) 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /optimize.js: -------------------------------------------------------------------------------- 1 | var glsl = require('mapbox-glsl-optimizer') 2 | 3 | module.exports = { 4 | frag: optimize(glsl.FRAGMENT_SHADER, 'fragment') 5 | , vert: optimize(glsl.VERTEX_SHADER, 'vertex') 6 | } 7 | 8 | var target = glsl.TARGET_OPENGLES20 9 | var compiler = new glsl.Compiler(target) 10 | 11 | function optimize(kind, name) { 12 | return function(source) { 13 | var shader = new glsl.Shader(compiler, kind, source) 14 | if (!shader.compiled()) { 15 | throw new Error('Failed to optimize ' + name + ' shader') 16 | } 17 | 18 | var output = shader.output() 19 | shader.dispose() 20 | 21 | return output 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "glslify-optimize", 3 | "version": "2.0.1", 4 | "description": "A browserify transform stream that optimizes your glslify shaders", 5 | "main": "index.js", 6 | "license": "MIT", 7 | "scripts": { 8 | "test": "DEBUG='glslify-optimize' DEBUG_COLORS=true browserify -t glslify -t ./ test/fixture.js > /dev/null", 9 | "start": "cd test && beefy fixture.js -- -t glslify -t ../" 10 | }, 11 | "author": "Hugh Kennedy (http://hughsk.io/)", 12 | "dependencies": { 13 | "astw": "^1.2.0", 14 | "escodegen": "^1.3.3", 15 | "esprima": "^1.2.2", 16 | "mapbox-glsl-optimizer": "^0.1.1", 17 | "through2": "^0.5.1" 18 | }, 19 | "devDependencies": { 20 | "a-big-triangle": "0.0.0", 21 | "gl-texture2d": "^1.0.1", 22 | "glsl-dither": "^1.0.0", 23 | "gl-context": "^0.1.0", 24 | "glslify": "^1.4.0", 25 | "lena": "^1.0.0" 26 | }, 27 | "repository": { 28 | "type": "git", 29 | "url": "git://github.com/hughsk/glslify-optimize.git" 30 | }, 31 | "keywords": [ 32 | "browserify-transform", 33 | "glsl", 34 | "optimise", 35 | "optimize", 36 | "shader", 37 | "webgl", 38 | "glslify" 39 | ], 40 | "homepage": "https://github.com/hughsk/glslify-optimize", 41 | "bugs": { 42 | "url": "https://github.com/hughsk/glslify-optimize/issues" 43 | }, 44 | "directories": { 45 | "test": "test" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /test/fixture.frag: -------------------------------------------------------------------------------- 1 | precision mediump float; 2 | 3 | uniform sampler2D uTexture; 4 | varying vec2 vUv; 5 | 6 | #pragma glslify: dither = require(glsl-dither) 7 | 8 | void main() { 9 | vec4 color = texture2D(uTexture, vUv); 10 | gl_FragColor = dither(gl_FragCoord.xy, color); 11 | } 12 | -------------------------------------------------------------------------------- /test/fixture.js: -------------------------------------------------------------------------------- 1 | var canvas = document.body.appendChild(document.createElement('canvas')) 2 | var triangle = require('a-big-triangle') 3 | var createTexture = require('gl-texture2d') 4 | var getContext = require('gl-context') 5 | var createShader = require('glslify') 6 | var lena = require('lena') 7 | 8 | canvas.width = 512 9 | canvas.height = 512 10 | 11 | var gl = getContext(canvas, render) 12 | var tex = createTexture(gl, lena) 13 | var shader = createShader({ 14 | vert: './fixture.vert' 15 | , frag: './fixture.frag' 16 | })(gl) 17 | 18 | function render() { 19 | shader.bind() 20 | shader.uniforms.uTexture = tex.bind() 21 | triangle(gl) 22 | } 23 | -------------------------------------------------------------------------------- /test/fixture.vert: -------------------------------------------------------------------------------- 1 | precision mediump float; 2 | 3 | attribute vec2 position; 4 | varying vec2 vUv; 5 | 6 | void main() { 7 | vUv = (position + vec2(1.0)) / 2.0; 8 | vUv.y = 1.0 - vUv.y; 9 | gl_Position = vec4(position, 1.0, 1.0); 10 | } 11 | --------------------------------------------------------------------------------