├── .gitignore ├── .npmignore ├── LICENSE.md ├── README.md ├── demo └── index.js ├── frag.glsl ├── index.js ├── package.json └── vert.glsl /.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 | The MIT License (MIT) 2 | Copyright (c) 2014 Matt DesLauriers 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE 20 | OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # gl-vignette-background 2 | 3 | [![experimental](http://badges.github.io/stability-badges/dist/experimental.svg)](http://github.com/badges/stability-badges) 4 | 5 | Creates a soft gradient background with noise, suitable for your sweet WebGL demos! 6 | 7 | ![demo](http://i.imgur.com/IMRLl9D.png) 8 | 9 | Also see [three-vignette-background](https://github.com/mattdesl/three-vignette-background) for a ThreeJS version of this module, with a slightly different API and noise algorithm. 10 | 11 | ## Install 12 | 13 | ```sh 14 | npm install gl-vignette-background --save 15 | ``` 16 | 17 | ## Example 18 | 19 | ```js 20 | var createBackground = require('gl-vignette-background') 21 | 22 | // get a WebGL canvas 23 | var gl = require('webgl-context')() 24 | 25 | // create your background 26 | var background = createBackground(gl) 27 | 28 | function render () { 29 | var width = gl.drawingBufferWidth 30 | var height = gl.drawingBufferHeight 31 | 32 | gl.viewport(0, 0, width, height) 33 | gl.clearColor(0, 0, 0, 1) 34 | 35 | // set some flags before drawing 36 | gl.clear(gl.COLOR_BUFFER_BIT) 37 | gl.disable(gl.DEPTH_TEST) 38 | gl.disable(gl.CULL_FACE) 39 | 40 | // setup some fancy style (optional) 41 | var radius = Math.max(width, height) * 1.05 42 | background.style({ 43 | // xy scale 44 | scale: [ 1 / width * radius, 1 / height * radius ], 45 | // aspect ratio for vignette 46 | aspect: 1, 47 | // radial gradient colors A->B 48 | color1: [ 1, 1, 1 ], 49 | color2: [ 0.5, 0.5, 0.5 ], 50 | // smoothstep low/high input 51 | smoothing: [ -0.5, 1.0 ], 52 | // % opacity of noise grain (0 -> disabled) 53 | noiseAlpha: 0.35, 54 | // whether or not the noise is monochromatic 55 | coloredNoise: true, 56 | // offset the vignette 57 | offset: [ -0.05, -0.15 ] 58 | }) 59 | background.draw() 60 | } 61 | ``` 62 | 63 | See [demo/index.js](demo/index.js) for a full-screen example. 64 | 65 | ## Usage 66 | 67 | [![NPM](https://nodei.co/npm/gl-vignette-background.png)](https://nodei.co/npm/gl-vignette-background/) 68 | 69 | ### ```var bg = createBackground(gl [, style])``` 70 | 71 | Creates a background quad with some default options (bright and soft white gradient in the center, using the current canvas size for aspect ratio). 72 | 73 | You can provide `style` to override some defaults, e.g: 74 | 75 | ```js 76 | bg = createBackground(gl { 77 | color1: [ 1, 0, 0] 78 | }) 79 | ``` 80 | 81 | See [styling](#styling) 82 | 83 | 84 | ### ```bg.style(options)``` 85 | 86 | Style the background with the given overrides in the specified object. Acts the same as the styling options passed to constructor. 87 | 88 | ### ```bg.draw()``` 89 | 90 | Draws the quad. 91 | 92 | ### ```bg.dispose()``` 93 | 94 | Disposes the quad and its shader. 95 | 96 | ## styling 97 | 98 | The following options are stylable: 99 | 100 | - `aspect`: a float for aspect ratio; typically set whenever the background size changes 101 | - `smoothing`: a vec2 representing the low and high end for the smooth function 102 | - `noiseAlpha`: the opacity of the random noise (set to zero to disable) 103 | - `coloredNoise`: a bool for whether noise is enabled, `1` for chromatic, `0` for monochrome 104 | - `offset`: the position vec2 offset, normalized. `[0, 0]` is center (default), `[-0.5, -0.5]` will be top left 105 | - `scale`: the vec2 amount to scale the gradient, normalized. default is `[1, 1]` 106 | - `color1`: the first `[r, g, b]` color in the gradient, default white 107 | - `color2`: the second `[r, g, b]` color in the gradient, default black 108 | 109 | ## running the demo 110 | 111 | Git clone this repo, run `npm install`, then `npm start` and open `localhost:9966`. 112 | 113 | ## License 114 | 115 | MIT, see [LICENSE.md](http://github.com/mattdesl/gl-vignette-background/blob/master/LICENSE.md) for details. 116 | -------------------------------------------------------------------------------- /demo/index.js: -------------------------------------------------------------------------------- 1 | var hex = require('hex-rgb') 2 | var gl = require('webgl-context')() 3 | var canvas = document.body.appendChild(gl.canvas) 4 | 5 | var app = require('canvas-loop')(canvas, { 6 | scale: 1 7 | }) 8 | 9 | app.on('tick', render) 10 | app.start() 11 | 12 | var background = require('../')(gl) 13 | 14 | function rgb (str) { 15 | return hex(str).map(function (a) { 16 | return a / 255 17 | }) 18 | } 19 | 20 | function render () { 21 | gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight) 22 | gl.clearColor(0, 0, 0, 1) 23 | gl.clear(gl.COLOR_BUFFER_BIT) 24 | gl.disable(gl.DEPTH_TEST) 25 | gl.disable(gl.CULL_FACE) 26 | 27 | var width = app.shape[0] 28 | var height = app.shape[1] 29 | var radius = Math.max(width, height) * 1.05 30 | background.style({ 31 | scale: [ 1 / width * radius, 1 / height * radius ], 32 | aspect: 1, 33 | color1: rgb('#ffffff'), 34 | color2: rgb('#283844'), 35 | smoothing: [ -0.5, 1.0 ], 36 | noiseAlpha: 0.35, 37 | coloredNoise: true, 38 | offset: [ -0.05, -0.15 ] 39 | }) 40 | background.draw() 41 | } 42 | -------------------------------------------------------------------------------- /frag.glsl: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision mediump float; 3 | #endif 4 | 5 | varying vec2 vUv; 6 | 7 | #pragma glslify: random = require('glsl-random') 8 | #pragma glslify: blend = require('glsl-blend-overlay') 9 | 10 | uniform float aspect; 11 | uniform vec2 scale; 12 | uniform vec2 offset; 13 | uniform bool coloredNoise; 14 | 15 | uniform vec2 smoothing; 16 | uniform float noiseAlpha; 17 | 18 | uniform vec3 color1; 19 | uniform vec3 color2; 20 | 21 | void main() { 22 | vec2 pos = vUv; 23 | pos -= 0.5; 24 | 25 | pos.x *= aspect; 26 | pos /= scale; 27 | pos -= offset; 28 | 29 | float dist = length(pos); 30 | dist = smoothstep(smoothing.x, smoothing.y, 1.-dist); 31 | 32 | vec4 color = vec4(1.0); 33 | color.rgb = mix(color2, color1, dist); 34 | 35 | if (noiseAlpha > 0.0) { 36 | vec3 noise = coloredNoise ? vec3(random(vUv * 1.5), random(vUv * 2.5), random(vUv)) : vec3(random(vUv)); 37 | color.rgb = mix(color.rgb, blend(color.rgb, noise), noiseAlpha); 38 | } 39 | gl_FragColor = color; 40 | } -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var glslify = require('glslify') 2 | 3 | var createQuad = require('gl-quad') 4 | var createShader = require('gl-shader') 5 | 6 | var identity4x4 = require('gl-mat4/identity') 7 | 8 | var vert = glslify('./vert.glsl') 9 | var frag = glslify('./frag.glsl') 10 | 11 | module.exports = createBackground 12 | function createBackground (gl) { 13 | var attribs = [ 14 | { name: 'position', location: 0, type: 'vec4' }, 15 | { name: 'uv', location: 1, type: 'vec2' } 16 | ] 17 | 18 | var shader = createShader(gl, vert, frag, null, attribs) 19 | var quad = createQuad(gl) 20 | var matrix = identity4x4([]) 21 | 22 | var width = gl.drawingBufferWidth 23 | var height = gl.drawingBufferHeight 24 | 25 | // some defaults 26 | style({ 27 | aspect: width / height, 28 | smoothing: [-0.4, 0.8], 29 | noiseAlpha: 0.04, 30 | coloredNoise: true, 31 | offset: [0, 0], 32 | resolution: [ width, height ], 33 | color1: [1, 1, 1], 34 | color2: [0, 0, 0], 35 | scale: [1.0, 1.0], 36 | projection: matrix, 37 | view: matrix, 38 | model: matrix 39 | }) 40 | 41 | function style (opt) { 42 | if (!opt) { 43 | return 44 | } 45 | 46 | shader.bind() 47 | var uniforms = shader.uniforms 48 | for (var k in opt) { 49 | if (exists(opt, k)) { 50 | uniforms[k] = opt[k] 51 | } 52 | } 53 | } 54 | 55 | function draw () { 56 | shader.bind() 57 | quad.draw() 58 | } 59 | 60 | function dispose () { 61 | shader.dispose() 62 | quad.dispose() 63 | } 64 | 65 | return { 66 | draw: draw, 67 | dispose: dispose, 68 | style: style 69 | } 70 | } 71 | 72 | function exists (opt, k) { 73 | return opt.hasOwnProperty(k) && 74 | (opt[k] || 75 | typeof opt[k] === 'number' || 76 | typeof opt[k] === 'boolean') 77 | } 78 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gl-vignette-background", 3 | "version": "2.0.1", 4 | "description": "a soft gradient background in WebGL", 5 | "main": "index.js", 6 | "license": "MIT", 7 | "author": "Matt DesLauriers ", 8 | "dependencies": { 9 | "gl-mat4": "^1.0.0", 10 | "gl-quad": "^1.0.0", 11 | "gl-shader": "^4.0.1", 12 | "glsl-blend-overlay": "^1.0.5", 13 | "glsl-random": "0.0.4", 14 | "glslify": "^5.0.0" 15 | }, 16 | "devDependencies": { 17 | "budo": "^7.0.3", 18 | "canvas-loop": "^1.0.4", 19 | "canvas-testbed": "^1.0.0", 20 | "hex-rgb": "^1.0.0", 21 | "standard": "^5.4.1", 22 | "webgl-context": "^2.1.2" 23 | }, 24 | "scripts": { 25 | "start": "budo demo/index.js:bundle.js --live", 26 | "test": "standard" 27 | }, 28 | "repository": { 29 | "type": "git", 30 | "url": "git://github.com/mattdesl/gl-vignette-background.git" 31 | }, 32 | "homepage": "https://github.com/mattdesl/gl-vignette-background", 33 | "bugs": { 34 | "url": "https://github.com/mattdesl/gl-vignette-background/issues" 35 | }, 36 | "keywords": [ 37 | "glsl", 38 | "gl", 39 | "webgl", 40 | "gl-modules", 41 | "stackgl", 42 | "texture", 43 | "image", 44 | "background", 45 | "vignette", 46 | "gradient" 47 | ], 48 | "browserify": { 49 | "transform": [ 50 | "glslify" 51 | ] 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /vert.glsl: -------------------------------------------------------------------------------- 1 | attribute vec4 position; 2 | attribute vec2 uv; 3 | uniform mat4 projection; 4 | uniform mat4 view; 5 | uniform mat4 model; 6 | 7 | varying vec2 vUv; 8 | 9 | void main() { 10 | gl_Position = projection * view * model * position; 11 | vUv = uv; 12 | } --------------------------------------------------------------------------------