├── demo.png
├── demo
├── phaser2.png
├── 8710000952_a7830143dd_b.jpg
├── 14001968572_cf2d689031_b.jpg
├── index.html
└── demo.js
├── README.md
└── src
├── Vignette.js
├── SNoise.js
└── FilmGrain.js
/demo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jounii/phaser-filterkit/HEAD/demo.png
--------------------------------------------------------------------------------
/demo/phaser2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jounii/phaser-filterkit/HEAD/demo/phaser2.png
--------------------------------------------------------------------------------
/demo/8710000952_a7830143dd_b.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jounii/phaser-filterkit/HEAD/demo/8710000952_a7830143dd_b.jpg
--------------------------------------------------------------------------------
/demo/14001968572_cf2d689031_b.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jounii/phaser-filterkit/HEAD/demo/14001968572_cf2d689031_b.jpg
--------------------------------------------------------------------------------
/demo/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Filter Test
6 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/demo/demo.js:
--------------------------------------------------------------------------------
1 | var background;
2 | var filter = [];
3 | var FILTER_VIGNETTE = 0;
4 | var FILTER_FILMGRAIN = 1;
5 | var FILTER_SNOISE = 2;
6 | var game = new Phaser.Game(800, 600, Phaser.AUTO, 'filter-example', { preload: preload, create: create, update: update });
7 |
8 | function preload() {
9 |
10 | game.load.image('phaser', 'phaser2.png');
11 | game.load.image('background', '8710000952_a7830143dd_b.jpg');
12 | game.load.script('filter-vignette', '../src/Vignette.js');
13 | //game.load.script('filter-snoise', '../src/SNoise.js');
14 | game.load.script('filter-filmgrain', '../src/FilmGrain.js');
15 |
16 | }
17 |
18 | function create() {
19 |
20 | background = game.add.sprite(0, 0, 'background');
21 | background.width = 800;
22 | background.height = 600;
23 |
24 | filter[FILTER_VIGNETTE] = game.add.filter('Vignette');
25 | filter[FILTER_VIGNETTE].size = 0.3;
26 | filter[FILTER_VIGNETTE].amount = 0.5;
27 | filter[FILTER_VIGNETTE].alpha = 1.0;
28 |
29 | //filter[FILTER_SNOISE] = game.add.filter('SNoise');
30 |
31 | filter[FILTER_FILMGRAIN] = game.add.filter('FilmGrain');
32 | filter[FILTER_FILMGRAIN].color = 0.6;
33 | filter[FILTER_FILMGRAIN].amount = 0.04;
34 | filter[FILTER_FILMGRAIN].luminance = 0.8;
35 |
36 | //background.filters = [filter[FILTER_FILMGRAIN], filter[FILTER_VIGNETTE]];
37 | game.stage.filters = [filter[FILTER_FILMGRAIN], filter[FILTER_VIGNETTE]];
38 |
39 | var logo = game.add.sprite(game.world.centerX, game.world.centerY, 'phaser');
40 | logo.anchor.setTo(0.5, 0.5);
41 |
42 | }
43 |
44 | var direction = -1;
45 |
46 | function update() {
47 | var f = filter[FILTER_FILMGRAIN];
48 | /*
49 | f.amount += 0.01 * direction;
50 | if (f.amount <= 0) {
51 | f.amount = 0;
52 | direction = 1;
53 | } else if (f.amount >= 1.0) {
54 | f.amount = 1.0;
55 | direction = -1;
56 | }
57 | */
58 |
59 | f.update();
60 |
61 | }
62 |
63 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | phaser-filterkit
2 | ================
3 |
4 | Assorted kit of PhaserJS WebGL Filters.
5 |
6 | Filters
7 | =======
8 |
9 | Vignette
10 | --------
11 |
12 | Original shader by Evan Wallace.
13 |
14 | http://evanw.github.io/glfx.js/
15 | https://github.com/evanw/glfx.js/blob/master/src/filters/adjust/vignette.js
16 |
17 | FilmGrain
18 | ---------
19 |
20 | Original shader by Martins Upitis.
21 |
22 | http://devlog-martinsh.blogspot.fi/2013/05/image-imperfections-and-film-grain-post.html
23 |
24 | Notes: The shader parameters were published and the texture randomness had some issues
25 | with Phaser time uniform (seconds) over time. Shader modified so that it basically loops
26 | every 120 seconds and the texture rotation is randomized to certain angle range.
27 |
28 | SNoise
29 | ------
30 |
31 | Original shader by Ian McEwan, Ashima Arts.
32 |
33 | https://github.com/ashima/webgl-noise
34 |
35 | Not sure if this is useful. Possibly with some tweaks and parameterization
36 | could make it more useful. But use this as base for other filters.
37 |
38 |
39 | License
40 | =======
41 |
42 | As code is mostly based on existing shaders so their licensing carries over:
43 |
44 | -------
45 | This work is licensed under a Creative Commons Attribution 3.0 Unported License.
46 | So you are free to share, modify and adapt it for your needs, and even use it for commercial use.
47 | I would also love to hear about a project you are using it.
48 |
49 | -------
50 | Permission is hereby granted, free of charge, to any person obtaining a copy
51 | of this software and associated documentation files (the "Software"), to deal
52 | in the Software without restriction, including without limitation the rights
53 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
54 | copies of the Software, and to permit persons to whom the Software is
55 | furnished to do so, subject to the following conditions:
56 |
57 | The above copyright notice and this permission notice shall be included in
58 | all copies or substantial portions of the Software.
59 |
60 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
61 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
62 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
63 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
64 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
65 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
66 | THE SOFTWARE.
--------------------------------------------------------------------------------
/src/Vignette.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | * @filter Vignette
4 | * @description Adds a simulated lens edge darkening effect.
5 | *
6 | * param size 0 to 1 (0 for center of frame, 1 for edge of frame)
7 | * param amount 0 to 1 (0 for no effect, 1 for maximum lens darkening)
8 | *
9 | * Original shader by Evan Wallace.
10 | *
11 | * http://evanw.github.io/glfx.js/
12 | *
13 | * https://github.com/evanw/glfx.js/blob/master/src/filters/adjust/vignette.js
14 | *
15 | * Converted to Phaser/PIXI by Jouni Airaksinen, jouni.airaksinen@sc5.io
16 | *
17 | */
18 | Phaser.Filter.Vignette = function (game) {
19 |
20 | Phaser.Filter.call(this, game);
21 |
22 | this.uniforms.alpha = { type: '1f', value: 1.0 };
23 | this.uniforms.size = { type: '1f', value: 0.5 };
24 | this.uniforms.amount = { type: '1f', value: 0.5 };
25 |
26 | this.fragmentSrc = [
27 |
28 | "precision mediump float;",
29 | "uniform sampler2D uSampler;",
30 | "uniform float time;",
31 | "uniform float alpha;",
32 | "uniform float size;",
33 | "uniform float amount;",
34 | "varying vec2 vTextureCoord;",
35 |
36 | "void main(void) {",
37 |
38 | "vec4 color = texture2D(uSampler, vTextureCoord);",
39 |
40 | "float dist = distance(vTextureCoord, vec2(0.5, 0.5));",
41 |
42 | "color.rgb *= smoothstep(0.8, size * 1.0 * 0.799, dist * (alpha * amount + size));",
43 | "gl_FragColor = color;",
44 | "}"
45 | ];
46 |
47 | };
48 |
49 | Phaser.Filter.Vignette.prototype = Object.create(Phaser.Filter.prototype);
50 | Phaser.Filter.Vignette.prototype.constructor = Phaser.Filter.Vignette;
51 |
52 | Object.defineProperty(Phaser.Filter.Vignette.prototype, 'alpha', {
53 |
54 | get: function() {
55 | return this.uniforms.alpha.value;
56 | },
57 |
58 | set: function(value) {
59 | this.uniforms.alpha.value = value;
60 | }
61 |
62 | });
63 |
64 | Object.defineProperty(Phaser.Filter.Vignette.prototype, 'size', {
65 |
66 | get: function() {
67 | return this.uniforms.size.value;
68 | },
69 |
70 | set: function(value) {
71 | this.uniforms.size.value = Math.max(0, Math.min(value, 1));
72 | }
73 |
74 | });
75 |
76 | Object.defineProperty(Phaser.Filter.Vignette.prototype, 'amount', {
77 |
78 | get: function() {
79 | return this.uniforms.amount.value;
80 | },
81 |
82 | set: function(value) {
83 | this.uniforms.amount.value = Math.max(0, Math.min(value, 1));
84 | }
85 |
86 | });
--------------------------------------------------------------------------------
/src/SNoise.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | * @filter SNoise
4 | *
5 | * Original shader by Ian McEwan, Ashima Arts.
6 | *
7 | * https://github.com/ashima/webgl-noise
8 | *
9 | * Converted to Phaser/PIXI by Jouni Airaksinen, jouni.airaksinen@sc5.io
10 | *
11 | * Notes: Not sure if this is useful. Possibly with some tweaks and parameterization
12 | * could make it more useful. But use this as base for other filters.
13 | *
14 | */
15 |
16 | //
17 | // Description : Array and textureless GLSL 2D simplex noise function.
18 | // Author : Ian McEwan, Ashima Arts.
19 | // Maintainer : ijm
20 | // Lastmod : 20110822 (ijm)
21 | // License : Copyright (C) 2011 Ashima Arts. All rights reserved.
22 | // Distributed under the MIT License. See LICENSE file.
23 | // https://github.com/ashima/webgl-noise
24 | //
25 |
26 | Phaser.Filter.SNoise = function (game) {
27 |
28 | Phaser.Filter.call(this, game);
29 |
30 | this.uniforms.amount = { type: '1f', value: 0.5 };
31 | this.uniforms.z = { type: '1f', value: 0.0 };
32 |
33 | this.fragmentSrc = [
34 | "precision mediump float;",
35 | "uniform float time;",
36 | "uniform float uz;",
37 | "uniform float amount;",
38 | "uniform sampler2D uSampler;",
39 | "varying vec2 vTextureCoord;",
40 |
41 | "vec3 mod289(vec3 x) {",
42 | "return x - floor(x * (1.0 / 289.0)) * 289.0;",
43 | "}",
44 |
45 | "vec2 mod289(vec2 x) {",
46 | "return x - floor(x * (1.0 / 289.0)) * 289.0;",
47 | "}",
48 |
49 | "vec4 mod289(vec4 x) {",
50 | "return x - floor(x * (1.0 / 289.0)) * 289.0;",
51 | "}",
52 |
53 | "vec4 permute(vec4 x) {",
54 | "return mod289(((x*34.0)+1.0)*x);",
55 | "}",
56 |
57 | "vec4 taylorInvSqrt(vec4 r) {",
58 | "return 1.79284291400159 - 0.85373472095314 * r;",
59 | "}",
60 |
61 | "float snoise(vec3 v) {",
62 | "const vec2 C = vec2(1.0/6.0, 1.0/3.0);",
63 | "const vec4 D = vec4(0.0, 0.5, 1.0, 2.0);",
64 |
65 | // First corner
66 | "vec3 i = floor(v + dot(v, C.yyy) );",
67 | "vec3 x0 = v - i + dot(i, C.xxx) ;",
68 |
69 | // Other corners
70 | "vec3 g = step(x0.yzx, x0.xyz);",
71 | "vec3 l = 1.0 - g;",
72 | "vec3 i1 = min( g.xyz, l.zxy );",
73 | "vec3 i2 = max( g.xyz, l.zxy );",
74 |
75 | // x0 = x0 - 0.0 + 0.0 * C.xxx;
76 | // x1 = x0 - i1 + 1.0 * C.xxx;
77 | // x2 = x0 - i2 + 2.0 * C.xxx;
78 | // x3 = x0 - 1.0 + 3.0 * C.xxx;
79 | "vec3 x1 = x0 - i1 + C.xxx;",
80 | "vec3 x2 = x0 - i2 + C.yyy;", // 2.0*C.x = 1/3 = C.y
81 | "vec3 x3 = x0 - D.yyy;", // -1.0+3.0*C.x = -0.5 = -D.y
82 |
83 | // Permutations
84 | "i = mod289(i);",
85 | "vec4 p = permute( permute( permute(",
86 | " i.z + vec4(0.0, i1.z, i2.z, 1.0 ))",
87 | "+ i.y + vec4(0.0, i1.y, i2.y, 1.0 ))",
88 | "+ i.x + vec4(0.0, i1.x, i2.x, 1.0 ));",
89 |
90 | // Gradients: 7x7 points over a square, mapped onto an octahedron.
91 | // The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294)
92 | "float n_ = 0.142857142857;", // 1.0/7.0
93 | "vec3 ns = n_ * D.wyz - D.xzx;",
94 |
95 | "vec4 j = p - 49.0 * floor(p * ns.z * ns.z);", // mod(p,7*7)
96 |
97 | "vec4 x_ = floor(j * ns.z);",
98 | "vec4 y_ = floor(j - 7.0 * x_ );", // mod(j,N)
99 |
100 | "vec4 x = x_ *ns.x + ns.yyyy;",
101 | "vec4 y = y_ *ns.x + ns.yyyy;",
102 | "vec4 h = 1.0 - abs(x) - abs(y);",
103 |
104 | "vec4 b0 = vec4( x.xy, y.xy );",
105 | "vec4 b1 = vec4( x.zw, y.zw );",
106 |
107 | //vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0;
108 | //vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0;
109 | "vec4 s0 = floor(b0)*2.0 + 1.0;",
110 | "vec4 s1 = floor(b1)*2.0 + 1.0;",
111 | "vec4 sh = -step(h, vec4(0.0));",
112 |
113 | "vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ;",
114 | "vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ;",
115 |
116 | "vec3 p0 = vec3(a0.xy,h.x);",
117 | "vec3 p1 = vec3(a0.zw,h.y);",
118 | "vec3 p2 = vec3(a1.xy,h.z);",
119 | "vec3 p3 = vec3(a1.zw,h.w);",
120 |
121 | //Normalise gradients
122 | "vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));",
123 | "p0 *= norm.x;",
124 | "p1 *= norm.y;",
125 | "p2 *= norm.z;",
126 | "p3 *= norm.w;",
127 |
128 | // Mix final noise value
129 | "vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0);",
130 | "m = m * m;",
131 | "return 42.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1),",
132 | " dot(p2,x2), dot(p3,x3) ) );",
133 | "}",
134 |
135 | "void main(void) {",
136 | "vec3 vTextureCoord3D = vec3(vTextureCoord, uz);",
137 | "vec3 uvw = vTextureCoord3D + 0.1*vec3(snoise(vTextureCoord3D + vec3(0.0, 0.0, time)),",
138 | "snoise(vTextureCoord3D + vec3(43.0, 17.0, time)),",
139 | "snoise(vTextureCoord3D + vec3(-17.0, -43.0, time)));",
140 | // Six components of noise in a fractal sum
141 | "float n = snoise(uvw - vec3(0.0, 0.0, time));",
142 | "n += 0.5 * snoise(uvw * 2.0 - vec3(0.0, 0.0, time*1.4));",
143 | "n += 0.25 * snoise(uvw * 4.0 - vec3(0.0, 0.0, time*2.0));",
144 | "n += 0.125 * snoise(uvw * 8.0 - vec3(0.0, 0.0, time*2.8));",
145 | "n += 0.0625 * snoise(uvw * 16.0 - vec3(0.0, 0.0, time*4.0));",
146 | "n += 0.03125 * snoise(uvw * 32.0 - vec3(0.0, 0.0, time*5.6));",
147 | "n = n * amount;",
148 | // Overlay to the texture
149 | "vec4 color = texture2D(uSampler, vTextureCoord);",
150 | "gl_FragColor = color + vec4(vec3(n, n, n), color.a * 1.0);",
151 | "}"
152 | ];
153 |
154 | };
155 |
156 | Phaser.Filter.SNoise.prototype = Object.create(Phaser.Filter.prototype);
157 | Phaser.Filter.SNoise.prototype.constructor = Phaser.Filter.SNoise;
158 |
159 | Object.defineProperty(Phaser.Filter.SNoise.prototype, 'z', {
160 |
161 | get: function() {
162 | return this.uniforms.z.value;
163 | },
164 |
165 | set: function(value) {
166 | this.uniforms.z.value = Math.max(0, Math.min(value, 1));
167 | }
168 |
169 | });
170 |
171 | Object.defineProperty(Phaser.Filter.SNoise.prototype, 'amount', {
172 |
173 | get: function() {
174 | return this.uniforms.amount.value;
175 | },
176 |
177 | set: function(value) {
178 | this.uniforms.amount.value = Math.max(0, Math.min(value, 1));
179 | }
180 |
181 | });
--------------------------------------------------------------------------------
/src/FilmGrain.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | * @filter Film Grain
4 | *
5 | * Original shader by Martins Upitis
6 | *
7 | * http://devlog-martinsh.blogspot.fi/2013/05/image-imperfections-and-film-grain-post.html
8 | *
9 | * Converted to Phaser/PIXI by Jouni Airaksinen, jouni.airaksinen@sc5.io
10 | *
11 | */
12 | /*
13 | Film Grain post-process shader v1.1
14 | Martins Upitis (martinsh) devlog-martinsh.blogspot.com
15 | 2013
16 |
17 | --------------------------
18 | This work is licensed under a Creative Commons Attribution 3.0 Unported License.
19 | So you are free to share, modify and adapt it for your needs, and even use it for commercial use.
20 | I would also love to hear about a project you are using it.
21 |
22 | Have fun,
23 | Martins
24 | --------------------------
25 |
26 | Perlin noise shader by toneburst:
27 | http://machinesdontcare.wordpress.com/2009/06/25/3d-perlin-noise-sphere-vertex-shader-sourcecode/
28 | */
29 |
30 | Phaser.Filter.FilmGrain = function (game) {
31 |
32 | Phaser.Filter.call(this, game);
33 |
34 | this.uniforms.lumAmount = { type: '1f', value: 1.0 };
35 | this.uniforms.grainSize = { type: '1f', value: 0.1 };
36 | this.uniforms.grainAmount = { type: '1f', value: 0.05 };
37 | this.uniforms.colorAmount = { type: '1f', value: 0.0 };
38 |
39 | this.fragmentSrc = [
40 | "precision mediump float;",
41 | "uniform float time;",
42 | "uniform sampler2D uSampler;",
43 | "uniform vec2 resolution;",
44 | "uniform float colorAmount;",
45 | "uniform float grainAmount;",
46 | "uniform float grainSize;",
47 | "uniform float lumAmount;",
48 | "varying vec2 vTextureCoord;",
49 |
50 | "const float permTexUnit = 1.0/256.0;", // Perm texture texel-size
51 | "const float permTexUnitHalf = 0.5/256.0;", // Half perm texture texel-size
52 |
53 | // As time progresses, the random starts to produce artifacts, rotate time in range
54 | // which is still fine, thus the grain loops every 120 seconds
55 | "float modTime = time - floor(time * (1.0 / 120.0)) * 120.0;",
56 |
57 | "float width = resolution.x;",
58 | "float height = resolution.y;",
59 |
60 | "bool colored = colorAmount > 0.0;",
61 | "float grainsize = 1.5 + grainSize;", //grain particle size (1.5 - 2.5)
62 |
63 | //a random texture generator, but you can also use a pre-computed perturbation texture
64 | "vec4 rnm(in vec2 tc) {",
65 | "float noise = sin(dot(tc + vec2(modTime,modTime),vec2(12.9898,78.233))) * 43758.5453;",
66 |
67 | "float noiseR = fract(noise)*2.0-1.0;",
68 | "float noiseG = fract(noise*1.2154)*2.0-1.0;",
69 | "float noiseB = fract(noise*1.3453)*2.0-1.0;",
70 | "float noiseA = fract(noise*1.3647)*2.0-1.0;",
71 |
72 | "return vec4(noiseR,noiseG,noiseB,noiseA);",
73 | "}",
74 |
75 | "float fade(in float t) {",
76 | "return t*t*t*(t*(t*6.0-15.0)+10.0);",
77 | "}",
78 |
79 | // TODO: replace to simplex from SNoise?
80 | "float pnoise3D(in vec3 p) {",
81 | "vec3 pi = permTexUnit*floor(p)+permTexUnitHalf;", // Integer part, scaled so +1 moves permTexUnit texel
82 | // and offset 1/2 texel to sample texel centers
83 | "vec3 pf = fract(p);", // Fractional part for interpolation
84 |
85 | // Noise contributions from (x=0, y=0), z=0 and z=1
86 | "float perm00 = rnm(pi.xy).a;",
87 | "vec3 grad000 = rnm(vec2(perm00, pi.z)).rgb * 4.0 - 1.0;",
88 | "float n000 = dot(grad000, pf);",
89 | "vec3 grad001 = rnm(vec2(perm00, pi.z + permTexUnit)).rgb * 4.0 - 1.0;",
90 | "float n001 = dot(grad001, pf - vec3(0.0, 0.0, 1.0));",
91 |
92 | // Noise contributions from (x=0, y=1), z=0 and z=1
93 | "float perm01 = rnm(pi.xy + vec2(0.0, permTexUnit)).a ;",
94 | "vec3 grad010 = rnm(vec2(perm01, pi.z)).rgb * 4.0 - 1.0;",
95 | "float n010 = dot(grad010, pf - vec3(0.0, 1.0, 0.0));",
96 | "vec3 grad011 = rnm(vec2(perm01, pi.z + permTexUnit)).rgb * 4.0 - 1.0;",
97 | "float n011 = dot(grad011, pf - vec3(0.0, 1.0, 1.0));",
98 |
99 | // Noise contributions from (x=1, y=0), z=0 and z=1
100 | "float perm10 = rnm(pi.xy + vec2(permTexUnit, 0.0)).a ;",
101 | "vec3 grad100 = rnm(vec2(perm10, pi.z)).rgb * 4.0 - 1.0;",
102 | "float n100 = dot(grad100, pf - vec3(1.0, 0.0, 0.0));",
103 | "vec3 grad101 = rnm(vec2(perm10, pi.z + permTexUnit)).rgb * 4.0 - 1.0;",
104 | "float n101 = dot(grad101, pf - vec3(1.0, 0.0, 1.0));",
105 |
106 | // Noise contributions from (x=1, y=1), z=0 and z=1
107 | "float perm11 = rnm(pi.xy + vec2(permTexUnit, permTexUnit)).a ;",
108 | "vec3 grad110 = rnm(vec2(perm11, pi.z)).rgb * 4.0 - 1.0;",
109 | "float n110 = dot(grad110, pf - vec3(1.0, 1.0, 0.0));",
110 | "vec3 grad111 = rnm(vec2(perm11, pi.z + permTexUnit)).rgb * 4.0 - 1.0;",
111 | "float n111 = dot(grad111, pf - vec3(1.0, 1.0, 1.0));",
112 |
113 | // Blend contributions along x
114 | "vec4 n_x = mix(vec4(n000, n001, n010, n011), vec4(n100, n101, n110, n111), fade(pf.x));",
115 |
116 | // Blend contributions along y
117 | "vec2 n_xy = mix(n_x.xy, n_x.zw, fade(pf.y));",
118 |
119 | // Blend contributions along z
120 | "float n_xyz = mix(n_xy.x, n_xy.y, fade(pf.z));",
121 |
122 | // We're done, return the final noise value.
123 | "return n_xyz;",
124 | "}",
125 |
126 | //2d coordinate orientation thing
127 | "vec2 coordRot(in vec2 tc, in float angle) {",
128 | "float aspect = width/height;",
129 | "float rotX = ((tc.x*2.0-1.0)*aspect*cos(angle)) - ((tc.y*2.0-1.0)*sin(angle));",
130 | "float rotY = ((tc.y*2.0-1.0)*cos(angle)) + ((tc.x*2.0-1.0)*aspect*sin(angle));",
131 | "rotX = ((rotX/aspect)*0.5+0.5);",
132 | "rotY = rotY*0.5+0.5;",
133 | "return vec2(rotX,rotY);",
134 | "}",
135 |
136 | "float rand() {",
137 | "return fract(cos(dot(vec2(modTime, modTime), vec2(12.9898, 4.1414))) * 43758.5453);",
138 | "}",
139 |
140 | // Main filter
141 | "void main(void) {",
142 |
143 | "vec2 rotCoordsR = coordRot(vTextureCoord, 0.05*rand() + 1.1087);",
144 | //"vec2 rotCoordsR = vTextureCoord;",
145 | "vec3 noise = vec3(pnoise3D(vec3(rotCoordsR*vec2(width/grainsize,height/grainsize),0.0)));",
146 |
147 | "if (colored) {",
148 | "vec2 rotCoordsG = coordRot(vTextureCoord, 0.06*rand() + 1.1087);",
149 | "vec2 rotCoordsB = coordRot(vTextureCoord, 0.07*rand() + 1.1087);",
150 | "noise.g = mix(noise.r,pnoise3D(vec3(rotCoordsG*vec2(width/grainsize,height/grainsize),1.0)),colorAmount);",
151 | "noise.b = mix(noise.r,pnoise3D(vec3(rotCoordsB*vec2(width/grainsize,height/grainsize),2.0)),colorAmount);",
152 | "}",
153 |
154 | "vec4 color = texture2D(uSampler, vTextureCoord);",
155 | "vec3 col = color.rgb;",
156 |
157 | //noisiness response curve based on scene luminance
158 | "vec3 lumcoeff = vec3(0.299,0.587,0.114);",
159 | "float luminance = mix(0.0,dot(col, lumcoeff),lumAmount);",
160 | "float lum = smoothstep(0.2,0.0,luminance);",
161 | "lum += luminance;",
162 |
163 | "noise = mix(noise,vec3(0.0),pow(lum,4.0));",
164 | "col = col + noise*grainAmount;",
165 |
166 | "gl_FragColor = vec4(col, color.a);",
167 | "}"
168 | ];
169 |
170 | };
171 |
172 | Phaser.Filter.FilmGrain.prototype = Object.create(Phaser.Filter.prototype);
173 | Phaser.Filter.FilmGrain.prototype.constructor = Phaser.Filter.FilmGrain;
174 |
175 | Phaser.Filter.FilmGrain.prototype.init = function (width, height) {
176 | this.setResolution(width || this.game.width, height || this.game.height);
177 | };
178 |
179 | Object.defineProperty(Phaser.Filter.FilmGrain.prototype, 'color', {
180 |
181 | get: function() {
182 | return this.uniforms.colorAmount.value;
183 | },
184 |
185 | set: function(value) {
186 | this.uniforms.colorAmount.value = Math.max(0, Math.min(value, 1));
187 | }
188 |
189 | });
190 | Object.defineProperty(Phaser.Filter.FilmGrain.prototype, 'luminance', {
191 |
192 | get: function() {
193 | return this.uniforms.lumAmount.value;
194 | },
195 |
196 | set: function(value) {
197 | this.uniforms.lumAmount.value = value;
198 | }
199 |
200 | });
201 | Object.defineProperty(Phaser.Filter.FilmGrain.prototype, 'size', {
202 |
203 | get: function() {
204 | return this.uniforms.grainSize.value;
205 | },
206 |
207 | set: function(value) {
208 | this.uniforms.grainSize.value = Math.max(0, Math.min(value, 1));
209 | }
210 |
211 | });
212 | Object.defineProperty(Phaser.Filter.FilmGrain.prototype, 'amount', {
213 |
214 | get: function() {
215 | return this.uniforms.grainAmount.value;
216 | },
217 |
218 | set: function(value) {
219 | this.uniforms.grainAmount.value = Math.max(0, Math.min(value, 1));
220 | }
221 |
222 | });
--------------------------------------------------------------------------------