1+ #pragma header
2+
3+ /*
4+ Film Grain post-process shader v1.1
5+ Martins Upitis (martinsh) devlog-martinsh.blogspot.com
6+ 2013
7+
8+ --------------------------
9+ This work is licensed under a Creative Commons Attribution 3.0 Unported License.
10+ So you are free to share, modify and adapt it for your needs, and even use it for commercial use.
11+ I would also love to hear about a project you are using it.
12+
13+ Have fun,
14+ Martins
15+ --------------------------
16+
17+ Perlin noise shader by toneburst:
18+ http://machinesdontcare.wordpress.com/2009/06/25/3d-perlin-noise-sphere-vertex-shader-sourcecode/
19+ */
20+ uniform float uTime;
21+
22+ const float permTexUnit = 1.0 / 256.0 ; // Perm texture texel-size
23+ const float permTexUnitHalf = 0.5 / 256.0 ; // Half perm texture texel-size
24+
25+ float width = openfl_TextureSize.x;
26+ float height = openfl_TextureSize.y;
27+
28+ const float grainamount = 0.1 ; // grain amount
29+ bool colored = false; // colored noise?
30+ float coloramount = 0.6 ;
31+ float grainsize = 2.0 ; // grain particle size (1.5 - 2.5)
32+
33+ // a random texture generator, but you can also use a pre-computed perturbation texture
34+ vec4 rnm(in vec2 tc)
35+ {
36+ float noise = sin (dot (tc + vec2 (uTime,uTime),vec2 (12.9898 ,78.233 ))) * 43758.5453 ;
37+
38+ float noiseR = fract (noise)* 2.0 - 1.0 ;
39+ float noiseG = fract (noise* 1.2154 )* 2.0 - 1.0 ;
40+ float noiseB = fract (noise* 1.3453 )* 2.0 - 1.0 ;
41+ float noiseA = fract (noise* 1.3647 )* 2.0 - 1.0 ;
42+
43+ return vec4 (noiseR,noiseG,noiseB,noiseA);
44+ }
45+
46+ float fade(in float t) {
47+ return t* t* t* (t* (t* 6.0 - 15.0 )+ 10.0 );
48+ }
49+
50+ float pnoise3D(in vec3 p)
51+ {
52+ vec3 pi = permTexUnit* floor (p)+ permTexUnitHalf; // Integer part, scaled so +1 moves permTexUnit texel
53+ // and offset 1/2 texel to sample texel centers
54+ vec3 pf = fract (p); // Fractional part for interpolation
55+
56+ // Noise contributions from (x=0, y=0), z=0 and z=1
57+ float perm00 = rnm(pi.xy).a ;
58+ vec3 grad000 = rnm(vec2 (perm00, pi.z)).rgb * 4.0 - 1.0 ;
59+ float n000 = dot (grad000, pf);
60+ vec3 grad001 = rnm(vec2 (perm00, pi.z + permTexUnit)).rgb * 4.0 - 1.0 ;
61+ float n001 = dot (grad001, pf - vec3 (0.0 , 0.0 , 1.0 ));
62+
63+ // Noise contributions from (x=0, y=1), z=0 and z=1
64+ float perm01 = rnm(pi.xy + vec2 (0.0 , permTexUnit)).a ;
65+ vec3 grad010 = rnm(vec2 (perm01, pi.z)).rgb * 4.0 - 1.0 ;
66+ float n010 = dot (grad010, pf - vec3 (0.0 , 1.0 , 0.0 ));
67+ vec3 grad011 = rnm(vec2 (perm01, pi.z + permTexUnit)).rgb * 4.0 - 1.0 ;
68+ float n011 = dot (grad011, pf - vec3 (0.0 , 1.0 , 1.0 ));
69+
70+ // Noise contributions from (x=1, y=0), z=0 and z=1
71+ float perm10 = rnm(pi.xy + vec2 (permTexUnit, 0.0 )).a ;
72+ vec3 grad100 = rnm(vec2 (perm10, pi.z)).rgb * 4.0 - 1.0 ;
73+ float n100 = dot (grad100, pf - vec3 (1.0 , 0.0 , 0.0 ));
74+ vec3 grad101 = rnm(vec2 (perm10, pi.z + permTexUnit)).rgb * 4.0 - 1.0 ;
75+ float n101 = dot (grad101, pf - vec3 (1.0 , 0.0 , 1.0 ));
76+
77+ // Noise contributions from (x=1, y=1), z=0 and z=1
78+ float perm11 = rnm(pi.xy + vec2 (permTexUnit, permTexUnit)).a ;
79+ vec3 grad110 = rnm(vec2 (perm11, pi.z)).rgb * 4.0 - 1.0 ;
80+ float n110 = dot (grad110, pf - vec3 (1.0 , 1.0 , 0.0 ));
81+ vec3 grad111 = rnm(vec2 (perm11, pi.z + permTexUnit)).rgb * 4.0 - 1.0 ;
82+ float n111 = dot (grad111, pf - vec3 (1.0 , 1.0 , 1.0 ));
83+
84+ // Blend contributions along x
85+ vec4 n_x = mix (vec4 (n000, n001, n010, n011), vec4 (n100, n101, n110, n111), fade(pf.x));
86+
87+ // Blend contributions along y
88+ vec2 n_xy = mix (n_x.xy, n_x.zw, fade(pf.y));
89+
90+ // Blend contributions along z
91+ float n_xyz = mix (n_xy.x, n_xy.y, fade(pf.z));
92+
93+ // We are done, return the final noise value.
94+ return n_xyz;
95+ }
96+
97+ // 2d coordinate orientation thing
98+ vec2 coordRot(in vec2 tc, in float angle)
99+ {
100+ float aspect = width/ height;
101+ float rotX = ((tc.x* 2.0 - 1.0 )* aspect* cos (angle)) - ((tc.y* 2.0 - 1.0 )* sin (angle));
102+ float rotY = ((tc.y* 2.0 - 1.0 )* cos (angle)) + ((tc.x* 2.0 - 1.0 )* aspect* sin (angle));
103+ rotX = ((rotX/ aspect)* 0.5 + 0.5 );
104+ rotY = rotY* 0.5 + 0.5 ;
105+ return vec2 (rotX,rotY);
106+ }
107+
108+ void main()
109+ {
110+ vec2 texCoord = openfl_TextureCoordv.st;
111+
112+ vec3 rotOffset = vec3 (1.425 ,3.892 ,5.835 ); // rotation offset values
113+ vec2 rotCoordsR = coordRot(texCoord, uTime + rotOffset.x);
114+ vec3 noise = vec3 (pnoise3D(vec3 (rotCoordsR* vec2 (width/ grainsize,height/ grainsize),0.0 )));
115+
116+ if (colored)
117+ {
118+ vec2 rotCoordsG = coordRot(texCoord, uTime + rotOffset.y);
119+ vec2 rotCoordsB = coordRot(texCoord, uTime + rotOffset.z);
120+ noise.g = mix (noise.r,pnoise3D(vec3 (rotCoordsG* vec2 (width/ grainsize,height/ grainsize),1.0 )),coloramount);
121+ noise.b = mix (noise.r,pnoise3D(vec3 (rotCoordsB* vec2 (width/ grainsize,height/ grainsize),2.0 )),coloramount);
122+ }
123+
124+ vec3 col = texture2D (bitmap, openfl_TextureCoordv).rgb;
125+ col = col+ noise* grainamount;
126+
127+ gl_FragColor = vec4 (col,1.0 );
128+ }
0 commit comments