diff --git a/src/extension/FireShader.js b/src/extension/FireShader.js index 621c8dd..56091a7 100644 --- a/src/extension/FireShader.js +++ b/src/extension/FireShader.js @@ -124,7 +124,7 @@ var FireShader = GObject.registerClass({Properties: {}, Signals: {}}, // Get a noise value which moves vertically in time. vec2 uv = cogl_tex_coord_in[0].st * vec2(uSizeX, uSizeY) / FIRE_SCALE; uv.y += uTime * FIRE_SPEED; - float noise = perlinNoise(uv, 10.0, 5, 0.5); + float noise = noise(uv * 5.0); // Modulate noise by effect mask. vec2 effectMask = effectMask(HIDE_TIME, FADE_WIDTH, EDGE_FADE); diff --git a/src/extension/MatrixShader.js b/src/extension/MatrixShader.js index 9275a89..06afeaa 100644 --- a/src/extension/MatrixShader.js +++ b/src/extension/MatrixShader.js @@ -46,7 +46,9 @@ var MatrixShader = GObject.registerClass({Properties: {}, Signals: {}}, const tipColor = Clutter.Color.from_string(settings.get_string('matrix-tip-color'))[1]; - // This is partially based on https://www.shadertoy.com/view/ldccW4 (CC-BY-NC-SA). + // The technique for this effect was inspired by + // https://www.shadertoy.com/view/ldccW4, however the implementation is quite + // different as the letters drop only once and there is no need for a noise texture. this.set_shader_source(` // Inject some common shader snippets. @@ -72,7 +74,7 @@ var MatrixShader = GObject.registerClass({Properties: {}, Signals: {}}, vec2 block = pixelCoords/LETTER_SIZE - uv; // Choose random letter. - uv += floor(rand2(floor(rand(block)*vec2(12.9898,78.233) + LETTER_FLICKER_SPEED*uTime + 42.254))*LETTER_TILES); + uv += floor(rand(floor(rand(block)*vec2(12.9898,78.233) + LETTER_FLICKER_SPEED*uTime + 42.254))*LETTER_TILES); return texture2D(uFontTexture, uv/LETTER_TILES).r; } diff --git a/src/extension/TRexShader.js b/src/extension/TRexShader.js index 6ae0db6..57a6b86 100644 --- a/src/extension/TRexShader.js +++ b/src/extension/TRexShader.js @@ -65,7 +65,7 @@ var TRexShader = GObject.registerClass({Properties: {}, Signals: {}}, vec2 getClawUV(vec2 texCoords, float gridScale, vec2 seed) { // Shift coordinates by a random offset and make sure the have a 1:1 aspect ratio. - vec2 coords = texCoords + rand2(seed); + vec2 coords = texCoords + rand(seed); coords *= uSizeX < uSizeY ? vec2(1.0, 1.0 * uSizeY / uSizeX) : vec2(1.0 * uSizeX / uSizeY, 1.0); // Apply global scale. @@ -78,10 +78,10 @@ var TRexShader = GObject.registerClass({Properties: {}, Signals: {}}, vec2 cellID = coords-cellUV + vec2(362.456); // Add random rotation, scale and offset to each grid cell. - float scale = mix(0.8, 1.0, rand(cellID*seed*134.451)); - float offsetX = mix(0.0, 1.0 - scale, rand(cellID*seed*54.4129)); - float offsetY = mix(0.0, 1.0 - scale, rand(cellID*seed*25.3089)); - float rotation = mix(0.0, 2.0 * 3.141, rand(cellID*seed*2.99837)); + float scale = mix(0.8, 1.0, rand(cellID*seed*134.451).x); + float offsetX = mix(0.0, 1.0 - scale, rand(cellID*seed*54.4129).x); + float offsetY = mix(0.0, 1.0 - scale, rand(cellID*seed*25.3089).x); + float rotation = mix(0.0, 2.0 * 3.141, rand(cellID*seed*2.99837).x); cellUV -= vec2(offsetX, offsetY); cellUV /= scale; diff --git a/src/extension/shaderSnippets.js b/src/extension/shaderSnippets.js index 93b3876..bd04b73 100644 --- a/src/extension/shaderSnippets.js +++ b/src/extension/shaderSnippets.js @@ -33,51 +33,41 @@ function standardUniforms() { `; } -// The noise implementation is from https://www.shadertoy.com/view/3tcBzH (CC-BY-NC-SA). +// This simplex noise algorithm is based on an implementation by Inigo Quilez which is +// available under the MIT License (Copyright © 2013 Inigo Quilez). +// https://www.shadertoy.com/view/Msf3WH. function noise() { return ` - float rand(vec2 co) { - return fract(sin(dot(co.xy, vec2(12.9898,78.233))) * 43758.5453); + vec2 rand(vec2 p) { + p = vec2(dot(p,vec2(127.1,311.7)), dot(p,vec2(269.5,183.3))); + return fract(sin(p)*43758.5453123); } - vec2 rand2(vec2 co) { - return vec2(rand(co), rand(co + vec2(12.9898,78.233))); + float noiseImpl(vec2 p) { + const float K1 = 0.366025404; // (sqrt(3)-1)/2; + const float K2 = 0.211324865; // (3-sqrt(3))/6; + + vec2 i = floor(p + (p.x + p.y) * K1); + vec2 a = p - i + (i.x + i.y) * K2; + float m = step(a.y, a.x); + vec2 o = vec2(m, 1.0-m); + vec2 b = a - o + K2; + vec2 c = a - 1.0 + 2.0*K2; + vec3 h = max(0.5 - vec3(dot(a, a), dot(b, b), dot(c, c)), 0.0); + vec3 n = h * h * h * h * vec3(dot(a, -1.0 + 2.0 * rand(i + 0.0)), + dot(b, -1.0 + 2.0 * rand(i + o)), + dot(c, -1.0 + 2.0 * rand(i + 1.0))); + return dot(n, vec3(70.0)) * 0.5 + 0.5; } - float hermite(float t) { - return t * t * (3.0 - 2.0 * t); - } + float noise(vec2 p) { + mat2 m = mat2(1.6, 1.2, -1.2, 1.6); + float f = 0.5000 * noiseImpl(p); p = m*p; + f += 0.2500 * noiseImpl(p); p = m*p; + f += 0.1250 * noiseImpl(p); p = m*p; + f += 0.0625 * noiseImpl(p); p = m*p; - float noiseImpl(vec2 co, float frequency) { - vec2 v = vec2(co.x * frequency, co.y * frequency); - - float ix1 = floor(v.x); - float iy1 = floor(v.y); - float ix2 = floor(v.x + 1.0); - float iy2 = floor(v.y + 1.0); - - float fx = hermite(fract(v.x)); - float fy = hermite(fract(v.y)); - - float fade1 = mix(rand(vec2(ix1, iy1)), rand(vec2(ix2, iy1)), fx); - float fade2 = mix(rand(vec2(ix1, iy2)), rand(vec2(ix2, iy2)), fx); - - return mix(fade1, fade2, fy); - } - - float perlinNoise(vec2 co, float freq, int steps, float persistence) { - float value = 0.0; - float ampl = 1.0; - float sum = 0.0; - - for(int i=0 ; i