├── .gitignore
├── LICENSE
├── README.md
├── example
├── index.js
├── quad_frag.glsl
├── quad_vert.glsl
├── sphere_frag.glsl
└── sphere_vert.glsl
├── images
├── f.png
├── g.png
├── h.png
├── j.png
└── l.png
├── index.glsl
└── package.json
/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | .idea/
3 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
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 | # glsl-cos-palette
2 |
3 | `cosPalette` is a simple shader function that is defined as
4 |
5 | ```glsl
6 | vec3 cosPalette( float t, vec3 a, vec3 b, vec3 c, vec3 d ){
7 | return a + b*cos( 6.28318*(c*t+d) );
8 | }
9 | ```
10 |
11 | where `a,b,c,d` are RGB-colors. This function can be used to make very compact color palettes.
12 | A simple editor for making such palettes is provided [here](http://erkaman.github.io/glsl-cos-palette/).
13 |
14 |
15 | The function `cosPalette(t, a, b, c, d )`, which is the palette, will basically assign a color to every value `t`, which is in the range `[0,1]`. So if you set `t` to be the value of some noise function(say, Perlin noise) in range `[0,1]`, you can use this
16 | palette to make simple procedural textures. The palette will basically colorize the noise. In the fragment shader, we can easily procedurally generate a texture by doing something like
17 |
18 | ```glsl
19 | float t = noise(vPosition);
20 | vec3 tex = cosPalette(t, uAColor, uBColor, uCColor, uDColor );
21 | ```
22 |
23 | Credit goes to [Inigo Quilez](http://www.iquilezles.org/www/articles/palettes/palettes.htm) for coming up with this technique.
24 |
25 | If even more advanced palettes are desired, they can be created using [glsl-gradient-palette](https://github.com/Erkaman/glsl-gradient-palette)
26 |
27 | ## Examples
28 |
29 | Below are some examples of palettes
30 |
31 | `cosPalette(t,vec3(0.2,0.7,0.4),vec3(0.6,0.9,0.2),vec3(0.6,0.8,0.7),vec3(0.5,0.1,0.0))`
32 |
33 |
34 |
35 |
36 |
37 | `cosPalette(t,vec3(0.2,0.5,0.3),vec3(0.0,0.5,0.7),vec3(1.0,1.0,1.0),vec3(0.0,0.3,0.7))`
38 |
39 |
40 |
41 |
42 | `cosPalette(t,vec3(0.6,0.0,0.0),vec3(1.0,0.0,0.0),vec3(1.0,0.0,0.0),vec3(1.0,0.0,0.0))`
43 |
44 |
45 |
46 |
47 | `cosPalette(t,vec3(1.0,0.4,0.0),vec3(0.4,0.8,0.0),vec3(0.5,0.3,0.9),vec3(0.9,0.6,0.9))`
48 |
49 |
50 |
51 |
52 | `cosPalette(t,vec3(0.4,0.3,0.1),vec3(0.1,0.1,0.1),vec3(0.4,0.4,0.4),vec3(0.0,0.0,0.0))`
53 |
54 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/example/index.js:
--------------------------------------------------------------------------------
1 | /* global requestAnimationFrame */
2 |
3 | var mat4 = require('gl-mat4');
4 | var vec3 = require('gl-vec3');
5 | var Geometry = require('gl-geometry');
6 | var glShader = require('gl-shader');
7 | var glslify = require('glslify')
8 | var createOrbitCamera = require('orbit-camera');
9 | var shell = require("gl-now")();
10 | var createGui = require("pnp-gui");
11 | var cameraPosFromViewMatrix = require('gl-camera-pos-from-view-matrix');
12 | var randomArray = require('random-array');
13 | var createSphere = require('primitive-icosphere');
14 | var copyToClipboard = require('copy-to-clipboard');
15 |
16 | var sphereShader, quadShader, quadGeo, sphereGeo;
17 |
18 | var camera = createOrbitCamera([0, -2.0, 0], [0, 0, 0], [0, 1, 0]);
19 |
20 | var mouseLeftDownPrev = false;
21 |
22 | var bg = [0.6, 0.7, 1.0]; // clear color.
23 |
24 | var aColor = [0.2, 0.7, 0.4];
25 | var bColor = [0.6, 0.9, 0.2];
26 | var cColor = [0.6, 0.8, 0.7];
27 | var dColor = [0.5, 0.1, 0.0];
28 |
29 | var noiseScale = {val: 1.0};
30 | var seed = 100;
31 |
32 | // arguments are top-left and bottom-right corners
33 | function createQuad(tl, br) {
34 | var positions = [];
35 | var uvs = [];
36 |
37 | positions.push( [tl[0], tl[1] ] );
38 | positions.push( [ br[0], tl[1] ] );
39 | positions.push( [ tl[0] , br[1] ] );
40 | positions.push([ br[0], br[1] ] );
41 |
42 | uvs.push( [0,0 ] );// top-left
43 | uvs.push( [1,0 ] );// bottom-left
44 | uvs.push( [0,1 ] );// top-right
45 | uvs.push( [1,1 ] );// bottom-right
46 |
47 | var cells = [];
48 | cells.push( [2,1,0] );
49 |
50 | cells.push( [1,2,3] );
51 |
52 | return {positions: positions, cells:cells, uvs:uvs};
53 | }
54 |
55 | shell.on("gl-init", function () {
56 | var gl = shell.gl
57 |
58 | gl.enable(gl.DEPTH_TEST);
59 | gl.enable(gl.CULL_FACE);
60 | gl.cullFace(gl.BACK)
61 |
62 | gui = new createGui(gl);
63 | gui.windowSizes = [300, 380];
64 |
65 | var sphere = createSphere(1, { subdivisions: 2});
66 | sphereGeo = Geometry(gl)
67 | .attr('aPosition', sphere.positions).faces(sphere.cells);
68 |
69 | var quad = createQuad( [400, 40], [880, 100] );
70 | quadGeo = Geometry(gl).
71 | attr('aPosition', quad.positions, {size:2} ).
72 | attr('aUv', quad.uvs, {size:2} ).faces(quad.cells, {size:3});
73 |
74 | sphereShader = glShader(gl, glslify("./sphere_vert.glsl"), glslify("./sphere_frag.glsl"));
75 | quadShader = glShader(gl, glslify("./quad_vert.glsl"), glslify("./quad_frag.glsl"));
76 |
77 |
78 | // fix intial camera view.
79 | camera.rotate([0,0], [0,0] );
80 | });
81 |
82 |
83 | function randomizeColor() {
84 | aColor = randomArray(0, 1).oned(3);
85 | bColor = randomArray(0, 1).oned(3);
86 | cColor = randomArray(0, 1).oned(3);
87 | dColor = randomArray(0, 1).oned(3);
88 | }
89 |
90 | function blackColor() {
91 | aColor = [0,0,0];
92 | bColor =[0,0,0];
93 | cColor = [0,0,0];
94 | dColor = [0,0,0];
95 | }
96 |
97 | function colorToStr(c) {
98 | return "vec3(" + [ c[0].toFixed(2),c[1].toFixed(2),c[2].toFixed(2) ].join() + ")";
99 | }
100 |
101 | function paletteToStr() {
102 | return "cosPalette(t," + [colorToStr(aColor),colorToStr(bColor),colorToStr(cColor),colorToStr(dColor)].join()+ ")";
103 | }
104 |
105 | function newSeed() {
106 | seed = randomArray(0.0, 100.0).oned(1)[0];
107 | }
108 |
109 | shell.on("gl-render", function (t) {
110 | var gl = shell.gl
111 | var canvas = shell.canvas;
112 |
113 | gl.clearColor(bg[0], bg[1], bg[2], 1);
114 | gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
115 | gl.viewport(0, 0, canvas.width, canvas.height);
116 |
117 | var projection = mat4.create();
118 | var scratchMat = mat4.create();
119 | var view = camera.view(scratchMat);
120 |
121 | mat4.perspective(projection, Math.PI / 2, canvas.width / canvas.height, 0.1, 10000.0);
122 |
123 | /*
124 | Render Sphere
125 | */
126 |
127 | sphereShader.bind();
128 |
129 | sphereShader.uniforms.uView = view;
130 | sphereShader.uniforms.uProjection = projection;
131 | sphereShader.uniforms.uAColor = aColor;
132 | sphereShader.uniforms.uBColor = bColor;
133 | sphereShader.uniforms.uCColor = cColor;
134 | sphereShader.uniforms.uDColor = dColor;
135 | sphereShader.uniforms.uNoiseScale = noiseScale.val;
136 | sphereShader.uniforms.uSeed = seed;
137 |
138 | sphereGeo.bind(sphereShader);
139 | sphereGeo.draw();
140 |
141 | /*
142 | Render Palette.
143 | */
144 |
145 | quadShader.bind();
146 | quadShader.uniforms.uAColor = aColor;
147 | quadShader.uniforms.uBColor = bColor;
148 | quadShader.uniforms.uCColor = cColor;
149 | quadShader.uniforms.uDColor = dColor;
150 |
151 | var projection = mat4.create()
152 | mat4.ortho(projection, 0, canvas.width, canvas.height, 0, -1.0, 1.0)
153 | quadGeo.bind(quadShader);
154 | quadShader.uniforms.uProj = projection;
155 | quadGeo.draw();
156 |
157 |
158 | /*
159 | Render GUI.
160 | */
161 |
162 | var pressed = shell.wasDown("mouse-left");
163 | var io = {
164 | mouseLeftDownCur: pressed,
165 | mouseLeftDownPrev: mouseLeftDownPrev,
166 |
167 | mousePositionCur: shell.mouse,
168 | mousePositionPrev: shell.prevMouse
169 | };
170 | mouseLeftDownPrev = pressed;
171 |
172 | gui.begin(io, "Window");
173 |
174 | gui.textLine("a + b*cos(2pi*(c*t+d))");
175 |
176 | gui.draggerRgb("a", aColor);
177 | gui.draggerRgb("b", bColor);
178 | gui.draggerRgb("c", cColor);
179 | gui.draggerRgb("d", dColor);
180 |
181 | if(gui.button("Randomize")) {
182 | randomizeColor();
183 | }
184 |
185 | if(gui.button("To Black")) {
186 | blackColor();
187 | }
188 |
189 | if(gui.button("Copy to Clipboard")) {
190 | copyToClipboard(paletteToStr() );
191 | }
192 |
193 |
194 | gui.separator();
195 |
196 | gui.textLine("Noise Settings");
197 |
198 |
199 | gui.sliderFloat("Scale", noiseScale, 0.1, 10.0);
200 |
201 | if(gui.button("New Seed")) {
202 | newSeed();
203 | }
204 |
205 | gui.end(gl, canvas.width, canvas.height);
206 | });
207 |
208 | shell.on("tick", function () {
209 |
210 | // if interacting with the GUI, do not let the mouse control the camera.
211 | if (gui.hasMouseFocus())
212 | return;
213 |
214 | if (shell.wasDown("mouse-left")) {
215 | var speed = 1.3;
216 | camera.rotate([(shell.mouseX / shell.width - 0.5) * speed, (shell.mouseY / shell.height - 0.5) * speed],
217 | [(shell.prevMouseX / shell.width - 0.5) * speed, (shell.prevMouseY / shell.height - 0.5) * speed])
218 | }
219 | if (shell.scroll[1]) {
220 | camera.zoom(shell.scroll[1] * 0.01);
221 | }
222 | });
223 |
--------------------------------------------------------------------------------
/example/quad_frag.glsl:
--------------------------------------------------------------------------------
1 | precision mediump float;
2 |
3 | varying vec2 vUv;
4 |
5 | uniform vec3 uAColor;
6 | uniform vec3 uBColor;
7 | uniform vec3 uCColor;
8 | uniform vec3 uDColor;
9 |
10 | #pragma glslify: cosPalette = require(../index.glsl)
11 |
12 | void main() {
13 | gl_FragColor = vec4(cosPalette(vUv.x, uAColor, uBColor, uCColor, uDColor ), 1.0 );
14 |
15 | }
--------------------------------------------------------------------------------
/example/quad_vert.glsl:
--------------------------------------------------------------------------------
1 | precision mediump float;
2 |
3 | attribute vec2 aPosition;
4 | attribute vec2 aUv;
5 |
6 | varying vec2 vUv;
7 |
8 | uniform mat4 uProj;
9 |
10 |
11 | void main() {
12 | gl_Position = uProj * vec4(aPosition, 0.0, 1.0);
13 | vUv = aUv;
14 | }
--------------------------------------------------------------------------------
/example/sphere_frag.glsl:
--------------------------------------------------------------------------------
1 | precision mediump float;
2 |
3 | varying vec3 vPosition;
4 |
5 | uniform vec3 uAColor;
6 | uniform vec3 uBColor;
7 | uniform vec3 uCColor;
8 | uniform vec3 uDColor;
9 | uniform float uNoiseScale;
10 | uniform float uSeed;
11 |
12 | #pragma glslify: snoise3 = require(glsl-noise/simplex/3d)
13 | #pragma glslify: cosPalette = require(../index.glsl)
14 |
15 | float noise(vec3 s) {
16 | return snoise3(s) * 0.5 + 0.5; // scale to range [0,1]
17 | }
18 |
19 | float fbm( vec3 p) {
20 | float f = 0.0;
21 | f += 0.5000*noise( p ); p = p*2.02;
22 | f += 0.2500*noise( p ); p = p*2.03;
23 | f += 0.1250*noise( p ); p = p*2.01;
24 | f += 0.0625*noise( p );
25 | return f/0.9375;
26 | }
27 |
28 | void main() {
29 | float t = fbm(uNoiseScale*(vPosition + uSeed ) );
30 |
31 | vec3 tex = cosPalette(t, uAColor, uBColor, uCColor, uDColor );
32 |
33 | gl_FragColor = vec4(tex, 1.0);
34 | }
35 |
--------------------------------------------------------------------------------
/example/sphere_vert.glsl:
--------------------------------------------------------------------------------
1 | precision mediump float;
2 |
3 | attribute vec3 aPosition;
4 |
5 | varying vec3 vPosition;
6 |
7 | uniform mat4 uProjection;
8 | uniform mat4 uView;
9 |
10 | void main() {
11 | vPosition = aPosition;
12 | gl_Position = uProjection * uView * vec4(aPosition, 1.0);
13 | }
--------------------------------------------------------------------------------
/images/f.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Erkaman/glsl-cos-palette/2183c2352891f08afe6b7f27e29119a6e9ca78ec/images/f.png
--------------------------------------------------------------------------------
/images/g.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Erkaman/glsl-cos-palette/2183c2352891f08afe6b7f27e29119a6e9ca78ec/images/g.png
--------------------------------------------------------------------------------
/images/h.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Erkaman/glsl-cos-palette/2183c2352891f08afe6b7f27e29119a6e9ca78ec/images/h.png
--------------------------------------------------------------------------------
/images/j.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Erkaman/glsl-cos-palette/2183c2352891f08afe6b7f27e29119a6e9ca78ec/images/j.png
--------------------------------------------------------------------------------
/images/l.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Erkaman/glsl-cos-palette/2183c2352891f08afe6b7f27e29119a6e9ca78ec/images/l.png
--------------------------------------------------------------------------------
/index.glsl:
--------------------------------------------------------------------------------
1 |
2 |
3 | vec3 cosPalette( float t, vec3 a, vec3 b, vec3 c, vec3 d ){
4 | return a + b*cos( 6.28318*(c*t+d) );
5 | }
6 |
7 | #pragma glslify: export(cosPalette)
8 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "glsl-cos-palette",
3 | "version": "1.0.0",
4 | "description": "glsl function for making cosine palettes",
5 | "scripts": {
6 | "start": "budo --verbose example/index.js -t glslify --live --open",
7 | "test": "standard"
8 | },
9 | "keywords": [
10 | "stackgl",
11 | "glsl",
12 | "gl",
13 | "webgl",
14 | "procedual",
15 | "palette",
16 | "cos",
17 | "cosine",
18 | "palette",
19 | "texture",
20 | "noise"
21 | ],
22 | "author": "Eric Arnebäck (https://github.com/Erkaman)",
23 | "license": "MIT",
24 | "devDependencies": {
25 | "copy-to-clipboard": "^2.0.0",
26 | "gl-camera-pos-from-view-matrix": "^1.0.1",
27 | "gl-geometry": "^3.1.0",
28 | "gl-mat4": "^1.1.4",
29 | "gl-now": "^1.4.0",
30 | "gl-shader": "^4.2.0",
31 | "gl-vec3": "^1.0.3",
32 | "glslify": "^5.0.2",
33 | "orbit-camera": "^1.0.0",
34 | "pnp-gui": "0.0.3",
35 | "primitive-icosphere": "^1.0.2",
36 | "random-array": "0.0.2",
37 | "glsl-noise": "0.0.0"
38 | },
39 | "dependencies": {
40 | },
41 | "directories": {
42 | "example": "example"
43 | },
44 | "browserify": {
45 | "transform": [
46 | "glslify"
47 | ]
48 | },
49 | "repository": {
50 | "type": "git",
51 | "url": "https://github.com/Erkaman/glsl-cos-palette.git"
52 | },
53 | "homepage": "https://github.com/Erkaman/glsl-cos-palette#readme"
54 | }
55 |
--------------------------------------------------------------------------------