🚚 Move shader code to GLSL files
This commit is contained in:
@@ -3,4 +3,5 @@ AlignConsecutiveAssignments: true
|
|||||||
AlignAfterOpenBracket: Align
|
AlignAfterOpenBracket: Align
|
||||||
ContinuationIndentWidth: 2
|
ContinuationIndentWidth: 2
|
||||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||||
|
SortIncludes: false
|
||||||
ColumnLimit: 90
|
ColumnLimit: 90
|
||||||
@@ -239,7 +239,7 @@ if (utils.isInShellProcess()) {
|
|||||||
// float uProgress: A value which transitions from 0 to 1 during the entire animation.
|
// float uProgress: A value which transitions from 0 to 1 during the entire animation.
|
||||||
// float uTime: A steadily increasing value in seconds.
|
// float uTime: A steadily increasing value in seconds.
|
||||||
// vec2 uSize: The size of uTexture in pixels.
|
// vec2 uSize: The size of uTexture in pixels.
|
||||||
${shaderSnippets.standardUniforms()}
|
#include "common/uniforms.glsl"
|
||||||
|
|
||||||
// The width of the fading effect is loaded from the settings.
|
// The width of the fading effect is loaded from the settings.
|
||||||
uniform float uFadeWidth;
|
uniform float uFadeWidth;
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
// Inject some common shader snippets. It is only possible to include glsl files from the
|
||||||
|
// "common" directory. Also, the files in the "common" directory are not allowed to
|
||||||
|
// include any further files.
|
||||||
|
#include "common/uniforms.glsl"
|
||||||
|
|
||||||
|
uniform vec2 uSeed;
|
||||||
|
uniform float uShake;
|
||||||
|
uniform float uTwirl;
|
||||||
|
uniform float uSuction;
|
||||||
|
uniform float uRandomness;
|
||||||
|
|
||||||
|
const float ACTOR_SCALE = 2.0;
|
||||||
|
const float PADDING = ACTOR_SCALE / 2.0 - 0.5;
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
// The math for the whirling is inspired by this post:
|
||||||
|
// http://www.geeks3d.com/20110428/shader-library-swirl-post-processing-filter-in-glsl
|
||||||
|
// We simply inverse the progress for opening windows.
|
||||||
|
float progress = uForOpening ? 1.0 - uProgress : uProgress;
|
||||||
|
|
||||||
|
// Choose a random suction center.
|
||||||
|
vec2 center = uSeed * uRandomness + 0.5 * (1.0 - uRandomness);
|
||||||
|
vec2 coords = cogl_tex_coord_in[0].st * ACTOR_SCALE - PADDING - center;
|
||||||
|
|
||||||
|
// Add some shaking.
|
||||||
|
coords.x +=
|
||||||
|
progress * 0.05 * uShake * sin((progress + uSeed.x) * (1.0 + uSeed.x) * uShake);
|
||||||
|
coords.y +=
|
||||||
|
progress * 0.05 * uShake * cos((progress + uSeed.y) * (1.0 + uSeed.y) * uShake);
|
||||||
|
|
||||||
|
// "Suck" the texture into the center.
|
||||||
|
float dist = length(coords) / sqrt(2);
|
||||||
|
coords += progress * coords / dist * 0.5 * uSuction;
|
||||||
|
|
||||||
|
// Apply some whirling.
|
||||||
|
float angle = pow(1.0 - dist, 2.0) * uTwirl * progress;
|
||||||
|
float s = sin(angle);
|
||||||
|
float c = cos(angle);
|
||||||
|
coords = vec2(dot(coords, vec2(c, -s)), dot(coords, vec2(s, c)));
|
||||||
|
|
||||||
|
// Shell.GLSLEffect uses straight alpha. So we have to convert from premultiplied.
|
||||||
|
cogl_color_out = texture2D(uTexture, coords + center);
|
||||||
|
if (cogl_color_out.a > 0) {
|
||||||
|
cogl_color_out.rgb /= cogl_color_out.a;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fade out the window texture.
|
||||||
|
cogl_color_out.a *= 1.0 - progress;
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
// Inject some common shader snippets. It is only possible to include glsl files from the
|
||||||
|
// "common" directory. Also, the files in the "common" directory are not allowed to
|
||||||
|
// include any further files.
|
||||||
|
#include "common/uniforms.glsl"
|
||||||
|
|
||||||
|
uniform sampler2D uShardTexture;
|
||||||
|
uniform vec2 uSeed;
|
||||||
|
uniform vec2 uEpicenter;
|
||||||
|
uniform float uShardScale;
|
||||||
|
uniform float uBlowForce;
|
||||||
|
uniform float uGravity;
|
||||||
|
|
||||||
|
const float SHARD_LAYERS = 5;
|
||||||
|
const float ACTOR_SCALE = 2.0;
|
||||||
|
const float PADDING = ACTOR_SCALE / 2.0 - 0.5;
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
cogl_color_out = vec4(0, 0, 0, 0);
|
||||||
|
|
||||||
|
float progress = uForOpening ? 1.0 - uProgress : uProgress;
|
||||||
|
|
||||||
|
// Draw the individual shard layers.
|
||||||
|
for (float i = 0; i < SHARD_LAYERS; ++i) {
|
||||||
|
|
||||||
|
// To enable drawing shards outside of the window bounds, the actor was scaled
|
||||||
|
// by ACTOR_SCALE. Here we scale and move the texture coordinates so that the
|
||||||
|
// window gets drawn at the correct position again.
|
||||||
|
vec2 coords = cogl_tex_coord_in[0].st * ACTOR_SCALE - PADDING;
|
||||||
|
|
||||||
|
// Scale and rotate around our epicenter.
|
||||||
|
coords -= uEpicenter;
|
||||||
|
|
||||||
|
// Scale each layer a bit differently.
|
||||||
|
coords /= mix(1.0, 1.0 + uBlowForce * (i + 2) / SHARD_LAYERS, progress);
|
||||||
|
|
||||||
|
// Rotate each layer a bit differently.
|
||||||
|
float rotation = (mod(i, 2.0) - 0.5) * 0.2 * progress;
|
||||||
|
coords = vec2(coords.x * cos(rotation) - coords.y * sin(rotation),
|
||||||
|
coords.x * sin(rotation) + coords.y * cos(rotation));
|
||||||
|
|
||||||
|
// Move down each layer a bit.
|
||||||
|
float gravity =
|
||||||
|
(uForOpening ? -1.0 : 1.0) * uGravity * 0.1 * (i + 1) * progress * progress;
|
||||||
|
coords += vec2(0, gravity);
|
||||||
|
|
||||||
|
// Restore correct position.
|
||||||
|
coords += uEpicenter;
|
||||||
|
|
||||||
|
// Retrieve information from the shard texture for our layer.
|
||||||
|
vec2 shardCoords = (coords + uSeed) * uSize / uShardScale / 500.0;
|
||||||
|
vec2 shardMap = texture2D(uShardTexture, shardCoords).rg;
|
||||||
|
|
||||||
|
// The green channel contains a random value in [0..1] for each shard. We
|
||||||
|
// discretize this into SHARD_LAYERS bins and check if our layer falls into
|
||||||
|
// the bin of the current shard.
|
||||||
|
float shardGroup = floor(shardMap.g * SHARD_LAYERS * 0.999);
|
||||||
|
|
||||||
|
if (shardGroup == i && (shardMap.x - pow(progress + 0.1, 2)) > 0) {
|
||||||
|
cogl_color_out = texture2D(uTexture, coords);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shell.GLSLEffect uses straight alpha. So we have to convert from premultiplied.
|
||||||
|
if (cogl_color_out.a > 0) {
|
||||||
|
cogl_color_out.rgb /= cogl_color_out.a;
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
// The Shell.GLSLEffect uses straight alpha blending. This helper method allows
|
||||||
|
// compositing color values in the shader in the same way.
|
||||||
|
vec4 alphaOver(vec4 under, vec4 over) {
|
||||||
|
float alpha = over.a + under.a * (1.0 - over.a);
|
||||||
|
return vec4((over.rgb * over.a + under.rgb * under.a * (1.0 - over.a)) / alpha, alpha);
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
// This method returns a mask which smoothly transitions towards zero when approaching
|
||||||
|
// the window's borders. There is a variant which takes the transition area width in
|
||||||
|
// pixels and one which takes this as a percentage.
|
||||||
|
float getEdgeMask(vec2 uv, vec2 maxUV, float fadeWidth) {
|
||||||
|
float mask = 1.0;
|
||||||
|
mask *= smoothstep(0, 1, clamp(uv.x / fadeWidth, 0, 1));
|
||||||
|
mask *= smoothstep(0, 1, clamp(uv.y / fadeWidth, 0, 1));
|
||||||
|
mask *= smoothstep(0, 1, clamp((maxUV.x - uv.x) / fadeWidth, 0, 1));
|
||||||
|
mask *= smoothstep(0, 1, clamp((maxUV.y - uv.y) / fadeWidth, 0, 1));
|
||||||
|
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
float getAbsoluteEdgeMask(float fadePixels) {
|
||||||
|
vec2 uv = cogl_tex_coord_in[0].st * uSize;
|
||||||
|
return getEdgeMask(uv, uSize, fadePixels);
|
||||||
|
}
|
||||||
|
|
||||||
|
float getRelativeEdgeMask(float fadeAmount) {
|
||||||
|
vec2 uv = cogl_tex_coord_in[0].st;
|
||||||
|
return getEdgeMask(uv, vec2(1.0), fadeAmount);
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
float distToLine(vec2 origin, vec2 direction, vec2 point) {
|
||||||
|
vec2 perpendicular = vec2(direction.y, -direction.x);
|
||||||
|
return abs(dot(normalize(perpendicular), origin - point));
|
||||||
|
}
|
||||||
|
|
||||||
|
float getWinding(vec2 a, vec2 b) { return cross(vec3(a, 0.0), vec3(b, 0.0)).z; }
|
||||||
|
|
||||||
|
vec2 rotate(vec2 a, float angle) {
|
||||||
|
return vec2(a.x * cos(angle) - a.y * sin(angle), a.x * sin(angle) + a.y * cos(angle));
|
||||||
|
}
|
||||||
@@ -0,0 +1,207 @@
|
|||||||
|
// These noise algorithms are based on implementations by various authors from
|
||||||
|
// shadertoy.com, which are all available under the MIT License. See the respective links
|
||||||
|
// in the comments below.
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Hash without Sine //
|
||||||
|
// MIT License, https://www.shadertoy.com/view/4djSRW //
|
||||||
|
// Copyright (c) 2014 David Hoskins. //
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// 1 out, 1 in...
|
||||||
|
float hash11(float p) {
|
||||||
|
p = fract(p * .1031);
|
||||||
|
p *= p + 33.33;
|
||||||
|
p *= p + p;
|
||||||
|
return fract(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1 out, 2 in...
|
||||||
|
float hash12(vec2 p) {
|
||||||
|
vec3 p3 = fract(vec3(p.xyx) * .1031);
|
||||||
|
p3 += dot(p3, p3.yzx + 33.33);
|
||||||
|
return fract((p3.x + p3.y) * p3.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1 out, 3 in...
|
||||||
|
float hash13(vec3 p3) {
|
||||||
|
p3 = fract(p3 * .1031);
|
||||||
|
p3 += dot(p3, p3.zyx + 31.32);
|
||||||
|
return fract((p3.x + p3.y) * p3.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2 out, 1 in...
|
||||||
|
vec2 hash21(float p) {
|
||||||
|
vec3 p3 = fract(vec3(p) * vec3(.1031, .1030, .0973));
|
||||||
|
p3 += dot(p3, p3.yzx + 33.33);
|
||||||
|
return fract((p3.xx + p3.yz) * p3.zy);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2 out, 2 in...
|
||||||
|
vec2 hash22(vec2 p) {
|
||||||
|
vec3 p3 = fract(vec3(p.xyx) * vec3(.1031, .1030, .0973));
|
||||||
|
p3 += dot(p3, p3.yzx + 33.33);
|
||||||
|
return fract((p3.xx + p3.yz) * p3.zy);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2 out, 3 in...
|
||||||
|
vec2 hash23(vec3 p3) {
|
||||||
|
p3 = fract(p3 * vec3(.1031, .1030, .0973));
|
||||||
|
p3 += dot(p3, p3.yzx + 33.33);
|
||||||
|
return fract((p3.xx + p3.yz) * p3.zy);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3 out, 1 in...
|
||||||
|
vec3 hash31(float p) {
|
||||||
|
vec3 p3 = fract(vec3(p) * vec3(.1031, .1030, .0973));
|
||||||
|
p3 += dot(p3, p3.yzx + 33.33);
|
||||||
|
return fract((p3.xxy + p3.yzz) * p3.zyx);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3 out, 2 in...
|
||||||
|
vec3 hash32(vec2 p) {
|
||||||
|
vec3 p3 = fract(vec3(p.xyx) * vec3(.1031, .1030, .0973));
|
||||||
|
p3 += dot(p3, p3.yxz + 33.33);
|
||||||
|
return fract((p3.xxy + p3.yzz) * p3.zyx);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3 out, 3 in...
|
||||||
|
vec3 hash33(vec3 p3) {
|
||||||
|
p3 = fract(p3 * vec3(.1031, .1030, .0973));
|
||||||
|
p3 += dot(p3, p3.yxz + 33.33);
|
||||||
|
return fract((p3.xxy + p3.yxx) * p3.zyx);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4 out, 1 in...
|
||||||
|
vec4 hash41(float p) {
|
||||||
|
vec4 p4 = fract(vec4(p) * vec4(.1031, .1030, .0973, .1099));
|
||||||
|
p4 += dot(p4, p4.wzxy + 33.33);
|
||||||
|
return fract((p4.xxyz + p4.yzzw) * p4.zywx);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4 out, 2 in...
|
||||||
|
vec4 hash42(vec2 p) {
|
||||||
|
vec4 p4 = fract(vec4(p.xyxy) * vec4(.1031, .1030, .0973, .1099));
|
||||||
|
p4 += dot(p4, p4.wzxy + 33.33);
|
||||||
|
return fract((p4.xxyz + p4.yzzw) * p4.zywx);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4 out, 3 in...
|
||||||
|
vec4 hash43(vec3 p) {
|
||||||
|
vec4 p4 = fract(vec4(p.xyzx) * vec4(.1031, .1030, .0973, .1099));
|
||||||
|
p4 += dot(p4, p4.wzxy + 33.33);
|
||||||
|
return fract((p4.xxyz + p4.yzzw) * p4.zywx);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4 out, 4 in...
|
||||||
|
vec4 hash44(vec4 p4) {
|
||||||
|
p4 = fract(p4 * vec4(.1031, .1030, .0973, .1099));
|
||||||
|
p4 += dot(p4, p4.wzxy + 33.33);
|
||||||
|
return fract((p4.xxyz + p4.yzzw) * p4.zywx);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// 2D Simplex Noise //
|
||||||
|
// MIT License, https://www.shadertoy.com/view/Msf3WH //
|
||||||
|
// Copyright © 2013 Inigo Quilez //
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
float simplex2D(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 * hash22(i + 0.0)), dot(b, -1.0 + 2.0 * hash22(i + o)),
|
||||||
|
dot(c, -1.0 + 2.0 * hash22(i + 1.0)));
|
||||||
|
return 0.5 + 0.5 * dot(n, vec3(70.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
float simplex2DFractal(vec2 p) {
|
||||||
|
mat2 m = mat2(1.6, 1.2, -1.2, 1.6);
|
||||||
|
float f = 0.5000 * simplex2D(p);
|
||||||
|
p = m * p;
|
||||||
|
f += 0.2500 * simplex2D(p);
|
||||||
|
p = m * p;
|
||||||
|
f += 0.1250 * simplex2D(p);
|
||||||
|
p = m * p;
|
||||||
|
f += 0.0625 * simplex2D(p);
|
||||||
|
p = m * p;
|
||||||
|
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// 3D Simplex Noise //
|
||||||
|
// MIT License, https://www.shadertoy.com/view/XsX3zB //
|
||||||
|
// Copyright © 2013 Nikita Miropolskiy //
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
float simplex3D(vec3 p) {
|
||||||
|
|
||||||
|
// skew constants for 3D simplex functions
|
||||||
|
const float F3 = 0.3333333;
|
||||||
|
const float G3 = 0.1666667;
|
||||||
|
|
||||||
|
// 1. find current tetrahedron T and it's four vertices
|
||||||
|
// s, s+i1, s+i2, s+1.0 - absolute skewed (integer) coordinates of T vertices
|
||||||
|
// x, x1, x2, x3 - unskewed coordinates of p relative to each of T vertice
|
||||||
|
|
||||||
|
// calculate s and x
|
||||||
|
vec3 s = floor(p + dot(p, vec3(F3)));
|
||||||
|
vec3 x = p - s + dot(s, vec3(G3));
|
||||||
|
|
||||||
|
// calculate i1 and i2
|
||||||
|
vec3 e = step(vec3(0.0), x - x.yzx);
|
||||||
|
vec3 i1 = e * (1.0 - e.zxy);
|
||||||
|
vec3 i2 = 1.0 - e.zxy * (1.0 - e);
|
||||||
|
|
||||||
|
// x1, x2, x3
|
||||||
|
vec3 x1 = x - i1 + G3;
|
||||||
|
vec3 x2 = x - i2 + 2.0 * G3;
|
||||||
|
vec3 x3 = x - 1.0 + 3.0 * G3;
|
||||||
|
|
||||||
|
// 2. find four surflets and store them in d
|
||||||
|
vec4 w, d;
|
||||||
|
|
||||||
|
// calculate surflet weights
|
||||||
|
w.x = dot(x, x);
|
||||||
|
w.y = dot(x1, x1);
|
||||||
|
w.z = dot(x2, x2);
|
||||||
|
w.w = dot(x3, x3);
|
||||||
|
|
||||||
|
// w fades from 0.6 at the center of the surflet to 0.0 at the margin
|
||||||
|
w = max(0.6 - w, 0.0);
|
||||||
|
|
||||||
|
// calculate surflet components
|
||||||
|
d.x = dot(-0.5 + hash33(s), x);
|
||||||
|
d.y = dot(-0.5 + hash33(s + i1), x1);
|
||||||
|
d.z = dot(-0.5 + hash33(s + i2), x2);
|
||||||
|
d.w = dot(-0.5 + hash33(s + 1.0), x3);
|
||||||
|
|
||||||
|
// multiply d by w^4
|
||||||
|
w *= w;
|
||||||
|
w *= w;
|
||||||
|
d *= w;
|
||||||
|
|
||||||
|
// 3. return the sum of the four surflets
|
||||||
|
return dot(d, vec4(52.0)) * 0.5 + 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
// directional artifacts can be reduced by rotating each octave
|
||||||
|
float simplex3DFractal(vec3 m) {
|
||||||
|
|
||||||
|
// const matrices for 3D rotation
|
||||||
|
const mat3 rot1 = mat3(-0.37, 0.36, 0.85, -0.14, -0.93, 0.34, 0.92, 0.01, 0.4);
|
||||||
|
const mat3 rot2 = mat3(-0.55, -0.39, 0.74, 0.33, -0.91, -0.24, 0.77, 0.12, 0.63);
|
||||||
|
const mat3 rot3 = mat3(-0.71, 0.52, -0.47, -0.08, -0.72, -0.68, -0.7, -0.45, 0.56);
|
||||||
|
|
||||||
|
return 0.5333333 * simplex3D(m * rot1) + 0.2666667 * simplex3D(2.0 * m * rot2) +
|
||||||
|
0.1333333 * simplex3D(4.0 * m * rot3) + 0.0666667 * simplex3D(8.0 * m);
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
// These should be included in every shader.
|
||||||
|
// uForOpening: True if a window-open animation is ongoing, false otherwise.
|
||||||
|
// uTexture: Contains the texture of the window.
|
||||||
|
// uProgress: A value which transitions from 0 to 1 during the entire animation.
|
||||||
|
// uTime: A steadily increasing value in seconds.
|
||||||
|
// uSize: The size of uTexture in pixels.
|
||||||
|
uniform bool uForOpening;
|
||||||
|
uniform sampler2D uTexture;
|
||||||
|
uniform float uProgress;
|
||||||
|
uniform float uTime;
|
||||||
|
uniform vec2 uSize;
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
// Inject some common shader snippets. It is only possible to include glsl files from the
|
||||||
|
// "common" directory. Also, the files in the "common" directory are not allowed to
|
||||||
|
// include any further files.
|
||||||
|
#include "common/uniforms.glsl"
|
||||||
|
#include "common/noise.glsl"
|
||||||
|
#include "common/edgeMask.glsl"
|
||||||
|
|
||||||
|
uniform vec3 uColor;
|
||||||
|
uniform float uScale;
|
||||||
|
|
||||||
|
const float FADE_IN_TIME = 0.3;
|
||||||
|
const float FADE_OUT_TIME = 0.6;
|
||||||
|
const float HEART_FADE_TIME = 0.3;
|
||||||
|
const float EDGE_FADE_WIDTH = 50;
|
||||||
|
|
||||||
|
// This method returns two values:
|
||||||
|
// result.x: A mask for the particles.
|
||||||
|
// result.y: The opacity of the fading window.
|
||||||
|
vec2 getMasks() {
|
||||||
|
float fadeInProgress = clamp(uProgress / FADE_IN_TIME, 0, 1);
|
||||||
|
float fadeOutProgress = clamp((uProgress - FADE_IN_TIME) / FADE_OUT_TIME, 0, 1);
|
||||||
|
float heartProgress =
|
||||||
|
clamp((uProgress - (1.0 - HEART_FADE_TIME)) / HEART_FADE_TIME, 0, 1);
|
||||||
|
|
||||||
|
// Compute mask for the "atom" particles.
|
||||||
|
float dist = length(cogl_tex_coord_in[0].st - 0.5) * 4.0;
|
||||||
|
float atomMask = smoothstep(0.0, 1.0, (fadeInProgress * 2.0 - dist + 1.0));
|
||||||
|
atomMask *= fadeInProgress;
|
||||||
|
atomMask *= smoothstep(1.0, 0.0, fadeOutProgress);
|
||||||
|
|
||||||
|
// Fade-out the masks at the window edges.
|
||||||
|
float edgeFade = getAbsoluteEdgeMask(EDGE_FADE_WIDTH);
|
||||||
|
atomMask *= edgeFade;
|
||||||
|
|
||||||
|
float heartMask = getRelativeEdgeMask(0.5);
|
||||||
|
heartMask = 3.0 * pow(heartMask, 5);
|
||||||
|
heartMask *= fadeOutProgress;
|
||||||
|
heartMask *= 1.0 - heartProgress;
|
||||||
|
atomMask = clamp(heartMask + atomMask, 0, 1);
|
||||||
|
|
||||||
|
// Compute fading window opacity.
|
||||||
|
float windowMask = pow(1.0 - fadeOutProgress, 2.0);
|
||||||
|
|
||||||
|
if (uForOpening) {
|
||||||
|
windowMask = 1.0 - windowMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
return vec2(atomMask, windowMask);
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
vec2 masks = getMasks();
|
||||||
|
vec4 windowColor = texture2D(uTexture, cogl_tex_coord_in[0].st);
|
||||||
|
|
||||||
|
// Shell.GLSLEffect uses straight alpha. So we have to convert from premultiplied.
|
||||||
|
if (windowColor.a > 0) {
|
||||||
|
windowColor.rgb /= windowColor.a;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dissolve window to effect color / transparency.
|
||||||
|
cogl_color_out.rgb = mix(uColor, windowColor.rgb, 0.2 * masks.y + 0.8);
|
||||||
|
cogl_color_out.a = windowColor.a * masks.y;
|
||||||
|
|
||||||
|
vec2 scaledUV = (cogl_tex_coord_in[0].st - 0.5) * (1.0 + 0.1 * uProgress);
|
||||||
|
scaledUV /= uScale;
|
||||||
|
|
||||||
|
// Add molecule particles.
|
||||||
|
vec2 uv = scaledUV + vec2(0, 0.1 * uTime);
|
||||||
|
uv *= 0.010598 * vec2(0.5 * uSize.x, uSize.y);
|
||||||
|
float particles = 0.2 * pow((simplex3D(vec3(uv, 0.0 * uTime))), 3.0);
|
||||||
|
|
||||||
|
// Add more molecule particles.
|
||||||
|
for (int i = 1; i <= 3; ++i) {
|
||||||
|
vec2 uv = scaledUV * 0.12154 / pow(1.5, i) * uSize;
|
||||||
|
float atoms = simplex3D(vec3(uv, 2.0 * uTime / i));
|
||||||
|
particles += 0.5 * pow(0.2 * (1.0 / (1.0 - atoms) - 1.0), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
cogl_color_out.rgb += uColor * particles * masks.x;
|
||||||
|
cogl_color_out.a += particles * masks.x;
|
||||||
|
|
||||||
|
// These are pretty useful for understanding how this works.
|
||||||
|
// cogl_color_out = vec4(masks, 0.0, 1.0);
|
||||||
|
// cogl_color_out = vec4(vec3(masks.x), 1.0);
|
||||||
|
// cogl_color_out = vec4(vec3(masks.y), 1.0);
|
||||||
|
// cogl_color_out = vec4(vec3(particles), 1.0);
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
// Inject some common shader snippets. It is only possible to include glsl files from the
|
||||||
|
// "common" directory. Also, the files in the "common" directory are not allowed to
|
||||||
|
// include any further files.
|
||||||
|
#include "common/uniforms.glsl"
|
||||||
|
#include "common/noise.glsl"
|
||||||
|
#include "common/edgeMask.glsl"
|
||||||
|
|
||||||
|
uniform vec3 uColor;
|
||||||
|
uniform float uScale;
|
||||||
|
|
||||||
|
const float SHOWER_TIME = 0.3;
|
||||||
|
const float SHOWER_WIDTH = 0.3;
|
||||||
|
const float STREAK_TIME = 0.6;
|
||||||
|
const float EDGE_FADE = 50;
|
||||||
|
|
||||||
|
// This method returns four values:
|
||||||
|
// result.x: A mask for the particles which lead the shower.
|
||||||
|
// result.y: A mask for the streaks which follow the shower particles.
|
||||||
|
// result.z: A mask for the final "atom" particles.
|
||||||
|
// result.w: The opacity of the fading window.
|
||||||
|
vec4 getMasks() {
|
||||||
|
float showerProgress = uProgress / SHOWER_TIME;
|
||||||
|
float streakProgress = clamp((uProgress - SHOWER_TIME) / STREAK_TIME, 0, 1);
|
||||||
|
float fadeProgress = clamp((uProgress - SHOWER_TIME) / (1.0 - SHOWER_TIME), 0, 1);
|
||||||
|
|
||||||
|
// Gradient from top to bottom.
|
||||||
|
float t = cogl_tex_coord_in[0].t;
|
||||||
|
|
||||||
|
// A smooth gradient which moves to the bottom within the showerProgress.
|
||||||
|
float showerMask =
|
||||||
|
smoothstep(1, 0, abs(showerProgress - t - SHOWER_WIDTH) / SHOWER_WIDTH);
|
||||||
|
|
||||||
|
// This is 1 above the streak mask.
|
||||||
|
float streakMask = (showerProgress - t - SHOWER_WIDTH) > 0 ? 1 : 0;
|
||||||
|
|
||||||
|
// Compute mask for the "atom" particles.
|
||||||
|
float atomMask = getRelativeEdgeMask(0.2);
|
||||||
|
atomMask = max(0, atomMask - showerMask);
|
||||||
|
atomMask *= streakMask;
|
||||||
|
atomMask *= sqrt(1 - fadeProgress * fadeProgress);
|
||||||
|
|
||||||
|
// Make some particles visible in the streaks.
|
||||||
|
showerMask += 0.05 * streakMask;
|
||||||
|
|
||||||
|
// Add shower mask to streak mask.
|
||||||
|
streakMask = max(streakMask, showerMask);
|
||||||
|
|
||||||
|
// Fade-out the masks at the window edges.
|
||||||
|
float edgeFade = getAbsoluteEdgeMask(EDGE_FADE);
|
||||||
|
streakMask *= edgeFade;
|
||||||
|
showerMask *= edgeFade;
|
||||||
|
|
||||||
|
// Fade-out the masks from top to bottom.
|
||||||
|
float fade = smoothstep(0.0, 1.0, 1.0 + t - 2.0 * streakProgress);
|
||||||
|
streakMask *= fade;
|
||||||
|
showerMask *= fade;
|
||||||
|
|
||||||
|
// Compute fading window opacity.
|
||||||
|
float windowMask = pow(1.0 - fadeProgress, 2.0);
|
||||||
|
|
||||||
|
if (uForOpening) {
|
||||||
|
windowMask = 1.0 - windowMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
return vec4(showerMask, streakMask, atomMask, windowMask);
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
vec4 masks = getMasks();
|
||||||
|
vec4 windowColor = texture2D(uTexture, cogl_tex_coord_in[0].st);
|
||||||
|
|
||||||
|
// Shell.GLSLEffect uses straight alpha. So we have to convert from premultiplied.
|
||||||
|
if (windowColor.a > 0) {
|
||||||
|
windowColor.rgb /= windowColor.a;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dissolve window to effect color / transparency.
|
||||||
|
cogl_color_out.rgb = mix(uColor, windowColor.rgb, 0.5 * masks.w + 0.5);
|
||||||
|
cogl_color_out.a = windowColor.a * masks.w;
|
||||||
|
|
||||||
|
// Add leading shower particles.
|
||||||
|
vec2 showerUV = cogl_tex_coord_in[0].st + vec2(0, -0.7 * uProgress / SHOWER_TIME);
|
||||||
|
showerUV *= 0.02 * uSize / uScale;
|
||||||
|
float shower = pow(simplex2D(showerUV), 10.0);
|
||||||
|
cogl_color_out.rgb += uColor * shower * masks.x;
|
||||||
|
cogl_color_out.a += shower * masks.x;
|
||||||
|
|
||||||
|
// Add trailing streak lines.
|
||||||
|
vec2 streakUV = cogl_tex_coord_in[0].st + vec2(0, -uProgress / SHOWER_TIME);
|
||||||
|
streakUV *= vec2(0.05 * uSize.x, 0.001 * uSize.y) / uScale;
|
||||||
|
float streaks = simplex2DFractal(streakUV) * 0.5;
|
||||||
|
cogl_color_out.rgb += uColor * streaks * masks.y;
|
||||||
|
cogl_color_out.a += streaks * masks.y;
|
||||||
|
|
||||||
|
// Add glimmering atoms.
|
||||||
|
vec2 atomUV = cogl_tex_coord_in[0].st + vec2(0, -0.025 * uProgress / SHOWER_TIME);
|
||||||
|
atomUV *= 0.2 * uSize / uScale;
|
||||||
|
float atoms = pow((simplex3D(vec3(atomUV, uTime))), 5.0);
|
||||||
|
cogl_color_out.rgb += uColor * atoms * masks.z;
|
||||||
|
cogl_color_out.a += atoms * masks.z;
|
||||||
|
|
||||||
|
// These are pretty useful for understanding how this works.
|
||||||
|
// cogl_color_out = vec4(masks.rgb, 1.0);
|
||||||
|
// cogl_color_out = vec4(vec3(masks.x), 1.0);
|
||||||
|
// cogl_color_out = vec4(vec3(masks.y), 1.0);
|
||||||
|
// cogl_color_out = vec4(vec3(masks.z), 1.0);
|
||||||
|
// cogl_color_out = vec4(vec3(masks.w), 1.0);
|
||||||
|
// cogl_color_out = vec4(vec3(shower), 1.0);
|
||||||
|
// cogl_color_out = vec4(vec3(streaks), 1.0);
|
||||||
|
// cogl_color_out = vec4(vec3(atoms), 1.0);
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
// Inject some common shader snippets. It is only possible to include glsl files from the
|
||||||
|
// "common" directory. Also, the files in the "common" directory are not allowed to
|
||||||
|
// include any further files.
|
||||||
|
#include "common/uniforms.glsl"
|
||||||
|
#include "common/compositing.glsl"
|
||||||
|
#include "common/edgeMask.glsl"
|
||||||
|
#include "common/noise.glsl"
|
||||||
|
|
||||||
|
uniform bool u3DNoise;
|
||||||
|
uniform float uScale;
|
||||||
|
uniform float uMovementSpeed;
|
||||||
|
uniform vec4 uGradient1;
|
||||||
|
uniform vec4 uGradient2;
|
||||||
|
uniform vec4 uGradient3;
|
||||||
|
uniform vec4 uGradient4;
|
||||||
|
uniform vec4 uGradient5;
|
||||||
|
|
||||||
|
// These may be configurable in the future.
|
||||||
|
const float EDGE_FADE = 70;
|
||||||
|
const float FADE_WIDTH = 0.1;
|
||||||
|
const float HIDE_TIME = 0.4;
|
||||||
|
|
||||||
|
// This maps the input value from [0..1] to a color from the gradient.
|
||||||
|
vec4 getFireColor(float v) {
|
||||||
|
const float steps[5] = float[](0.0, 0.2, 0.35, 0.5, 0.8);
|
||||||
|
vec4 colors[5] = vec4[](uGradient1, uGradient2, uGradient3, uGradient4, uGradient5);
|
||||||
|
|
||||||
|
if (v < steps[0]) {
|
||||||
|
return colors[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; ++i) {
|
||||||
|
if (v <= steps[i + 1]) {
|
||||||
|
return mix(colors[i], colors[i + 1],
|
||||||
|
vec4(v - steps[i]) / (steps[i + 1] - steps[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return colors[4];
|
||||||
|
}
|
||||||
|
|
||||||
|
// This method requires the uniforms from standardUniforms() to be available.
|
||||||
|
// It returns two values: The first is an alpha value which can be used for the window
|
||||||
|
// texture. This gradually dissolves the window from top to bottom. The second can be used
|
||||||
|
// to mask any effect, it will be most opaque where the window is currently fading and
|
||||||
|
// gradually dissolve to zero over time.
|
||||||
|
// hideTime: A value in [0..1]. It determines the percentage of the animation which
|
||||||
|
// is spent for hiding the window. 1-hideTime will be spent thereafter for
|
||||||
|
// dissolving the effect mask.
|
||||||
|
// fadeWidth: The relative size of the window-hiding gradient in [0..1].
|
||||||
|
// edgeFadeWidth: The pixel width of the effect fading range at the edges of the window.
|
||||||
|
vec2 effectMask(float hideTime, float fadeWidth, float edgeFadeWidth) {
|
||||||
|
float burnProgress = clamp(uProgress / hideTime, 0, 1);
|
||||||
|
float afterBurnProgress = clamp((uProgress - hideTime) / (1 - hideTime), 0, 1);
|
||||||
|
|
||||||
|
// Gradient from top to bottom.
|
||||||
|
float t = cogl_tex_coord_in[0].t * (1 - fadeWidth);
|
||||||
|
|
||||||
|
// Visible part of the window. Gradually dissolves towards the bottom.
|
||||||
|
float windowMask = 1 - clamp((burnProgress - t) / fadeWidth, 0, 1);
|
||||||
|
|
||||||
|
// Gradient from top burning window.
|
||||||
|
float effectMask = clamp(t * (1 - windowMask) / burnProgress, 0, 1);
|
||||||
|
|
||||||
|
// Fade-out when the window burned down.
|
||||||
|
if (uProgress > hideTime) {
|
||||||
|
float fade = sqrt(1 - afterBurnProgress * afterBurnProgress);
|
||||||
|
effectMask *= mix(1, 1 - t, afterBurnProgress) * fade;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fade at window borders.
|
||||||
|
effectMask *= getAbsoluteEdgeMask(edgeFadeWidth);
|
||||||
|
|
||||||
|
if (uForOpening) {
|
||||||
|
windowMask = 1.0 - windowMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
return vec2(windowMask, effectMask);
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
// Get a noise value which moves vertically in time.
|
||||||
|
vec2 uv = cogl_tex_coord_in[0].st * uSize / vec2(400, 600) / uScale;
|
||||||
|
uv.y += uTime * uMovementSpeed;
|
||||||
|
|
||||||
|
float noise = u3DNoise ? simplex3DFractal(vec3(uv * 4.0, uTime* uMovementSpeed * 1.5))
|
||||||
|
: simplex2DFractal(uv * 4.0);
|
||||||
|
|
||||||
|
// Modulate noise by effect mask.
|
||||||
|
vec2 effectMask = effectMask(HIDE_TIME, FADE_WIDTH, EDGE_FADE);
|
||||||
|
noise *= effectMask.y;
|
||||||
|
|
||||||
|
// Map noise value to color.
|
||||||
|
vec4 fire = getFireColor(noise);
|
||||||
|
|
||||||
|
// Get the window texture.
|
||||||
|
cogl_color_out = texture2D(uTexture, cogl_tex_coord_in[0].st);
|
||||||
|
|
||||||
|
// Shell.GLSLEffect uses straight alpha. So we have to convert from premultiplied.
|
||||||
|
if (cogl_color_out.a > 0) {
|
||||||
|
cogl_color_out.rgb /= cogl_color_out.a;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fade the window according to the effect mask.
|
||||||
|
cogl_color_out.a *= effectMask.x;
|
||||||
|
|
||||||
|
// Add the fire to the window.
|
||||||
|
cogl_color_out = alphaOver(cogl_color_out, fire);
|
||||||
|
|
||||||
|
// These are pretty useful for understanding how this works.
|
||||||
|
// cogl_color_out = vec4(vec3(noise), 1);
|
||||||
|
// cogl_color_out = vec4(vec3(effectMask.x), 1);
|
||||||
|
// cogl_color_out = vec4(vec3(effectMask.y), 1);
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
// Inject some common shader snippets. It is only possible to include glsl files from the
|
||||||
|
// "common" directory. Also, the files in the "common" directory are not allowed to
|
||||||
|
// include any further files.
|
||||||
|
#include "common/uniforms.glsl"
|
||||||
|
#include "common/noise.glsl"
|
||||||
|
|
||||||
|
uniform bool uAdditiveBlending;
|
||||||
|
uniform vec2 uSeed;
|
||||||
|
uniform float uScale;
|
||||||
|
uniform float uLineWidth;
|
||||||
|
uniform vec4 uGlowColor;
|
||||||
|
uniform vec4 uLineColor;
|
||||||
|
|
||||||
|
// This methods generates a procedural hexagonal pattern. It returns four values:
|
||||||
|
// result.xy: This contains cell-relative coordinates for the given point.
|
||||||
|
// [0, 0] is in the center of a cell, [0, 1] at the upper edge,
|
||||||
|
// [sqrt(4.0 / 3.0), 0] at the right tip and so on.
|
||||||
|
// result.z: This is the distance to the closest edge. This is used for shrinking
|
||||||
|
// of the tiles and the sharp overlay lines.
|
||||||
|
// result.w: This is the distance to the closest cell center. This is used for
|
||||||
|
// the glow effect.
|
||||||
|
vec4 getHexagons(vec2 p) {
|
||||||
|
|
||||||
|
// Length of a cell's edge.
|
||||||
|
const float edgeLength = sqrt(4.0 / 3.0);
|
||||||
|
|
||||||
|
// The hexgrid repeats after this distance.
|
||||||
|
const vec2 scale = vec2(3.0 * edgeLength, 2.0);
|
||||||
|
|
||||||
|
// This is a repeating grid of scale-sized cells. Y-values are in the
|
||||||
|
// interval [-1...1], X-value in [-1.5*edgeLength...1.5*edgeLength].
|
||||||
|
vec2 a = mod(p, scale) - scale * 0.5;
|
||||||
|
vec2 aAbs = abs(a);
|
||||||
|
|
||||||
|
// This is the same as above, but offset by half scale.
|
||||||
|
vec2 b = mod(p + scale * 0.5, scale) - scale * 0.5;
|
||||||
|
vec2 bAbs = abs(b);
|
||||||
|
|
||||||
|
// Distance to closer edge, diagonally or horizontally.
|
||||||
|
// Once for cell set A and once for cell set B.
|
||||||
|
float distA = max(aAbs.x / edgeLength + aAbs.y * 0.5, aAbs.y);
|
||||||
|
float distB = max(bAbs.x / edgeLength + bAbs.y * 0.5, bAbs.y);
|
||||||
|
|
||||||
|
// Minimum of both is distance to closest edge.
|
||||||
|
float dist = 1.0 - min(distA, distB);
|
||||||
|
|
||||||
|
// We use the radial distance to the center for glow.
|
||||||
|
float glow = min(dot(a, a), dot(b, b)) / 1.5;
|
||||||
|
|
||||||
|
// Take cell-relative coordinates from the closer cell.
|
||||||
|
vec2 cellCoords = distA < distB ? a : b;
|
||||||
|
|
||||||
|
return vec4(cellCoords, dist, glow);
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
// We simply inverse the progress for opening windows.
|
||||||
|
float progress = uForOpening ? 1.0 - uProgress : uProgress;
|
||||||
|
|
||||||
|
// Add some smooth noise to the progress so that not every tile behaves the
|
||||||
|
// same.
|
||||||
|
float noise = simplex2D(cogl_tex_coord_in[0].st + uSeed);
|
||||||
|
progress = clamp(mix(noise - 1.0, noise + 1.0, progress), 0.0, 1.0);
|
||||||
|
|
||||||
|
// glowProgress fades in in the first half of the animation, tileProgress fades
|
||||||
|
// in in the second half.
|
||||||
|
float glowProgress = smoothstep(0, 1, clamp(progress / 0.5, 0, 1));
|
||||||
|
float tileProgress = smoothstep(0, 1, clamp((progress - 0.5) / 0.5, 0, 1));
|
||||||
|
|
||||||
|
vec2 texScale = 0.1 * uSize / uScale;
|
||||||
|
vec4 hex = getHexagons(cogl_tex_coord_in[0].st * texScale);
|
||||||
|
|
||||||
|
if (tileProgress > hex.z) {
|
||||||
|
|
||||||
|
// Crop outer parts of the shrinking tiles.
|
||||||
|
cogl_color_out.a = 0.0;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// Make the tiles shrink by offsetting the texture lookup towards the edge
|
||||||
|
// of the cell.
|
||||||
|
vec2 lookupOffset = tileProgress * hex.xy / texScale / (1.0 - tileProgress);
|
||||||
|
cogl_color_out = texture2D(uTexture, cogl_tex_coord_in[0].st + lookupOffset);
|
||||||
|
|
||||||
|
// Shell.GLSLEffect uses straight alpha. So we have to convert from premultiplied.
|
||||||
|
if (cogl_color_out.a > 0) {
|
||||||
|
cogl_color_out.rgb /= cogl_color_out.a;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 glow = uGlowColor;
|
||||||
|
vec4 line = uLineColor;
|
||||||
|
|
||||||
|
// For the glow, we accumulate a few exponentially scaled versions of hex.w.
|
||||||
|
glow.a *= pow(hex.w, 20.0) * 10.0 + pow(hex.w, 10.0) * 5.0 + pow(hex.w, 2.0) * 0.5;
|
||||||
|
|
||||||
|
// Using step(uLineWidth, hex.z) would be simpler, but the below creates some
|
||||||
|
// fake antialiasing.
|
||||||
|
line.a *= 1.0 - smoothstep(uLineWidth * 0.02 * 0.5, uLineWidth * 0.02, hex.z);
|
||||||
|
|
||||||
|
// Fade in the glowing lines.
|
||||||
|
glow.a *= glowProgress;
|
||||||
|
line.a *= glowProgress;
|
||||||
|
|
||||||
|
// Do not add the hexagon lines onto transparent parts of the window.
|
||||||
|
glow *= cogl_color_out.a;
|
||||||
|
line *= cogl_color_out.a;
|
||||||
|
|
||||||
|
if (uAdditiveBlending) {
|
||||||
|
cogl_color_out.rgb += glow.rgb * glow.a;
|
||||||
|
cogl_color_out.rgb += line.rgb * line.a;
|
||||||
|
} else {
|
||||||
|
cogl_color_out.rgb = mix(cogl_color_out.rgb, glow.rgb, glow.a);
|
||||||
|
cogl_color_out.rgb = mix(cogl_color_out.rgb, line.rgb, line.a);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
// Inject some common shader snippets. It is only possible to include glsl files from the
|
||||||
|
// "common" directory. Also, the files in the "common" directory are not allowed to
|
||||||
|
// include any further files.
|
||||||
|
#include "common/uniforms.glsl"
|
||||||
|
#include "common/noise.glsl"
|
||||||
|
#include "common/edgeMask.glsl"
|
||||||
|
#include "common/compositing.glsl"
|
||||||
|
|
||||||
|
uniform sampler2D uFontTexture;
|
||||||
|
uniform vec3 uTrailColor;
|
||||||
|
uniform vec3 uTipColor;
|
||||||
|
uniform float uLetterSize;
|
||||||
|
uniform float uRandomness;
|
||||||
|
uniform float uOverShoot;
|
||||||
|
|
||||||
|
// These may be configurable in the future.
|
||||||
|
const float EDGE_FADE = 30;
|
||||||
|
const float FADE_WIDTH = 150;
|
||||||
|
const float TRAIL_LENGTH = 0.2;
|
||||||
|
const float FINAL_FADE_START_TIME = 0.8;
|
||||||
|
const float LETTER_TILES = 16.0;
|
||||||
|
const float LETTER_FLICKER_SPEED = 2.0;
|
||||||
|
|
||||||
|
// This returns a flickering grid of random letters.
|
||||||
|
float getText(vec2 fragCoord) {
|
||||||
|
vec2 pixelCoords = fragCoord * uSize;
|
||||||
|
vec2 uv = mod(pixelCoords.xy, uLetterSize) / uLetterSize;
|
||||||
|
vec2 block = pixelCoords / uLetterSize - uv;
|
||||||
|
|
||||||
|
// Choose random letter.
|
||||||
|
uv += floor(hash22(floor(hash22(block) * vec2(12.9898, 78.233) +
|
||||||
|
LETTER_FLICKER_SPEED * uTime + 42.254)) *
|
||||||
|
LETTER_TILES);
|
||||||
|
|
||||||
|
return texture2D(uFontTexture, uv / LETTER_TILES).r;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This returns two values: The first are gradients for the "raindrops" which move
|
||||||
|
// from top to bottom. This is used for fading the letters. The second value is set
|
||||||
|
// to one below each drop and to zero above it. This second value is used for fading
|
||||||
|
// the window texture.
|
||||||
|
vec2 getRain(vec2 fragCoord) {
|
||||||
|
float column = cogl_tex_coord_in[0].x * uSize.x;
|
||||||
|
column -= mod(column, uLetterSize);
|
||||||
|
|
||||||
|
float delay = fract(sin(column) * 78.233) * mix(0.0, 1.0, uRandomness);
|
||||||
|
float speed = fract(cos(column) * 12.989) * mix(0.0, 0.3, uRandomness) + 1.5;
|
||||||
|
|
||||||
|
float distToDrop = (uProgress * 2 - delay) * speed - cogl_tex_coord_in[0].y;
|
||||||
|
|
||||||
|
float rainAlpha = distToDrop >= 0 ? exp(-distToDrop / TRAIL_LENGTH) : 0;
|
||||||
|
float windowAlpha = 1 - clamp(uSize.y * distToDrop, 0, FADE_WIDTH) / FADE_WIDTH;
|
||||||
|
|
||||||
|
// Fade at window borders.
|
||||||
|
rainAlpha *= getAbsoluteEdgeMask(EDGE_FADE);
|
||||||
|
|
||||||
|
// Add some variation to the drop start and end position.
|
||||||
|
float shorten =
|
||||||
|
fract(sin(column + 42.0) * 33.423) * mix(0.0, uOverShoot * 0.25, uRandomness);
|
||||||
|
rainAlpha *= smoothstep(0, 1, clamp(cogl_tex_coord_in[0].y / shorten, 0, 1));
|
||||||
|
rainAlpha *= smoothstep(0, 1, clamp((1.0 - cogl_tex_coord_in[0].y) / shorten, 0, 1));
|
||||||
|
|
||||||
|
if (uForOpening) {
|
||||||
|
windowAlpha = 1.0 - windowAlpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
return vec2(rainAlpha, windowAlpha);
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
vec2 coords = cogl_tex_coord_in[0].st;
|
||||||
|
coords.y = coords.y * (uOverShoot + 1.0) - uOverShoot * 0.5;
|
||||||
|
|
||||||
|
// Get a cool matrix effect. See comments for those methods above.
|
||||||
|
vec2 rainMask = getRain(coords);
|
||||||
|
float textMask = getText(coords);
|
||||||
|
|
||||||
|
// Get the window texture.
|
||||||
|
cogl_color_out = texture2D(uTexture, coords);
|
||||||
|
|
||||||
|
// Shell.GLSLEffect uses straight alpha. So we have to convert from premultiplied.
|
||||||
|
if (cogl_color_out.a > 0) {
|
||||||
|
cogl_color_out.rgb /= cogl_color_out.a;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fade the window according to the effect mask.
|
||||||
|
cogl_color_out.a *= rainMask.y;
|
||||||
|
|
||||||
|
// This is used to fade out the remaining trails in the end.
|
||||||
|
float finalFade =
|
||||||
|
1 - clamp((uProgress - FINAL_FADE_START_TIME) / (1 - FINAL_FADE_START_TIME), 0, 1);
|
||||||
|
float rainAlpha = finalFade * rainMask.x;
|
||||||
|
|
||||||
|
// Add the matrix effect to the window.
|
||||||
|
vec4 text =
|
||||||
|
vec4(mix(uTrailColor, uTipColor, min(1, pow(rainAlpha + 0.1, 4))), rainAlpha* textMask);
|
||||||
|
cogl_color_out = alphaOver(cogl_color_out, text);
|
||||||
|
|
||||||
|
// These are pretty useful for understanding how this works.
|
||||||
|
// cogl_color_out = vec4(vec3(textMask), 1);
|
||||||
|
// cogl_color_out = vec4(vec3(rainMask.x), 1);
|
||||||
|
// cogl_color_out = vec4(vec3(rainMask.y), 1);
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
// Inject some common shader snippets. It is only possible to include glsl files from the
|
||||||
|
// "common" directory. Also, the files in the "common" directory are not allowed to
|
||||||
|
// include any further files.
|
||||||
|
#include "common/uniforms.glsl"
|
||||||
|
#include "common/noise.glsl"
|
||||||
|
#include "common/math2D.glsl"
|
||||||
|
|
||||||
|
uniform sampler2D uDustTexture;
|
||||||
|
uniform vec4 uDustColor;
|
||||||
|
uniform vec2 uSeed;
|
||||||
|
uniform float uDustScale;
|
||||||
|
|
||||||
|
const float DUST_LAYERS = 4;
|
||||||
|
const float GROW_INTENSITY = 0.05;
|
||||||
|
const float SHRINK_INTENSITY = 0.05;
|
||||||
|
const float WIND_INTENSITY = 0.05;
|
||||||
|
const float ACTOR_SCALE = 1.2;
|
||||||
|
const float PADDING = ACTOR_SCALE / 2.0 - 0.5;
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
// We simply inverse the progress for opening windows.
|
||||||
|
float progress = uForOpening ? uProgress : 1.0 - uProgress;
|
||||||
|
|
||||||
|
float gradient = cogl_tex_coord_in[0].t * ACTOR_SCALE - PADDING;
|
||||||
|
progress = 2.0 - gradient - 2.0 * progress;
|
||||||
|
progress = progress + 0.25 - 0.5 * simplex2D((cogl_tex_coord_in[0].st + uSeed) * 2.0);
|
||||||
|
progress = pow(max(0, progress), 2.0);
|
||||||
|
|
||||||
|
// This may help you to understand how this effect works.
|
||||||
|
// cogl_color_out = vec4(progress, 0, 0, 0);
|
||||||
|
// return;
|
||||||
|
|
||||||
|
cogl_color_out = vec4(0, 0, 0, 0);
|
||||||
|
|
||||||
|
for (float i = 0; i < DUST_LAYERS; ++i) {
|
||||||
|
|
||||||
|
// Create a random direction.
|
||||||
|
float factor = DUST_LAYERS == 1 ? 0 : i / (DUST_LAYERS - 1);
|
||||||
|
float angle = 123.123 * (uSeed.x + factor);
|
||||||
|
vec2 direction = vec2(1.0, 0.0);
|
||||||
|
direction = rotate(direction, angle);
|
||||||
|
|
||||||
|
// Flip direction for one side of the window.
|
||||||
|
vec2 coords = cogl_tex_coord_in[0].st * ACTOR_SCALE - PADDING - 0.5;
|
||||||
|
if (getWinding(direction, coords) > 0) {
|
||||||
|
direction *= -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flip direction for half the layers.
|
||||||
|
if (factor > 0.5) {
|
||||||
|
direction *= -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We grow the layer along the random direction, shrink it orthogonally to it
|
||||||
|
// and scale it up slightly.
|
||||||
|
float dist = distToLine(vec2(0.0), direction, coords);
|
||||||
|
vec2 grow = direction * dist * mix(0, GROW_INTENSITY, progress);
|
||||||
|
vec2 shrink =
|
||||||
|
vec2(direction.y, -direction.x) * dist * mix(0, SHRINK_INTENSITY, progress);
|
||||||
|
float scale = mix(1.0, 1.05, factor * progress);
|
||||||
|
coords = (coords + grow + shrink) / scale;
|
||||||
|
|
||||||
|
// Add some wind.
|
||||||
|
coords.x += WIND_INTENSITY * progress * (uForOpening ? 1.0 : -1.0);
|
||||||
|
|
||||||
|
// Now check wether there is actually something in the current dust layer at
|
||||||
|
// the coords position.
|
||||||
|
vec2 dustCoords = (coords + uSeed) * uSize / uDustScale / 100.0;
|
||||||
|
vec2 dustMap = texture2D(uDustTexture, dustCoords).rg;
|
||||||
|
float dustGroup = floor(dustMap.g * DUST_LAYERS * 0.999);
|
||||||
|
|
||||||
|
if (dustGroup == i) {
|
||||||
|
|
||||||
|
// Get the window color.
|
||||||
|
vec4 windowColor = texture2D(uTexture, coords + 0.5);
|
||||||
|
|
||||||
|
// Shell.GLSLEffect uses straight alpha. So we have to convert from premultiplied.
|
||||||
|
if (windowColor.a > 0) {
|
||||||
|
windowColor.rgb /= windowColor.a;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fade the window color to uDustColor.
|
||||||
|
vec3 dustColor = mix(windowColor.rgb, uDustColor.rgb, uDustColor.a);
|
||||||
|
windowColor.rgb = mix(windowColor.rgb, dustColor, progress);
|
||||||
|
|
||||||
|
// Dissolve and blend the layers.
|
||||||
|
if (dustMap.x - progress > 0) {
|
||||||
|
cogl_color_out = windowColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
// Inject some common shader snippets. It is only possible to include glsl files from the
|
||||||
|
// "common" directory. Also, the files in the "common" directory are not allowed to
|
||||||
|
// include any further files.
|
||||||
|
#include "common/uniforms.glsl"
|
||||||
|
#include "common/noise.glsl"
|
||||||
|
#include "common/compositing.glsl"
|
||||||
|
|
||||||
|
// See assets/README.md for how this texture was created.
|
||||||
|
uniform sampler2D uClawTexture;
|
||||||
|
uniform vec4 uFlashColor;
|
||||||
|
uniform vec2 uSeed;
|
||||||
|
uniform float uClawSize;
|
||||||
|
uniform float uNumClaws;
|
||||||
|
uniform float uWarpIntensity;
|
||||||
|
|
||||||
|
const float FLASH_INTENSITY = 0.1;
|
||||||
|
const float MAX_SPAWN_TIME =
|
||||||
|
0.6; // Scratches will only start in the first half of the animation.
|
||||||
|
const float FF_TIME = 0.6; // Relative time for the final fade to transparency.
|
||||||
|
|
||||||
|
// This method generates a grid of randomly rotated, slightly shifted and scaled
|
||||||
|
// UV squares. It returns the texture coords of the UV square at the given actor
|
||||||
|
// coordinates. If these do not fall into one of the UV grids, the coordinates of
|
||||||
|
// the closest UV grid will be clamped and returned.
|
||||||
|
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 + hash22(seed);
|
||||||
|
coords *= uSize.x < uSize.y ? vec2(1.0, 1.0 * uSize.y / uSize.x)
|
||||||
|
: vec2(1.0 * uSize.x / uSize.y, 1.0);
|
||||||
|
|
||||||
|
// Apply global scale.
|
||||||
|
coords *= gridScale;
|
||||||
|
|
||||||
|
// Get grid cell coordinates in [0..1].
|
||||||
|
vec2 cellUV = mod(coords, vec2(1));
|
||||||
|
|
||||||
|
// This is unique for each cell.
|
||||||
|
vec2 cellID = coords - cellUV + vec2(362.456);
|
||||||
|
|
||||||
|
// Add random rotation, scale and offset to each grid cell.
|
||||||
|
float scale = mix(0.8, 1.0, hash12(cellID * seed * 134.451));
|
||||||
|
float offsetX = mix(0.0, 1.0 - scale, hash12(cellID * seed * 54.4129));
|
||||||
|
float offsetY = mix(0.0, 1.0 - scale, hash12(cellID * seed * 25.3089));
|
||||||
|
float rotation = mix(0.0, 2.0 * 3.141, hash12(cellID * seed * 2.99837));
|
||||||
|
|
||||||
|
cellUV -= vec2(offsetX, offsetY);
|
||||||
|
cellUV /= scale;
|
||||||
|
|
||||||
|
cellUV -= 0.5;
|
||||||
|
cellUV = vec2(cellUV.x * cos(rotation) - cellUV.y * sin(rotation),
|
||||||
|
cellUV.x * sin(rotation) + cellUV.y * cos(rotation));
|
||||||
|
cellUV += 0.5;
|
||||||
|
|
||||||
|
// Clamp resulting coordinates.
|
||||||
|
return clamp(cellUV, vec2(0), vec2(1));
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
float progress = uForOpening ? 1.0 - uProgress : uProgress;
|
||||||
|
|
||||||
|
// Warp the texture coordinates to create a blow-up effect.
|
||||||
|
vec2 coords = cogl_tex_coord_in[0].st * 2.0 - 1.0;
|
||||||
|
float dist = length(coords);
|
||||||
|
coords = (coords / dist * pow(dist, 1.0 + uWarpIntensity)) * 0.5 + 0.5;
|
||||||
|
coords = mix(cogl_tex_coord_in[0].st, coords, progress);
|
||||||
|
|
||||||
|
// Accumulate several random scratches. The color in the scratch map refers to the
|
||||||
|
// relative time when the respective part will become invisible. Therefore we can
|
||||||
|
// add a value to make the scratch appear later.
|
||||||
|
float scratchMap = 1.0;
|
||||||
|
for (int i = 0; i < uNumClaws; ++i) {
|
||||||
|
vec2 uv = getClawUV(coords, 1.0 / uClawSize, uSeed * (i + 1));
|
||||||
|
float delay = i / uNumClaws * MAX_SPAWN_TIME;
|
||||||
|
scratchMap = min(scratchMap, clamp(texture2D(uClawTexture, uv).r + delay, 0, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the window texture. We shift the texture lookup by the local derivative of
|
||||||
|
// the claw texture in order to mimic some folding distortion.
|
||||||
|
vec2 offset = vec2(dFdx(scratchMap), dFdy(scratchMap)) * progress * 0.5;
|
||||||
|
cogl_color_out = texture2D(uTexture, coords + offset);
|
||||||
|
|
||||||
|
// Shell.GLSLEffect uses straight alpha. So we have to convert from premultiplied.
|
||||||
|
if (cogl_color_out.a > 0) {
|
||||||
|
cogl_color_out.rgb /= cogl_color_out.a;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add colorful flashes.
|
||||||
|
float flashIntensity = 1.0 / FLASH_INTENSITY * (scratchMap - progress) + 1;
|
||||||
|
if (flashIntensity < 0 || flashIntensity >= 1) {
|
||||||
|
flashIntensity = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hide flashes where there is now window.
|
||||||
|
vec4 flash = uFlashColor;
|
||||||
|
flash.a *= flashIntensity * cogl_color_out.a * (1.0 - progress);
|
||||||
|
|
||||||
|
// Hide scratched out parts.
|
||||||
|
cogl_color_out.a *= (scratchMap > progress ? 1 : 0);
|
||||||
|
|
||||||
|
// Add flash color.
|
||||||
|
cogl_color_out = alphaOver(cogl_color_out, flash);
|
||||||
|
|
||||||
|
// Fade out the remaining shards.
|
||||||
|
float fadeProgress = smoothstep(0, 1, (progress - 1.0 + FF_TIME) / FF_TIME);
|
||||||
|
cogl_color_out.a *= sqrt(1 - fadeProgress * fadeProgress);
|
||||||
|
|
||||||
|
// These are pretty useful for understanding how this works.
|
||||||
|
// cogl_color_out = vec4(vec3(flashIntensity), 1);
|
||||||
|
// cogl_color_out = vec4(vec3(scratchMap), 1);
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
// Inject some common shader snippets. It is only possible to include glsl files from the
|
||||||
|
// "common" directory. Also, the files in the "common" directory are not allowed to
|
||||||
|
// include any further files.
|
||||||
|
#include "common/uniforms.glsl"
|
||||||
|
|
||||||
|
uniform vec3 uColor;
|
||||||
|
|
||||||
|
const float BLUR_WIDTH = 0.01; // Width of the gradients.
|
||||||
|
const float TB_TIME = 0.7; // Relative time for the top/bottom animation.
|
||||||
|
const float LR_TIME = 0.4; // Relative time for the left/right animation.
|
||||||
|
const float LR_DELAY = 0.6; // Delay after which the left/right animation starts.
|
||||||
|
const float FF_TIME = 0.1; // Relative time for the final fade to transparency.
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
float progress = uForOpening ? 1.0 - uProgress : uProgress;
|
||||||
|
|
||||||
|
// All of these are in [0..1] during the different stages of the animation.
|
||||||
|
// tb refers to the top-bottom animation.
|
||||||
|
// lr refers to the left-right animation.
|
||||||
|
// ff refers to the final fade animation.
|
||||||
|
float tbProgress = smoothstep(0, 1, clamp(progress / TB_TIME, 0, 1));
|
||||||
|
float lrProgress = smoothstep(0, 1, clamp((progress - LR_DELAY) / LR_TIME, 0, 1));
|
||||||
|
float ffProgress = smoothstep(0, 1, clamp((progress - 1.0 + FF_TIME) / FF_TIME, 0, 1));
|
||||||
|
|
||||||
|
// This is a top-center-bottom gradient in [0..1..0]
|
||||||
|
float tb = cogl_tex_coord_in[0].t * 2;
|
||||||
|
tb = tb < 1 ? tb : 2 - tb;
|
||||||
|
|
||||||
|
// This is a left-center-right gradient in [0..1..0]
|
||||||
|
float lr = cogl_tex_coord_in[0].s * 2;
|
||||||
|
lr = lr < 1 ? lr : 2 - lr;
|
||||||
|
|
||||||
|
// Combine the progress values with the gradients to create the alpha masks.
|
||||||
|
float tbMask = 1 - smoothstep(0, 1, clamp((tbProgress - tb) / BLUR_WIDTH, 0, 1));
|
||||||
|
float lrMask = 1 - smoothstep(0, 1, clamp((lrProgress - lr) / BLUR_WIDTH, 0, 1));
|
||||||
|
float ffMask = 1 - smoothstep(0, 1, ffProgress);
|
||||||
|
|
||||||
|
// Assemble the final alpha value.
|
||||||
|
float mask = tbMask * lrMask * ffMask;
|
||||||
|
|
||||||
|
cogl_color_out = texture2D(uTexture, cogl_tex_coord_in[0].st);
|
||||||
|
|
||||||
|
// Shell.GLSLEffect uses straight alpha. So we have to convert from premultiplied.
|
||||||
|
if (cogl_color_out.a > 0) {
|
||||||
|
cogl_color_out.rgb /= cogl_color_out.a;
|
||||||
|
}
|
||||||
|
|
||||||
|
cogl_color_out.rgb =
|
||||||
|
mix(cogl_color_out.rgb, uColor* cogl_color_out.a, smoothstep(0, 1, progress));
|
||||||
|
cogl_color_out.a *= mask;
|
||||||
|
|
||||||
|
// These are pretty useful for understanding how this works.
|
||||||
|
// cogl_color_out = vec4(vec3(tbMask), 1);
|
||||||
|
// cogl_color_out = vec4(vec3(lrMask), 1);
|
||||||
|
// cogl_color_out = vec4(vec3(ffMask), 1);
|
||||||
|
// cogl_color_out = vec4(vec3(mask), 1);
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
// Inject some common shader snippets. It is only possible to include glsl files from the
|
||||||
|
// "common" directory. Also, the files in the "common" directory are not allowed to
|
||||||
|
// include any further files.
|
||||||
|
#include "common/uniforms.glsl"
|
||||||
|
#include "common/noise.glsl"
|
||||||
|
#include "common/edgeMask.glsl"
|
||||||
|
#include "common/compositing.glsl"
|
||||||
|
|
||||||
|
uniform vec2 uSeed;
|
||||||
|
uniform vec3 uColor;
|
||||||
|
uniform float uScale;
|
||||||
|
|
||||||
|
const float WISPS_RADIUS = 20.0;
|
||||||
|
const float WISPS_SPEED = 10.0;
|
||||||
|
const float WISPS_SPACING = 40 + WISPS_RADIUS;
|
||||||
|
const int WISPS_LAYERS = 8;
|
||||||
|
const float WISPS_IN_TIME = 0.5;
|
||||||
|
const float WINDOW_OUT_TIME = 1.0;
|
||||||
|
|
||||||
|
// Returns a grid of randomly moving points. Each grid cell contains one point which
|
||||||
|
// moves on an ellipse.
|
||||||
|
float getWisps(vec2 texCoords, float gridSize, vec2 seed) {
|
||||||
|
|
||||||
|
// Shift coordinates by a random offset and make sure the have a 1:1 aspect ratio.
|
||||||
|
vec2 coords = (texCoords + hash22(seed)) * uSize;
|
||||||
|
|
||||||
|
// Apply global scale.
|
||||||
|
coords /= gridSize;
|
||||||
|
|
||||||
|
// Get grid cell coordinates in [0..1].
|
||||||
|
vec2 cellUV = mod(coords, vec2(1));
|
||||||
|
|
||||||
|
// This is unique for each cell.
|
||||||
|
vec2 cellID = coords - cellUV + vec2(362.456);
|
||||||
|
|
||||||
|
// Add random rotation, scale and offset to each grid cell.
|
||||||
|
float speed = mix(10.0, 15.0, hash12(cellID * seed * 134.451)) / gridSize * WISPS_SPEED;
|
||||||
|
float rotation = mix(0.0, 6.283, hash12(cellID * seed * 54.4129));
|
||||||
|
float radius = mix(0.5, 1.0, hash12(cellID * seed * 19.1249)) * WISPS_RADIUS;
|
||||||
|
float roundness = mix(-1.0, 1.0, hash12(cellID * seed * 7.51949));
|
||||||
|
|
||||||
|
vec2 offset = vec2(sin(speed * (uTime + 1)) * roundness, cos(speed * (uTime + 1)));
|
||||||
|
offset *= 0.5 - 0.5 * radius / gridSize;
|
||||||
|
offset = vec2(offset.x * cos(rotation) - offset.y * sin(rotation),
|
||||||
|
offset.x * sin(rotation) + offset.y * cos(rotation));
|
||||||
|
|
||||||
|
cellUV += offset;
|
||||||
|
|
||||||
|
// Use distance to center of shifted / rotated UV coordinates to draw a glaring point.
|
||||||
|
float dist = length(cellUV - 0.5) * gridSize / radius;
|
||||||
|
if (dist < 1.0) {
|
||||||
|
return min(5, 0.01 / pow(dist, 2.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
float progress = uForOpening ? 1.0 - uProgress : uProgress;
|
||||||
|
|
||||||
|
// Get the color of the window.
|
||||||
|
cogl_color_out = texture2D(uTexture, cogl_tex_coord_in[0].st);
|
||||||
|
|
||||||
|
// Shell.GLSLEffect uses straight alpha. So we have to convert from premultiplied.
|
||||||
|
if (cogl_color_out.a > 0) {
|
||||||
|
cogl_color_out.rgb /= cogl_color_out.a;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute several layers of moving wisps.
|
||||||
|
vec2 uv = (cogl_tex_coord_in[0].st - 0.5) / mix(1.0, 0.5, progress) + 0.5;
|
||||||
|
uv /= uScale;
|
||||||
|
float wisps = 0;
|
||||||
|
for (int i = 0; i < WISPS_LAYERS; ++i) {
|
||||||
|
wisps += getWisps(uv * 0.3, WISPS_SPACING, uSeed * (i + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute shrinking edge mask.
|
||||||
|
float mask = getRelativeEdgeMask(mix(0.01, 0.5, progress));
|
||||||
|
|
||||||
|
// Compute three different progress values.
|
||||||
|
float wispsIn = smoothstep(0, 1, clamp(progress / WISPS_IN_TIME, 0, 1));
|
||||||
|
float wispsOut =
|
||||||
|
smoothstep(0, 1, clamp((progress - WISPS_IN_TIME) / (1.0 - WISPS_IN_TIME), 0, 1));
|
||||||
|
float windowOut = smoothstep(0, 1, clamp(progress / WINDOW_OUT_TIME, 0, 1));
|
||||||
|
|
||||||
|
// Use a noise function to dissolve the window.
|
||||||
|
float noise = smoothstep(1.0, 0.0, abs(2.0 * simplex2DFractal(uv * uSize / 250) - 1.0));
|
||||||
|
float windowMask = 1.0 - (windowOut < 0.5 ? mix(0.0, noise, windowOut * 2.0)
|
||||||
|
: mix(noise, 1.0, windowOut * 2.0 - 1.0));
|
||||||
|
cogl_color_out.a *= windowMask * mask;
|
||||||
|
|
||||||
|
// Add the wisps.
|
||||||
|
vec4 wispColor = wisps * vec4(uColor, min(wispsIn, 1.0 - wispsOut) * mask);
|
||||||
|
cogl_color_out = alphaOver(cogl_color_out, wispColor);
|
||||||
|
|
||||||
|
// These are pretty useful for understanding how this works.
|
||||||
|
// cogl_color_out = vec4(vec3(windowMask), 1.0);
|
||||||
|
// cogl_color_out = vec4(vec3(wisps), 1.0);
|
||||||
|
// cogl_color_out = vec4(vec3(noise), 1.0);
|
||||||
|
// cogl_color_out = vec4(vec3(mask*min(wispsIn, 1.0 - wispsOut)), 1.0);
|
||||||
+1
-1
@@ -32,7 +32,7 @@ cd "$( cd "$( dirname "$0" )" && pwd )/.." || \
|
|||||||
|
|
||||||
# Run cloc - this counts code lines, blank lines and comment lines for the specified
|
# Run cloc - this counts code lines, blank lines and comment lines for the specified
|
||||||
# languages. We are only interested in the summary, therefore the tail -1
|
# languages. We are only interested in the summary, therefore the tail -1
|
||||||
SUMMARY="$(cloc . --include-lang="JavaScript" --md | tail -1)"
|
SUMMARY="$(cloc . --include-lang="JavaScript,GLSL" --md | tail -1)"
|
||||||
|
|
||||||
# The $SUMMARY is one line of a markdown table and looks like this:
|
# The $SUMMARY is one line of a markdown table and looks like this:
|
||||||
# SUM:|101|3123|2238|10783
|
# SUM:|101|3123|2238|10783
|
||||||
|
|||||||
+5
-50
@@ -137,8 +137,7 @@ var Apparition = class Apparition {
|
|||||||
|
|
||||||
if (utils.isInShellProcess()) {
|
if (utils.isInShellProcess()) {
|
||||||
|
|
||||||
const Shell = imports.gi.Shell;
|
const Shell = imports.gi.Shell;
|
||||||
const shaderSnippets = Me.imports.src.shaderSnippets;
|
|
||||||
|
|
||||||
ShaderClass = GObject.registerClass({}, class ShaderClass extends Shell.GLSLEffect {
|
ShaderClass = GObject.registerClass({}, class ShaderClass extends Shell.GLSLEffect {
|
||||||
// This is called when the effect is used for the first time. This can be used to
|
// This is called when the effect is used for the first time. This can be used to
|
||||||
@@ -177,55 +176,11 @@ if (utils.isInShellProcess()) {
|
|||||||
// This is called by the constructor. This means, it's only called when the effect
|
// This is called by the constructor. This means, it's only called when the effect
|
||||||
// is used for the first time.
|
// is used for the first time.
|
||||||
vfunc_build_pipeline() {
|
vfunc_build_pipeline() {
|
||||||
const declarations = `
|
const decl =
|
||||||
// Inject some common shader snippets.
|
utils.loadGLSLResource(`/shaders/${Apparition.getNick()}-declarations.glsl`);
|
||||||
${shaderSnippets.standardUniforms()}
|
const code = utils.loadGLSLResource(`/shaders/${Apparition.getNick()}.glsl`);
|
||||||
|
|
||||||
uniform vec2 uSeed;
|
this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT, decl, code, true);
|
||||||
uniform float uShake;
|
|
||||||
uniform float uTwirl;
|
|
||||||
uniform float uSuction;
|
|
||||||
uniform float uRandomness;
|
|
||||||
|
|
||||||
const float ACTOR_SCALE = 2.0;
|
|
||||||
const float PADDING = ACTOR_SCALE / 2.0 - 0.5;
|
|
||||||
`;
|
|
||||||
|
|
||||||
// The math for the whirling is inspired by this post:
|
|
||||||
// http://www.geeks3d.com/20110428/shader-library-swirl-post-processing-filter-in-glsl
|
|
||||||
const code = `
|
|
||||||
// We simply inverse the progress for opening windows.
|
|
||||||
float progress = uForOpening ? 1.0-uProgress : uProgress;
|
|
||||||
|
|
||||||
// Choose a random suction center.
|
|
||||||
vec2 center = uSeed * uRandomness + 0.5 * (1.0 - uRandomness);
|
|
||||||
vec2 coords = cogl_tex_coord_in[0].st * ACTOR_SCALE - PADDING - center;
|
|
||||||
|
|
||||||
// Add some shaking.
|
|
||||||
coords.x += progress * 0.05 * uShake * sin((progress + uSeed.x) * (1.0 + uSeed.x) * uShake);
|
|
||||||
coords.y += progress * 0.05 * uShake * cos((progress + uSeed.y) * (1.0 + uSeed.y) * uShake);
|
|
||||||
|
|
||||||
// "Suck" the texture into the center.
|
|
||||||
float dist = length(coords) / sqrt(2);
|
|
||||||
coords += progress * coords / dist * 0.5 * uSuction;
|
|
||||||
|
|
||||||
// Apply some whirling.
|
|
||||||
float angle = pow(1.0 - dist, 2.0) * uTwirl * progress;
|
|
||||||
float s = sin(angle);
|
|
||||||
float c = cos(angle);
|
|
||||||
coords = vec2(dot(coords, vec2(c, -s)), dot(coords, vec2(s, c)));
|
|
||||||
|
|
||||||
// Shell.GLSLEffect uses straight alpha. So we have to convert from premultiplied.
|
|
||||||
cogl_color_out = texture2D(uTexture, coords + center);
|
|
||||||
if (cogl_color_out.a > 0) {
|
|
||||||
cogl_color_out.rgb /= cogl_color_out.a;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fade out the window texture.
|
|
||||||
cogl_color_out.a *= 1.0 - progress;
|
|
||||||
`;
|
|
||||||
|
|
||||||
this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT, declarations, code, true);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
+4
-68
@@ -142,7 +142,6 @@ var BrokenGlass = class BrokenGlass {
|
|||||||
if (utils.isInShellProcess()) {
|
if (utils.isInShellProcess()) {
|
||||||
|
|
||||||
const {Clutter, GdkPixbuf, Cogl, Shell} = imports.gi;
|
const {Clutter, GdkPixbuf, Cogl, Shell} = imports.gi;
|
||||||
const shaderSnippets = Me.imports.src.shaderSnippets;
|
|
||||||
|
|
||||||
// This shader creates a complex-looking effect with rather simple means. Here is how it
|
// This shader creates a complex-looking effect with rather simple means. Here is how it
|
||||||
// works: The window is drawn five times on top of each other (see the SHARD_LAYERS
|
// works: The window is drawn five times on top of each other (see the SHARD_LAYERS
|
||||||
@@ -214,74 +213,11 @@ if (utils.isInShellProcess()) {
|
|||||||
// This is called by the constructor. This means, it's only called when the effect
|
// This is called by the constructor. This means, it's only called when the effect
|
||||||
// is used for the first time.
|
// is used for the first time.
|
||||||
vfunc_build_pipeline() {
|
vfunc_build_pipeline() {
|
||||||
const declarations = `
|
const decl =
|
||||||
// Inject some common shader snippets.
|
utils.loadGLSLResource(`/shaders/${BrokenGlass.getNick()}-declarations.glsl`);
|
||||||
${shaderSnippets.standardUniforms()}
|
const code = utils.loadGLSLResource(`/shaders/${BrokenGlass.getNick()}.glsl`);
|
||||||
|
|
||||||
uniform sampler2D uShardTexture;
|
this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT, decl, code, true);
|
||||||
uniform vec2 uSeed;
|
|
||||||
uniform vec2 uEpicenter;
|
|
||||||
uniform float uShardScale;
|
|
||||||
uniform float uBlowForce;
|
|
||||||
uniform float uGravity;
|
|
||||||
|
|
||||||
const float SHARD_LAYERS = 5;
|
|
||||||
const float ACTOR_SCALE = 2.0;
|
|
||||||
const float PADDING = ACTOR_SCALE / 2.0 - 0.5;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const code = `
|
|
||||||
cogl_color_out = vec4(0, 0, 0, 0);
|
|
||||||
|
|
||||||
float progress = uForOpening ? 1.0-uProgress : uProgress;
|
|
||||||
|
|
||||||
// Draw the individual shard layers.
|
|
||||||
for (float i=0; i<SHARD_LAYERS; ++i) {
|
|
||||||
|
|
||||||
// To enable drawing shards outside of the window bounds, the actor was scaled
|
|
||||||
// by ACTOR_SCALE. Here we scale and move the texture coordinates so that the
|
|
||||||
// window gets drawn at the correct position again.
|
|
||||||
vec2 coords = cogl_tex_coord_in[0].st * ACTOR_SCALE - PADDING;
|
|
||||||
|
|
||||||
// Scale and rotate around our epicenter.
|
|
||||||
coords -= uEpicenter;
|
|
||||||
|
|
||||||
// Scale each layer a bit differently.
|
|
||||||
coords /= mix(1.0, 1.0 + uBlowForce*(i+2)/SHARD_LAYERS, progress);
|
|
||||||
|
|
||||||
// Rotate each layer a bit differently.
|
|
||||||
float rotation = (mod(i, 2.0)-0.5)*0.2*progress;
|
|
||||||
coords = vec2(coords.x * cos(rotation) - coords.y * sin(rotation),
|
|
||||||
coords.x * sin(rotation) + coords.y * cos(rotation));
|
|
||||||
|
|
||||||
// Move down each layer a bit.
|
|
||||||
float gravity = (uForOpening ? -1.0 : 1.0) * uGravity*0.1*(i+1)*progress*progress;
|
|
||||||
coords += vec2(0, gravity);
|
|
||||||
|
|
||||||
// Restore correct position.
|
|
||||||
coords += uEpicenter;
|
|
||||||
|
|
||||||
// Retrieve information from the shard texture for our layer.
|
|
||||||
vec2 shardCoords = (coords + uSeed) * uSize / uShardScale / 500.0;
|
|
||||||
vec2 shardMap = texture2D(uShardTexture, shardCoords).rg;
|
|
||||||
|
|
||||||
// The green channel contains a random value in [0..1] for each shard. We
|
|
||||||
// discretize this into SHARD_LAYERS bins and check if our layer falls into
|
|
||||||
// the bin of the current shard.
|
|
||||||
float shardGroup = floor(shardMap.g * SHARD_LAYERS * 0.999);
|
|
||||||
|
|
||||||
if (shardGroup == i && (shardMap.x - pow(progress+0.1, 2)) > 0) {
|
|
||||||
cogl_color_out = texture2D(uTexture, coords);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Shell.GLSLEffect uses straight alpha. So we have to convert from premultiplied.
|
|
||||||
if (cogl_color_out.a > 0) {
|
|
||||||
cogl_color_out.rgb /= cogl_color_out.a;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT, declarations, code, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is overridden to bind the shard texture for drawing. Sadly, this seems to be
|
// This is overridden to bind the shard texture for drawing. Sadly, this seems to be
|
||||||
|
|||||||
+4
-88
@@ -132,7 +132,6 @@ var EnergizeA = class EnergizeA {
|
|||||||
if (utils.isInShellProcess()) {
|
if (utils.isInShellProcess()) {
|
||||||
|
|
||||||
const {Clutter, Shell} = imports.gi;
|
const {Clutter, Shell} = imports.gi;
|
||||||
const shaderSnippets = Me.imports.src.shaderSnippets;
|
|
||||||
|
|
||||||
ShaderClass = GObject.registerClass({}, class ShaderClass extends Shell.GLSLEffect {
|
ShaderClass = GObject.registerClass({}, class ShaderClass extends Shell.GLSLEffect {
|
||||||
// This is called when the effect is used for the first time. This can be used to
|
// This is called when the effect is used for the first time. This can be used to
|
||||||
@@ -164,94 +163,11 @@ if (utils.isInShellProcess()) {
|
|||||||
// This is called by the constructor. This means, it's only called when the effect
|
// This is called by the constructor. This means, it's only called when the effect
|
||||||
// is used for the first time.
|
// is used for the first time.
|
||||||
vfunc_build_pipeline() {
|
vfunc_build_pipeline() {
|
||||||
const declarations = `
|
const decl =
|
||||||
// Inject some common shader snippets.
|
utils.loadGLSLResource(`/shaders/${EnergizeA.getNick()}-declarations.glsl`);
|
||||||
${shaderSnippets.standardUniforms()}
|
const code = utils.loadGLSLResource(`/shaders/${EnergizeA.getNick()}.glsl`);
|
||||||
${shaderSnippets.noise()}
|
|
||||||
${shaderSnippets.edgeMask()}
|
|
||||||
|
|
||||||
uniform vec3 uColor;
|
this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT, decl, code, true);
|
||||||
uniform float uScale;
|
|
||||||
|
|
||||||
const float FADE_IN_TIME = 0.3;
|
|
||||||
const float FADE_OUT_TIME = 0.6;
|
|
||||||
const float HEART_FADE_TIME = 0.3;
|
|
||||||
const float EDGE_FADE_WIDTH = 50;
|
|
||||||
|
|
||||||
// This method returns two values:
|
|
||||||
// result.x: A mask for the particles.
|
|
||||||
// result.y: The opacity of the fading window.
|
|
||||||
vec2 getMasks() {
|
|
||||||
float fadeInProgress = clamp(uProgress/FADE_IN_TIME, 0, 1);
|
|
||||||
float fadeOutProgress = clamp((uProgress-FADE_IN_TIME)/FADE_OUT_TIME, 0, 1);
|
|
||||||
float heartProgress = clamp((uProgress-(1.0-HEART_FADE_TIME))/HEART_FADE_TIME, 0, 1);
|
|
||||||
|
|
||||||
// Compute mask for the "atom" particles.
|
|
||||||
float dist = length(cogl_tex_coord_in[0].st - 0.5) * 4.0;
|
|
||||||
float atomMask = smoothstep(0.0, 1.0, (fadeInProgress * 2.0 - dist + 1.0));
|
|
||||||
atomMask *= fadeInProgress;
|
|
||||||
atomMask *= smoothstep(1.0, 0.0, fadeOutProgress);
|
|
||||||
|
|
||||||
// Fade-out the masks at the window edges.
|
|
||||||
float edgeFade = getAbsoluteEdgeMask(EDGE_FADE_WIDTH);
|
|
||||||
atomMask *= edgeFade;
|
|
||||||
|
|
||||||
float heartMask = getRelativeEdgeMask(0.5);
|
|
||||||
heartMask = 3.0 * pow(heartMask, 5);
|
|
||||||
heartMask *= fadeOutProgress;
|
|
||||||
heartMask *= 1.0 - heartProgress;
|
|
||||||
atomMask = clamp(heartMask+atomMask, 0, 1);
|
|
||||||
|
|
||||||
// Compute fading window opacity.
|
|
||||||
float windowMask = pow(1.0 - fadeOutProgress, 2.0);
|
|
||||||
|
|
||||||
if (uForOpening) {
|
|
||||||
windowMask = 1.0 - windowMask;
|
|
||||||
}
|
|
||||||
|
|
||||||
return vec2(atomMask, windowMask);
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const code = `
|
|
||||||
vec2 masks = getMasks();
|
|
||||||
vec4 windowColor = texture2D(uTexture, cogl_tex_coord_in[0].st);
|
|
||||||
|
|
||||||
// Shell.GLSLEffect uses straight alpha. So we have to convert from premultiplied.
|
|
||||||
if (windowColor.a > 0) {
|
|
||||||
windowColor.rgb /= windowColor.a;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dissolve window to effect color / transparency.
|
|
||||||
cogl_color_out.rgb = mix(uColor, windowColor.rgb, 0.2 * masks.y + 0.8);
|
|
||||||
cogl_color_out.a = windowColor.a * masks.y;
|
|
||||||
|
|
||||||
vec2 scaledUV = (cogl_tex_coord_in[0].st-0.5) * (1.0 + 0.1*uProgress);
|
|
||||||
scaledUV /= uScale;
|
|
||||||
|
|
||||||
// Add molecule particles.
|
|
||||||
vec2 uv = scaledUV + vec2(0, 0.1*uTime);
|
|
||||||
uv *= 0.010598 * vec2(0.5*uSize.x, uSize.y);
|
|
||||||
float particles = 0.2 * pow((simplex3D(vec3(uv, 0.0*uTime))), 3.0);
|
|
||||||
|
|
||||||
// Add more molecule particles.
|
|
||||||
for (int i=1; i<=3;++i) {
|
|
||||||
vec2 uv = scaledUV * 0.12154 / pow(1.5, i) * uSize;
|
|
||||||
float atoms = simplex3D(vec3(uv, 2.0*uTime/i));
|
|
||||||
particles += 0.5 * pow(0.2 * (1.0 / (1.0 - atoms)-1.0), 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
cogl_color_out.rgb += uColor * particles * masks.x;
|
|
||||||
cogl_color_out.a += particles * masks.x;
|
|
||||||
|
|
||||||
// These are pretty useful for understanding how this works.
|
|
||||||
// cogl_color_out = vec4(masks, 0.0, 1.0);
|
|
||||||
// cogl_color_out = vec4(vec3(masks.x), 1.0);
|
|
||||||
// cogl_color_out = vec4(vec3(masks.y), 1.0);
|
|
||||||
// cogl_color_out = vec4(vec3(particles), 1.0);
|
|
||||||
`;
|
|
||||||
|
|
||||||
this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT, declarations, code, true);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
+4
-112
@@ -132,7 +132,6 @@ var EnergizeB = class EnergizeB {
|
|||||||
if (utils.isInShellProcess()) {
|
if (utils.isInShellProcess()) {
|
||||||
|
|
||||||
const {Clutter, Shell} = imports.gi;
|
const {Clutter, Shell} = imports.gi;
|
||||||
const shaderSnippets = Me.imports.src.shaderSnippets;
|
|
||||||
|
|
||||||
ShaderClass = GObject.registerClass({}, class ShaderClass extends Shell.GLSLEffect {
|
ShaderClass = GObject.registerClass({}, class ShaderClass extends Shell.GLSLEffect {
|
||||||
// This is called when the effect is used for the first time. This can be used to
|
// This is called when the effect is used for the first time. This can be used to
|
||||||
@@ -164,118 +163,11 @@ if (utils.isInShellProcess()) {
|
|||||||
// This is called by the constructor. This means, it's only called when the effect
|
// This is called by the constructor. This means, it's only called when the effect
|
||||||
// is used for the first time.
|
// is used for the first time.
|
||||||
vfunc_build_pipeline() {
|
vfunc_build_pipeline() {
|
||||||
const declarations = `
|
const decl =
|
||||||
// Inject some common shader snippets.
|
utils.loadGLSLResource(`/shaders/${EnergizeB.getNick()}-declarations.glsl`);
|
||||||
${shaderSnippets.standardUniforms()}
|
const code = utils.loadGLSLResource(`/shaders/${EnergizeB.getNick()}.glsl`);
|
||||||
${shaderSnippets.noise()}
|
|
||||||
${shaderSnippets.edgeMask()}
|
|
||||||
|
|
||||||
uniform vec3 uColor;
|
this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT, decl, code, true);
|
||||||
uniform float uScale;
|
|
||||||
|
|
||||||
const float SHOWER_TIME = 0.3;
|
|
||||||
const float SHOWER_WIDTH = 0.3;
|
|
||||||
const float STREAK_TIME = 0.6;
|
|
||||||
const float EDGE_FADE = 50;
|
|
||||||
|
|
||||||
// This method returns four values:
|
|
||||||
// result.x: A mask for the particles which lead the shower.
|
|
||||||
// result.y: A mask for the streaks which follow the shower particles.
|
|
||||||
// result.z: A mask for the final "atom" particles.
|
|
||||||
// result.w: The opacity of the fading window.
|
|
||||||
vec4 getMasks() {
|
|
||||||
float showerProgress = uProgress/SHOWER_TIME;
|
|
||||||
float streakProgress = clamp((uProgress-SHOWER_TIME)/STREAK_TIME, 0, 1);
|
|
||||||
float fadeProgress = clamp((uProgress-SHOWER_TIME)/(1.0 - SHOWER_TIME), 0, 1);
|
|
||||||
|
|
||||||
// Gradient from top to bottom.
|
|
||||||
float t = cogl_tex_coord_in[0].t;
|
|
||||||
|
|
||||||
// A smooth gradient which moves to the bottom within the showerProgress.
|
|
||||||
float showerMask = smoothstep(1, 0, abs(showerProgress - t - SHOWER_WIDTH) / SHOWER_WIDTH);
|
|
||||||
|
|
||||||
// This is 1 above the streak mask.
|
|
||||||
float streakMask = (showerProgress - t - SHOWER_WIDTH) > 0 ? 1 : 0;
|
|
||||||
|
|
||||||
// Compute mask for the "atom" particles.
|
|
||||||
float atomMask = getRelativeEdgeMask(0.2);
|
|
||||||
atomMask = max(0, atomMask - showerMask);
|
|
||||||
atomMask *= streakMask;
|
|
||||||
atomMask *= sqrt(1-fadeProgress*fadeProgress);
|
|
||||||
|
|
||||||
// Make some particles visible in the streaks.
|
|
||||||
showerMask += 0.05 * streakMask;
|
|
||||||
|
|
||||||
// Add shower mask to streak mask.
|
|
||||||
streakMask = max(streakMask, showerMask);
|
|
||||||
|
|
||||||
// Fade-out the masks at the window edges.
|
|
||||||
float edgeFade = getAbsoluteEdgeMask(EDGE_FADE);
|
|
||||||
streakMask *= edgeFade;
|
|
||||||
showerMask *= edgeFade;
|
|
||||||
|
|
||||||
// Fade-out the masks from top to bottom.
|
|
||||||
float fade = smoothstep(0.0, 1.0, 1.0 + t - 2.0 * streakProgress);
|
|
||||||
streakMask *= fade;
|
|
||||||
showerMask *= fade;
|
|
||||||
|
|
||||||
// Compute fading window opacity.
|
|
||||||
float windowMask = pow(1.0 - fadeProgress, 2.0);
|
|
||||||
|
|
||||||
if (uForOpening) {
|
|
||||||
windowMask = 1.0 - windowMask;
|
|
||||||
}
|
|
||||||
|
|
||||||
return vec4(showerMask, streakMask, atomMask, windowMask);
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const code = `
|
|
||||||
vec4 masks = getMasks();
|
|
||||||
vec4 windowColor = texture2D(uTexture, cogl_tex_coord_in[0].st);
|
|
||||||
|
|
||||||
// Shell.GLSLEffect uses straight alpha. So we have to convert from premultiplied.
|
|
||||||
if (windowColor.a > 0) {
|
|
||||||
windowColor.rgb /= windowColor.a;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dissolve window to effect color / transparency.
|
|
||||||
cogl_color_out.rgb = mix(uColor, windowColor.rgb, 0.5 * masks.w + 0.5);
|
|
||||||
cogl_color_out.a = windowColor.a * masks.w;
|
|
||||||
|
|
||||||
// Add leading shower particles.
|
|
||||||
vec2 showerUV = cogl_tex_coord_in[0].st + vec2(0, -0.7*uProgress/SHOWER_TIME);
|
|
||||||
showerUV *= 0.02 * uSize / uScale;
|
|
||||||
float shower = pow(simplex2D(showerUV), 10.0);
|
|
||||||
cogl_color_out.rgb += uColor * shower * masks.x;
|
|
||||||
cogl_color_out.a += shower * masks.x;
|
|
||||||
|
|
||||||
// Add trailing streak lines.
|
|
||||||
vec2 streakUV = cogl_tex_coord_in[0].st + vec2(0, -uProgress/SHOWER_TIME);
|
|
||||||
streakUV *= vec2(0.05 * uSize.x, 0.001 * uSize.y) / uScale;
|
|
||||||
float streaks = simplex2DFractal(streakUV) * 0.5;
|
|
||||||
cogl_color_out.rgb += uColor * streaks * masks.y;
|
|
||||||
cogl_color_out.a += streaks * masks.y;
|
|
||||||
|
|
||||||
// Add glimmering atoms.
|
|
||||||
vec2 atomUV = cogl_tex_coord_in[0].st + vec2(0, -0.025*uProgress/SHOWER_TIME);
|
|
||||||
atomUV *= 0.2 * uSize / uScale;
|
|
||||||
float atoms = pow((simplex3D(vec3(atomUV, uTime))), 5.0);
|
|
||||||
cogl_color_out.rgb += uColor * atoms * masks.z;
|
|
||||||
cogl_color_out.a += atoms * masks.z;
|
|
||||||
|
|
||||||
// These are pretty useful for understanding how this works.
|
|
||||||
// cogl_color_out = vec4(masks.rgb, 1.0);
|
|
||||||
// cogl_color_out = vec4(vec3(masks.x), 1.0);
|
|
||||||
// cogl_color_out = vec4(vec3(masks.y), 1.0);
|
|
||||||
// cogl_color_out = vec4(vec3(masks.z), 1.0);
|
|
||||||
// cogl_color_out = vec4(vec3(masks.w), 1.0);
|
|
||||||
// cogl_color_out = vec4(vec3(shower), 1.0);
|
|
||||||
// cogl_color_out = vec4(vec3(streaks), 1.0);
|
|
||||||
// cogl_color_out = vec4(vec3(atoms), 1.0);
|
|
||||||
`;
|
|
||||||
|
|
||||||
this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT, declarations, code, true);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
+3
-122
@@ -243,7 +243,6 @@ var Fire = class Fire {
|
|||||||
if (utils.isInShellProcess()) {
|
if (utils.isInShellProcess()) {
|
||||||
|
|
||||||
const {Clutter, Shell} = imports.gi;
|
const {Clutter, Shell} = imports.gi;
|
||||||
const shaderSnippets = Me.imports.src.shaderSnippets;
|
|
||||||
|
|
||||||
ShaderClass = GObject.registerClass({}, class ShaderClass extends Shell.GLSLEffect {
|
ShaderClass = GObject.registerClass({}, class ShaderClass extends Shell.GLSLEffect {
|
||||||
// This is called when the effect is used for the first time. This can be used to
|
// This is called when the effect is used for the first time. This can be used to
|
||||||
@@ -291,128 +290,10 @@ if (utils.isInShellProcess()) {
|
|||||||
// This is called by the constructor. This means, it's only called when the effect
|
// This is called by the constructor. This means, it's only called when the effect
|
||||||
// is used for the first time.
|
// is used for the first time.
|
||||||
vfunc_build_pipeline() {
|
vfunc_build_pipeline() {
|
||||||
|
const decl = utils.loadGLSLResource(`/shaders/${Fire.getNick()}-declarations.glsl`);
|
||||||
|
const code = utils.loadGLSLResource(`/shaders/${Fire.getNick()}.glsl`);
|
||||||
|
|
||||||
const declarations = `
|
this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT, decl, code, true);
|
||||||
// Inject some common shader snippets.
|
|
||||||
${shaderSnippets.standardUniforms()}
|
|
||||||
${shaderSnippets.noise()}
|
|
||||||
${shaderSnippets.edgeMask()}
|
|
||||||
${shaderSnippets.compositing()}
|
|
||||||
|
|
||||||
uniform bool u3DNoise;
|
|
||||||
uniform float uScale;
|
|
||||||
uniform float uMovementSpeed;
|
|
||||||
uniform vec4 uGradient1;
|
|
||||||
uniform vec4 uGradient2;
|
|
||||||
uniform vec4 uGradient3;
|
|
||||||
uniform vec4 uGradient4;
|
|
||||||
uniform vec4 uGradient5;
|
|
||||||
|
|
||||||
// These may be configurable in the future.
|
|
||||||
const float EDGE_FADE = 70;
|
|
||||||
const float FADE_WIDTH = 0.1;
|
|
||||||
const float HIDE_TIME = 0.4;
|
|
||||||
|
|
||||||
// This maps the input value from [0..1] to a color from the gradient.
|
|
||||||
vec4 getFireColor(float v) {
|
|
||||||
const float steps[5] = float[](0.0, 0.2, 0.35, 0.5, 0.8);
|
|
||||||
vec4 colors[5] = vec4[](
|
|
||||||
uGradient1,
|
|
||||||
uGradient2,
|
|
||||||
uGradient3,
|
|
||||||
uGradient4,
|
|
||||||
uGradient5
|
|
||||||
);
|
|
||||||
|
|
||||||
if (v < steps[0]) {
|
|
||||||
return colors[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i=0; i<4; ++i) {
|
|
||||||
if (v <= steps[i+1]) {
|
|
||||||
return mix(colors[i], colors[i+1], vec4(v - steps[i])/(steps[i+1]-steps[i]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return colors[4];
|
|
||||||
}
|
|
||||||
|
|
||||||
// This method requires the uniforms from standardUniforms() to be available.
|
|
||||||
// It returns two values: The first is an alpha value which can be used for the window
|
|
||||||
// texture. This gradually dissolves the window from top to bottom. The second can be used
|
|
||||||
// to mask any effect, it will be most opaque where the window is currently fading and
|
|
||||||
// gradually dissolve to zero over time.
|
|
||||||
// hideTime: A value in [0..1]. It determines the percentage of the animation which
|
|
||||||
// is spent for hiding the window. 1-hideTime will be spent thereafter for
|
|
||||||
// dissolving the effect mask.
|
|
||||||
// fadeWidth: The relative size of the window-hiding gradient in [0..1].
|
|
||||||
// edgeFadeWidth: The pixel width of the effect fading range at the edges of the window.
|
|
||||||
vec2 effectMask(float hideTime, float fadeWidth, float edgeFadeWidth) {
|
|
||||||
float burnProgress = clamp(uProgress/hideTime, 0, 1);
|
|
||||||
float afterBurnProgress = clamp((uProgress-hideTime)/(1-hideTime), 0, 1);
|
|
||||||
|
|
||||||
// Gradient from top to bottom.
|
|
||||||
float t = cogl_tex_coord_in[0].t * (1 - fadeWidth);
|
|
||||||
|
|
||||||
// Visible part of the window. Gradually dissolves towards the bottom.
|
|
||||||
float windowMask = 1 - clamp((burnProgress - t) / fadeWidth, 0, 1);
|
|
||||||
|
|
||||||
// Gradient from top burning window.
|
|
||||||
float effectMask = clamp(t*(1-windowMask)/burnProgress, 0, 1);
|
|
||||||
|
|
||||||
// Fade-out when the window burned down.
|
|
||||||
if (uProgress > hideTime) {
|
|
||||||
float fade = sqrt(1-afterBurnProgress*afterBurnProgress);
|
|
||||||
effectMask *= mix(1, 1-t, afterBurnProgress) * fade;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fade at window borders.
|
|
||||||
effectMask *= getAbsoluteEdgeMask(edgeFadeWidth);
|
|
||||||
|
|
||||||
if (uForOpening) {
|
|
||||||
windowMask = 1.0 - windowMask;
|
|
||||||
}
|
|
||||||
|
|
||||||
return vec2(windowMask, effectMask);
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const code = `
|
|
||||||
// Get a noise value which moves vertically in time.
|
|
||||||
vec2 uv = cogl_tex_coord_in[0].st * uSize / vec2(400, 600) / uScale;
|
|
||||||
uv.y += uTime * uMovementSpeed;
|
|
||||||
|
|
||||||
float noise = u3DNoise ? simplex3DFractal(vec3(uv*4.0, uTime*uMovementSpeed*1.5))
|
|
||||||
: simplex2DFractal(uv * 4.0);
|
|
||||||
|
|
||||||
// Modulate noise by effect mask.
|
|
||||||
vec2 effectMask = effectMask(HIDE_TIME, FADE_WIDTH, EDGE_FADE);
|
|
||||||
noise *= effectMask.y;
|
|
||||||
|
|
||||||
// Map noise value to color.
|
|
||||||
vec4 fire = getFireColor(noise);
|
|
||||||
|
|
||||||
// Get the window texture.
|
|
||||||
cogl_color_out = texture2D(uTexture, cogl_tex_coord_in[0].st);
|
|
||||||
|
|
||||||
// Shell.GLSLEffect uses straight alpha. So we have to convert from premultiplied.
|
|
||||||
if (cogl_color_out.a > 0) {
|
|
||||||
cogl_color_out.rgb /= cogl_color_out.a;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fade the window according to the effect mask.
|
|
||||||
cogl_color_out.a *= effectMask.x;
|
|
||||||
|
|
||||||
// Add the fire to the window.
|
|
||||||
cogl_color_out = alphaOver(cogl_color_out, fire);
|
|
||||||
|
|
||||||
// These are pretty useful for understanding how this works.
|
|
||||||
// cogl_color_out = vec4(vec3(noise), 1);
|
|
||||||
// cogl_color_out = vec4(vec3(effectMask.x), 1);
|
|
||||||
// cogl_color_out = vec4(vec3(effectMask.y), 1);
|
|
||||||
`;
|
|
||||||
|
|
||||||
this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT, declarations, code, true);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
+4
-123
@@ -136,7 +136,6 @@ var Hexagon = class Hexagon {
|
|||||||
if (utils.isInShellProcess()) {
|
if (utils.isInShellProcess()) {
|
||||||
|
|
||||||
const {Clutter, Shell} = imports.gi;
|
const {Clutter, Shell} = imports.gi;
|
||||||
const shaderSnippets = Me.imports.src.shaderSnippets;
|
|
||||||
|
|
||||||
ShaderClass = GObject.registerClass({}, class ShaderClass extends Shell.GLSLEffect {
|
ShaderClass = GObject.registerClass({}, class ShaderClass extends Shell.GLSLEffect {
|
||||||
// This is called when the effect is used for the first time. This can be used to
|
// This is called when the effect is used for the first time. This can be used to
|
||||||
@@ -183,129 +182,11 @@ if (utils.isInShellProcess()) {
|
|||||||
// This is called by the constructor. This means, it's only called when the effect
|
// This is called by the constructor. This means, it's only called when the effect
|
||||||
// is used for the first time.
|
// is used for the first time.
|
||||||
vfunc_build_pipeline() {
|
vfunc_build_pipeline() {
|
||||||
|
const decl =
|
||||||
|
utils.loadGLSLResource(`/shaders/${Hexagon.getNick()}-declarations.glsl`);
|
||||||
|
const code = utils.loadGLSLResource(`/shaders/${Hexagon.getNick()}.glsl`);
|
||||||
|
|
||||||
// Feel free to read the inline comments below to learn how this shader works.
|
this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT, decl, code, true);
|
||||||
const declarations = `
|
|
||||||
|
|
||||||
// Inject some common shader snippets.
|
|
||||||
${shaderSnippets.standardUniforms()}
|
|
||||||
${shaderSnippets.noise()}
|
|
||||||
|
|
||||||
uniform bool uAdditiveBlending;
|
|
||||||
uniform vec2 uSeed;
|
|
||||||
uniform float uScale;
|
|
||||||
uniform float uLineWidth;
|
|
||||||
uniform vec4 uGlowColor;
|
|
||||||
uniform vec4 uLineColor;
|
|
||||||
|
|
||||||
// This methods generates a procedural hexagonal pattern. It returns four values:
|
|
||||||
// result.xy: This contains cell-relative coordinates for the given point.
|
|
||||||
// [0, 0] is in the center of a cell, [0, 1] at the upper edge,
|
|
||||||
// [sqrt(4.0 / 3.0), 0] at the right tip and so on.
|
|
||||||
// result.z: This is the distance to the closest edge. This is used for shrinking
|
|
||||||
// of the tiles and the sharp overlay lines.
|
|
||||||
// result.w: This is the distance to the closest cell center. This is used for
|
|
||||||
// the glow effect.
|
|
||||||
vec4 getHexagons(vec2 p) {
|
|
||||||
|
|
||||||
// Length of a cell's edge.
|
|
||||||
const float edgeLength = sqrt(4.0 / 3.0);
|
|
||||||
|
|
||||||
// The hexgrid repeats after this distance.
|
|
||||||
const vec2 scale = vec2(3.0 * edgeLength, 2.0);
|
|
||||||
|
|
||||||
// This is a repeating grid of scale-sized cells. Y-values are in the
|
|
||||||
// interval [-1...1], X-value in [-1.5*edgeLength...1.5*edgeLength].
|
|
||||||
vec2 a = mod(p, scale) - scale * 0.5;
|
|
||||||
vec2 aAbs = abs(a);
|
|
||||||
|
|
||||||
// This is the same as above, but offset by half scale.
|
|
||||||
vec2 b = mod(p + scale * 0.5, scale) - scale * 0.5;
|
|
||||||
vec2 bAbs = abs(b);
|
|
||||||
|
|
||||||
// Distance to closer edge, diagonally or horizontally.
|
|
||||||
// Once for cell set A and once for cell set B.
|
|
||||||
float distA = max(aAbs.x / edgeLength + aAbs.y * 0.5, aAbs.y);
|
|
||||||
float distB = max(bAbs.x / edgeLength + bAbs.y * 0.5, bAbs.y);
|
|
||||||
|
|
||||||
// Minimum of both is distance to closest edge.
|
|
||||||
float dist = 1.0 - min(distA, distB);
|
|
||||||
|
|
||||||
// We use the radial distance to the center for glow.
|
|
||||||
float glow = min(dot(a, a), dot(b, b)) / 1.5;
|
|
||||||
|
|
||||||
// Take cell-relative coordinates from the closer cell.
|
|
||||||
vec2 cellCoords = distA < distB ? a : b;
|
|
||||||
|
|
||||||
return vec4(cellCoords, dist, glow);
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const code = `
|
|
||||||
// We simply inverse the progress for opening windows.
|
|
||||||
float progress = uForOpening ? 1.0-uProgress : uProgress;
|
|
||||||
|
|
||||||
// Add some smooth noise to the progress so that not every tile behaves the
|
|
||||||
// same.
|
|
||||||
float noise = simplex2D(cogl_tex_coord_in[0].st + uSeed);
|
|
||||||
progress = clamp(mix(noise - 1.0, noise + 1.0, progress), 0.0, 1.0);
|
|
||||||
|
|
||||||
// glowProgress fades in in the first half of the animation, tileProgress fades
|
|
||||||
// in in the second half.
|
|
||||||
float glowProgress = smoothstep(0, 1, clamp(progress / 0.5, 0, 1));
|
|
||||||
float tileProgress = smoothstep(0, 1, clamp((progress - 0.5) / 0.5, 0, 1));
|
|
||||||
|
|
||||||
vec2 texScale = 0.1 * uSize / uScale;
|
|
||||||
vec4 hex = getHexagons(cogl_tex_coord_in[0].st * texScale);
|
|
||||||
|
|
||||||
if (tileProgress > hex.z) {
|
|
||||||
|
|
||||||
// Crop outer parts of the shrinking tiles.
|
|
||||||
cogl_color_out.a = 0.0;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// Make the tiles shrink by offsetting the texture lookup towards the edge
|
|
||||||
// of the cell.
|
|
||||||
vec2 lookupOffset = tileProgress * hex.xy / texScale / (1.0 - tileProgress);
|
|
||||||
cogl_color_out = texture2D(uTexture, cogl_tex_coord_in[0].st + lookupOffset);
|
|
||||||
|
|
||||||
// Shell.GLSLEffect uses straight alpha. So we have to convert from premultiplied.
|
|
||||||
if (cogl_color_out.a > 0) {
|
|
||||||
cogl_color_out.rgb /= cogl_color_out.a;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec4 glow = uGlowColor;
|
|
||||||
vec4 line = uLineColor;
|
|
||||||
|
|
||||||
// For the glow, we accumulate a few exponentially scaled versions of hex.w.
|
|
||||||
glow.a *= pow(hex.w, 20.0) * 10.0 +
|
|
||||||
pow(hex.w, 10.0) * 5.0 +
|
|
||||||
pow(hex.w, 2.0) * 0.5;
|
|
||||||
|
|
||||||
// Using step(uLineWidth, hex.z) would be simpler, but the below creates some
|
|
||||||
// fake antialiasing.
|
|
||||||
line.a *= 1.0 - smoothstep(uLineWidth*0.02*0.5, uLineWidth*0.02, hex.z);
|
|
||||||
|
|
||||||
// Fade in the glowing lines.
|
|
||||||
glow.a *= glowProgress;
|
|
||||||
line.a *= glowProgress;
|
|
||||||
|
|
||||||
// Do not add the hexagon lines onto transparent parts of the window.
|
|
||||||
glow *= cogl_color_out.a;
|
|
||||||
line *= cogl_color_out.a;
|
|
||||||
|
|
||||||
if (uAdditiveBlending) {
|
|
||||||
cogl_color_out.rgb += glow.rgb * glow.a;
|
|
||||||
cogl_color_out.rgb += line.rgb * line.a;
|
|
||||||
} else {
|
|
||||||
cogl_color_out.rgb = mix(cogl_color_out.rgb, glow.rgb, glow.a);
|
|
||||||
cogl_color_out.rgb = mix(cogl_color_out.rgb, line.rgb, line.a);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT, declarations, code, true);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
+4
-101
@@ -145,7 +145,6 @@ var Matrix = class Matrix {
|
|||||||
if (utils.isInShellProcess()) {
|
if (utils.isInShellProcess()) {
|
||||||
|
|
||||||
const {Clutter, GdkPixbuf, Cogl, Shell} = imports.gi;
|
const {Clutter, GdkPixbuf, Cogl, Shell} = imports.gi;
|
||||||
const shaderSnippets = Me.imports.src.shaderSnippets;
|
|
||||||
|
|
||||||
ShaderClass = GObject.registerClass({}, class ShaderClass extends Shell.GLSLEffect {
|
ShaderClass = GObject.registerClass({}, class ShaderClass extends Shell.GLSLEffect {
|
||||||
// This is called when the effect is used for the first time. This can be used to
|
// This is called when the effect is used for the first time. This can be used to
|
||||||
@@ -197,107 +196,11 @@ if (utils.isInShellProcess()) {
|
|||||||
// https://www.shadertoy.com/view/ldccW4, however the implementation is quite
|
// 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.
|
// different as the letters drop only once and there is no need for a noise texture.
|
||||||
vfunc_build_pipeline() {
|
vfunc_build_pipeline() {
|
||||||
const declarations = `
|
const decl =
|
||||||
// Inject some common shader snippets.
|
utils.loadGLSLResource(`/shaders/${Matrix.getNick()}-declarations.glsl`);
|
||||||
${shaderSnippets.standardUniforms()}
|
const code = utils.loadGLSLResource(`/shaders/${Matrix.getNick()}.glsl`);
|
||||||
${shaderSnippets.noise()}
|
|
||||||
${shaderSnippets.edgeMask()}
|
|
||||||
${shaderSnippets.compositing()}
|
|
||||||
|
|
||||||
uniform sampler2D uFontTexture;
|
this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT, decl, code, true);
|
||||||
uniform vec3 uTrailColor;
|
|
||||||
uniform vec3 uTipColor;
|
|
||||||
uniform float uLetterSize;
|
|
||||||
uniform float uRandomness;
|
|
||||||
uniform float uOverShoot;
|
|
||||||
|
|
||||||
// These may be configurable in the future.
|
|
||||||
const float EDGE_FADE = 30;
|
|
||||||
const float FADE_WIDTH = 150;
|
|
||||||
const float TRAIL_LENGTH = 0.2;
|
|
||||||
const float FINAL_FADE_START_TIME = 0.8;
|
|
||||||
const float LETTER_TILES = 16.0;
|
|
||||||
const float LETTER_FLICKER_SPEED = 2.0;
|
|
||||||
|
|
||||||
// This returns a flickering grid of random letters.
|
|
||||||
float getText(vec2 fragCoord) {
|
|
||||||
vec2 pixelCoords = fragCoord * uSize;
|
|
||||||
vec2 uv = mod(pixelCoords.xy, uLetterSize)/uLetterSize;
|
|
||||||
vec2 block = pixelCoords/uLetterSize - uv;
|
|
||||||
|
|
||||||
// Choose random letter.
|
|
||||||
uv += floor(hash22(floor(hash22(block)*vec2(12.9898,78.233) + LETTER_FLICKER_SPEED*uTime + 42.254))*LETTER_TILES);
|
|
||||||
|
|
||||||
return texture2D(uFontTexture, uv/LETTER_TILES).r;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This returns two values: The first are gradients for the "raindrops" which move
|
|
||||||
// from top to bottom. This is used for fading the letters. The second value is set
|
|
||||||
// to one below each drop and to zero above it. This second value is used for fading
|
|
||||||
// the window texture.
|
|
||||||
vec2 getRain(vec2 fragCoord) {
|
|
||||||
float column = cogl_tex_coord_in[0].x * uSize.x;
|
|
||||||
column -= mod(column, uLetterSize);
|
|
||||||
|
|
||||||
float delay = fract(sin(column)*78.233) * mix(0.0, 1.0, uRandomness);
|
|
||||||
float speed = fract(cos(column)*12.989) * mix(0.0, 0.3, uRandomness) + 1.5;
|
|
||||||
|
|
||||||
float distToDrop = (uProgress*2-delay)*speed - cogl_tex_coord_in[0].y;
|
|
||||||
|
|
||||||
float rainAlpha = distToDrop >= 0 ? exp(-distToDrop/TRAIL_LENGTH) : 0;
|
|
||||||
float windowAlpha = 1 - clamp(uSize.y*distToDrop, 0, FADE_WIDTH) / FADE_WIDTH;
|
|
||||||
|
|
||||||
// Fade at window borders.
|
|
||||||
rainAlpha *= getAbsoluteEdgeMask(EDGE_FADE);
|
|
||||||
|
|
||||||
// Add some variation to the drop start and end position.
|
|
||||||
float shorten = fract(sin(column+42.0)*33.423) * mix(0.0, uOverShoot*0.25, uRandomness);
|
|
||||||
rainAlpha *= smoothstep(0, 1, clamp(cogl_tex_coord_in[0].y / shorten, 0, 1));
|
|
||||||
rainAlpha *= smoothstep(0, 1, clamp((1.0 - cogl_tex_coord_in[0].y) / shorten, 0, 1));
|
|
||||||
|
|
||||||
if (uForOpening) {
|
|
||||||
windowAlpha = 1.0 - windowAlpha;
|
|
||||||
}
|
|
||||||
|
|
||||||
return vec2(rainAlpha, windowAlpha);
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const code = `
|
|
||||||
vec2 coords = cogl_tex_coord_in[0].st;
|
|
||||||
coords.y = coords.y * (uOverShoot + 1.0) - uOverShoot * 0.5;
|
|
||||||
|
|
||||||
// Get a cool matrix effect. See comments for those methods above.
|
|
||||||
vec2 rainMask = getRain(coords);
|
|
||||||
float textMask = getText(coords);
|
|
||||||
|
|
||||||
// Get the window texture.
|
|
||||||
cogl_color_out = texture2D(uTexture, coords);
|
|
||||||
|
|
||||||
// Shell.GLSLEffect uses straight alpha. So we have to convert from premultiplied.
|
|
||||||
if (cogl_color_out.a > 0) {
|
|
||||||
cogl_color_out.rgb /= cogl_color_out.a;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fade the window according to the effect mask.
|
|
||||||
cogl_color_out.a *= rainMask.y;
|
|
||||||
|
|
||||||
// This is used to fade out the remaining trails in the end.
|
|
||||||
float finalFade = 1-clamp((uProgress-FINAL_FADE_START_TIME)/
|
|
||||||
(1-FINAL_FADE_START_TIME), 0, 1);
|
|
||||||
float rainAlpha = finalFade * rainMask.x;
|
|
||||||
|
|
||||||
// Add the matrix effect to the window.
|
|
||||||
vec4 text = vec4(mix(uTrailColor, uTipColor, min(1, pow(rainAlpha+0.1, 4))), rainAlpha * textMask);
|
|
||||||
cogl_color_out = alphaOver(cogl_color_out, text);
|
|
||||||
|
|
||||||
// These are pretty useful for understanding how this works.
|
|
||||||
// cogl_color_out = vec4(vec3(textMask), 1);
|
|
||||||
// cogl_color_out = vec4(vec3(rainMask.x), 1);
|
|
||||||
// cogl_color_out = vec4(vec3(rainMask.y), 1);
|
|
||||||
`;
|
|
||||||
|
|
||||||
this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT, declarations, code, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is overridden to bind the font texture for drawing. Sadly, this seems to be
|
// This is overridden to bind the font texture for drawing. Sadly, this seems to be
|
||||||
|
|||||||
@@ -143,7 +143,6 @@ var SnapOfDisintegration = class SnapOfDisintegration {
|
|||||||
if (utils.isInShellProcess()) {
|
if (utils.isInShellProcess()) {
|
||||||
|
|
||||||
const {Clutter, GdkPixbuf, Cogl, Shell} = imports.gi;
|
const {Clutter, GdkPixbuf, Cogl, Shell} = imports.gi;
|
||||||
const shaderSnippets = Me.imports.src.shaderSnippets;
|
|
||||||
|
|
||||||
ShaderClass = GObject.registerClass({}, class ShaderClass extends Shell.GLSLEffect {
|
ShaderClass = GObject.registerClass({}, class ShaderClass extends Shell.GLSLEffect {
|
||||||
// This is called when the effect is used for the first time. This can be used to
|
// This is called when the effect is used for the first time. This can be used to
|
||||||
@@ -190,99 +189,12 @@ if (utils.isInShellProcess()) {
|
|||||||
// This is called by the constructor. This means, it's only called when the effect
|
// This is called by the constructor. This means, it's only called when the effect
|
||||||
// is used for the first time.
|
// is used for the first time.
|
||||||
vfunc_build_pipeline() {
|
vfunc_build_pipeline() {
|
||||||
const declarations = `
|
const decl = utils.loadGLSLResource(
|
||||||
// Inject some common shader snippets.
|
`/shaders/${SnapOfDisintegration.getNick()}-declarations.glsl`);
|
||||||
${shaderSnippets.standardUniforms()}
|
const code =
|
||||||
${shaderSnippets.noise()}
|
utils.loadGLSLResource(`/shaders/${SnapOfDisintegration.getNick()}.glsl`);
|
||||||
${shaderSnippets.math2D()}
|
|
||||||
|
|
||||||
uniform sampler2D uDustTexture;
|
this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT, decl, code, true);
|
||||||
uniform vec4 uDustColor;
|
|
||||||
uniform vec2 uSeed;
|
|
||||||
uniform float uDustScale;
|
|
||||||
|
|
||||||
const float DUST_LAYERS = 4;
|
|
||||||
const float GROW_INTENSITY = 0.05;
|
|
||||||
const float SHRINK_INTENSITY = 0.05;
|
|
||||||
const float WIND_INTENSITY = 0.05;
|
|
||||||
const float ACTOR_SCALE = 1.2;
|
|
||||||
const float PADDING = ACTOR_SCALE / 2.0 - 0.5;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const code = `
|
|
||||||
// We simply inverse the progress for opening windows.
|
|
||||||
float progress = uForOpening ? uProgress : 1.0 - uProgress;
|
|
||||||
|
|
||||||
float gradient = cogl_tex_coord_in[0].t * ACTOR_SCALE - PADDING;
|
|
||||||
progress = 2.0 - gradient - 2.0 * progress;
|
|
||||||
progress = progress + 0.25 - 0.5 * simplex2D((cogl_tex_coord_in[0].st + uSeed) * 2.0);
|
|
||||||
progress = pow(max(0, progress), 2.0);
|
|
||||||
|
|
||||||
// This may help you to understand how this effect works.
|
|
||||||
// cogl_color_out = vec4(progress, 0, 0, 0);
|
|
||||||
// return;
|
|
||||||
|
|
||||||
cogl_color_out = vec4(0, 0, 0, 0);
|
|
||||||
|
|
||||||
for (float i=0; i<DUST_LAYERS; ++i) {
|
|
||||||
|
|
||||||
// Create a random direction.
|
|
||||||
float factor = DUST_LAYERS == 1 ? 0 : i/(DUST_LAYERS-1);
|
|
||||||
float angle = 123.123 * (uSeed.x + factor);
|
|
||||||
vec2 direction = vec2(1.0, 0.0);
|
|
||||||
direction = rotate(direction, angle);
|
|
||||||
|
|
||||||
// Flip direction for one side of the window.
|
|
||||||
vec2 coords = cogl_tex_coord_in[0].st * ACTOR_SCALE - PADDING - 0.5;
|
|
||||||
if (getWinding(direction, coords) > 0) {
|
|
||||||
direction *= -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Flip direction for half the layers.
|
|
||||||
if (factor > 0.5) {
|
|
||||||
direction *= -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We grow the layer along the random direction, shrink it orthogonally to it
|
|
||||||
// and scale it up slightly.
|
|
||||||
float dist = distToLine(vec2(0.0), direction, coords);
|
|
||||||
vec2 grow = direction * dist * mix(0, GROW_INTENSITY, progress);
|
|
||||||
vec2 shrink = vec2(direction.y, -direction.x) * dist * mix(0, SHRINK_INTENSITY, progress);
|
|
||||||
float scale = mix(1.0, 1.05, factor * progress);
|
|
||||||
coords = (coords + grow + shrink) / scale;
|
|
||||||
|
|
||||||
// Add some wind.
|
|
||||||
coords.x += WIND_INTENSITY * progress * (uForOpening ? 1.0 : -1.0);
|
|
||||||
|
|
||||||
// Now check wether there is actually something in the current dust layer at
|
|
||||||
// the coords position.
|
|
||||||
vec2 dustCoords = (coords + uSeed) * uSize / uDustScale / 100.0;
|
|
||||||
vec2 dustMap = texture2D(uDustTexture, dustCoords).rg;
|
|
||||||
float dustGroup = floor(dustMap.g * DUST_LAYERS * 0.999);
|
|
||||||
|
|
||||||
if (dustGroup == i) {
|
|
||||||
|
|
||||||
// Get the window color.
|
|
||||||
vec4 windowColor = texture2D(uTexture, coords + 0.5);
|
|
||||||
|
|
||||||
// Shell.GLSLEffect uses straight alpha. So we have to convert from premultiplied.
|
|
||||||
if (windowColor.a > 0) {
|
|
||||||
windowColor.rgb /= windowColor.a;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fade the window color to uDustColor.
|
|
||||||
vec3 dustColor = mix(windowColor.rgb, uDustColor.rgb, uDustColor.a);
|
|
||||||
windowColor.rgb = mix(windowColor.rgb, dustColor, progress);
|
|
||||||
|
|
||||||
// Dissolve and blend the layers.
|
|
||||||
if (dustMap.x - progress > 0) {
|
|
||||||
cogl_color_out = windowColor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT, declarations, code, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is overridden to bind the dust texture for drawing. Sadly, this seems to be
|
// This is overridden to bind the dust texture for drawing. Sadly, this seems to be
|
||||||
|
|||||||
+4
-111
@@ -140,7 +140,6 @@ var TRexAttack = class TRexAttack {
|
|||||||
if (utils.isInShellProcess()) {
|
if (utils.isInShellProcess()) {
|
||||||
|
|
||||||
const {Clutter, GdkPixbuf, Cogl, Shell} = imports.gi;
|
const {Clutter, GdkPixbuf, Cogl, Shell} = imports.gi;
|
||||||
const shaderSnippets = Me.imports.src.shaderSnippets;
|
|
||||||
|
|
||||||
ShaderClass = GObject.registerClass({}, class ShaderClass extends Shell.GLSLEffect {
|
ShaderClass = GObject.registerClass({}, class ShaderClass extends Shell.GLSLEffect {
|
||||||
// This is called when the effect is used for the first time. This can be used to
|
// This is called when the effect is used for the first time. This can be used to
|
||||||
@@ -190,117 +189,11 @@ if (utils.isInShellProcess()) {
|
|||||||
// This is called by the constructor. This means, it's only called when the effect
|
// This is called by the constructor. This means, it's only called when the effect
|
||||||
// is used for the first time.
|
// is used for the first time.
|
||||||
vfunc_build_pipeline() {
|
vfunc_build_pipeline() {
|
||||||
const declarations = `
|
const decl =
|
||||||
// Inject some common shader snippets.
|
utils.loadGLSLResource(`/shaders/${TRexAttack.getNick()}-declarations.glsl`);
|
||||||
${shaderSnippets.standardUniforms()}
|
const code = utils.loadGLSLResource(`/shaders/${TRexAttack.getNick()}.glsl`);
|
||||||
${shaderSnippets.noise()}
|
|
||||||
${shaderSnippets.compositing()}
|
|
||||||
|
|
||||||
// See assets/README.md for how this texture was created.
|
this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT, decl, code, true);
|
||||||
uniform sampler2D uClawTexture;
|
|
||||||
uniform vec4 uFlashColor;
|
|
||||||
uniform vec2 uSeed;
|
|
||||||
uniform float uClawSize;
|
|
||||||
uniform float uNumClaws;
|
|
||||||
uniform float uWarpIntensity;
|
|
||||||
|
|
||||||
const float FLASH_INTENSITY = 0.1;
|
|
||||||
const float MAX_SPAWN_TIME = 0.6; // Scratches will only start in the first half of the animation.
|
|
||||||
const float FF_TIME = 0.6; // Relative time for the final fade to transparency.
|
|
||||||
|
|
||||||
// This method generates a grid of randomly rotated, slightly shifted and scaled
|
|
||||||
// UV squares. It returns the texture coords of the UV square at the given actor
|
|
||||||
// coordinates. If these do not fall into one of the UV grids, the coordinates of
|
|
||||||
// the closest UV grid will be clamped and returned.
|
|
||||||
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 + hash22(seed);
|
|
||||||
coords *= uSize.x < uSize.y ? vec2(1.0, 1.0 * uSize.y / uSize.x) : vec2(1.0 * uSize.x / uSize.y, 1.0);
|
|
||||||
|
|
||||||
// Apply global scale.
|
|
||||||
coords *= gridScale;
|
|
||||||
|
|
||||||
// Get grid cell coordinates in [0..1].
|
|
||||||
vec2 cellUV = mod(coords, vec2(1));
|
|
||||||
|
|
||||||
// This is unique for each cell.
|
|
||||||
vec2 cellID = coords-cellUV + vec2(362.456);
|
|
||||||
|
|
||||||
// Add random rotation, scale and offset to each grid cell.
|
|
||||||
float scale = mix(0.8, 1.0, hash12(cellID*seed*134.451));
|
|
||||||
float offsetX = mix(0.0, 1.0 - scale, hash12(cellID*seed*54.4129));
|
|
||||||
float offsetY = mix(0.0, 1.0 - scale, hash12(cellID*seed*25.3089));
|
|
||||||
float rotation = mix(0.0, 2.0 * 3.141, hash12(cellID*seed*2.99837));
|
|
||||||
|
|
||||||
cellUV -= vec2(offsetX, offsetY);
|
|
||||||
cellUV /= scale;
|
|
||||||
|
|
||||||
cellUV -= 0.5;
|
|
||||||
cellUV = vec2(cellUV.x * cos(rotation) - cellUV.y * sin(rotation),
|
|
||||||
cellUV.x * sin(rotation) + cellUV.y * cos(rotation));
|
|
||||||
cellUV += 0.5;
|
|
||||||
|
|
||||||
// Clamp resulting coordinates.
|
|
||||||
return clamp(cellUV, vec2(0), vec2(1));
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const code = `
|
|
||||||
float progress = uForOpening ? 1.0-uProgress : uProgress;
|
|
||||||
|
|
||||||
// Warp the texture coordinates to create a blow-up effect.
|
|
||||||
vec2 coords = cogl_tex_coord_in[0].st * 2.0 - 1.0;
|
|
||||||
float dist = length(coords);
|
|
||||||
coords = (coords/dist * pow(dist, 1.0 + uWarpIntensity)) * 0.5 + 0.5;
|
|
||||||
coords = mix(cogl_tex_coord_in[0].st, coords, progress);
|
|
||||||
|
|
||||||
// Accumulate several random scratches. The color in the scratch map refers to the
|
|
||||||
// relative time when the respective part will become invisible. Therefore we can
|
|
||||||
// add a value to make the scratch appear later.
|
|
||||||
float scratchMap = 1.0;
|
|
||||||
for (int i=0; i<uNumClaws; ++i) {
|
|
||||||
vec2 uv = getClawUV(coords, 1.0/uClawSize, uSeed*(i+1));
|
|
||||||
float delay = i/uNumClaws * MAX_SPAWN_TIME;
|
|
||||||
scratchMap = min(scratchMap, clamp(texture2D(uClawTexture, uv).r + delay, 0, 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the window texture. We shift the texture lookup by the local derivative of
|
|
||||||
// the claw texture in order to mimic some folding distortion.
|
|
||||||
vec2 offset = vec2(dFdx(scratchMap), dFdy(scratchMap)) * progress * 0.5;
|
|
||||||
cogl_color_out = texture2D(uTexture, coords + offset);
|
|
||||||
|
|
||||||
// Shell.GLSLEffect uses straight alpha. So we have to convert from premultiplied.
|
|
||||||
if (cogl_color_out.a > 0) {
|
|
||||||
cogl_color_out.rgb /= cogl_color_out.a;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add colorful flashes.
|
|
||||||
float flashIntensity = 1.0 / FLASH_INTENSITY * (scratchMap - progress) + 1;
|
|
||||||
if (flashIntensity < 0 || flashIntensity >= 1) {
|
|
||||||
flashIntensity = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hide flashes where there is now window.
|
|
||||||
vec4 flash = uFlashColor;
|
|
||||||
flash.a *= flashIntensity * cogl_color_out.a * (1.0 - progress);
|
|
||||||
|
|
||||||
// Hide scratched out parts.
|
|
||||||
cogl_color_out.a *= (scratchMap > progress ? 1 : 0);
|
|
||||||
|
|
||||||
// Add flash color.
|
|
||||||
cogl_color_out = alphaOver(cogl_color_out, flash);
|
|
||||||
|
|
||||||
// Fade out the remaining shards.
|
|
||||||
float fadeProgress = smoothstep(0, 1, (progress - 1.0 + FF_TIME)/FF_TIME);
|
|
||||||
cogl_color_out.a *= sqrt(1-fadeProgress*fadeProgress);
|
|
||||||
|
|
||||||
// These are pretty useful for understanding how this works.
|
|
||||||
// cogl_color_out = vec4(vec3(flashIntensity), 1);
|
|
||||||
// cogl_color_out = vec4(vec3(scratchMap), 1);
|
|
||||||
`;
|
|
||||||
|
|
||||||
this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT, declarations, code, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is overridden to bind the claw texture for drawing. Sadly, this seems to be
|
// This is overridden to bind the claw texture for drawing. Sadly, this seems to be
|
||||||
|
|||||||
+4
-58
@@ -133,7 +133,6 @@ var TVEffect = class TVEffect {
|
|||||||
if (utils.isInShellProcess()) {
|
if (utils.isInShellProcess()) {
|
||||||
|
|
||||||
const {Clutter, Shell} = imports.gi;
|
const {Clutter, Shell} = imports.gi;
|
||||||
const shaderSnippets = Me.imports.src.shaderSnippets;
|
|
||||||
|
|
||||||
ShaderClass = GObject.registerClass({}, class ShaderClass extends Shell.GLSLEffect {
|
ShaderClass = GObject.registerClass({}, class ShaderClass extends Shell.GLSLEffect {
|
||||||
// This is called when the effect is used for the first time. This can be used to
|
// This is called when the effect is used for the first time. This can be used to
|
||||||
@@ -160,64 +159,11 @@ if (utils.isInShellProcess()) {
|
|||||||
// This is called by the constructor. This means, it's only called when the effect
|
// This is called by the constructor. This means, it's only called when the effect
|
||||||
// is used for the first time.
|
// is used for the first time.
|
||||||
vfunc_build_pipeline() {
|
vfunc_build_pipeline() {
|
||||||
const declarations = `
|
const decl =
|
||||||
// Inject some common shader snippets.
|
utils.loadGLSLResource(`/shaders/${TVEffect.getNick()}-declarations.glsl`);
|
||||||
${shaderSnippets.standardUniforms()}
|
const code = utils.loadGLSLResource(`/shaders/${TVEffect.getNick()}.glsl`);
|
||||||
|
|
||||||
uniform vec3 uColor;
|
this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT, decl, code, true);
|
||||||
|
|
||||||
const float BLUR_WIDTH = 0.01; // Width of the gradients.
|
|
||||||
const float TB_TIME = 0.7; // Relative time for the top/bottom animation.
|
|
||||||
const float LR_TIME = 0.4; // Relative time for the left/right animation.
|
|
||||||
const float LR_DELAY = 0.6; // Delay after which the left/right animation starts.
|
|
||||||
const float FF_TIME = 0.1; // Relative time for the final fade to transparency.
|
|
||||||
`;
|
|
||||||
|
|
||||||
const code = `
|
|
||||||
float progress = uForOpening ? 1.0-uProgress : uProgress;
|
|
||||||
|
|
||||||
// All of these are in [0..1] during the different stages of the animation.
|
|
||||||
// tb refers to the top-bottom animation.
|
|
||||||
// lr refers to the left-right animation.
|
|
||||||
// ff refers to the final fade animation.
|
|
||||||
float tbProgress = smoothstep(0, 1, clamp(progress/TB_TIME, 0, 1));
|
|
||||||
float lrProgress = smoothstep(0, 1, clamp((progress - LR_DELAY)/LR_TIME, 0, 1));
|
|
||||||
float ffProgress = smoothstep(0, 1, clamp((progress - 1.0 + FF_TIME)/FF_TIME, 0, 1));
|
|
||||||
|
|
||||||
// This is a top-center-bottom gradient in [0..1..0]
|
|
||||||
float tb = cogl_tex_coord_in[0].t * 2;
|
|
||||||
tb = tb < 1 ? tb : 2 - tb;
|
|
||||||
|
|
||||||
// This is a left-center-right gradient in [0..1..0]
|
|
||||||
float lr = cogl_tex_coord_in[0].s * 2;
|
|
||||||
lr = lr < 1 ? lr : 2 - lr;
|
|
||||||
|
|
||||||
// Combine the progress values with the gradients to create the alpha masks.
|
|
||||||
float tbMask = 1 - smoothstep(0, 1, clamp((tbProgress - tb) / BLUR_WIDTH, 0, 1));
|
|
||||||
float lrMask = 1 - smoothstep(0, 1, clamp((lrProgress - lr) / BLUR_WIDTH, 0, 1));
|
|
||||||
float ffMask = 1 - smoothstep(0, 1, ffProgress);
|
|
||||||
|
|
||||||
// Assemble the final alpha value.
|
|
||||||
float mask = tbMask * lrMask * ffMask;
|
|
||||||
|
|
||||||
cogl_color_out = texture2D(uTexture, cogl_tex_coord_in[0].st);
|
|
||||||
|
|
||||||
// Shell.GLSLEffect uses straight alpha. So we have to convert from premultiplied.
|
|
||||||
if (cogl_color_out.a > 0) {
|
|
||||||
cogl_color_out.rgb /= cogl_color_out.a;
|
|
||||||
}
|
|
||||||
|
|
||||||
cogl_color_out.rgb = mix(cogl_color_out.rgb, uColor * cogl_color_out.a, smoothstep(0, 1, progress));
|
|
||||||
cogl_color_out.a *= mask;
|
|
||||||
|
|
||||||
// These are pretty useful for understanding how this works.
|
|
||||||
// cogl_color_out = vec4(vec3(tbMask), 1);
|
|
||||||
// cogl_color_out = vec4(vec3(lrMask), 1);
|
|
||||||
// cogl_color_out = vec4(vec3(ffMask), 1);
|
|
||||||
// cogl_color_out = vec4(vec3(mask), 1);
|
|
||||||
`;
|
|
||||||
|
|
||||||
this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT, declarations, code, true);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
+4
-101
@@ -133,7 +133,6 @@ var Wisps = class Wisps {
|
|||||||
if (utils.isInShellProcess()) {
|
if (utils.isInShellProcess()) {
|
||||||
|
|
||||||
const {Clutter, Shell} = imports.gi;
|
const {Clutter, Shell} = imports.gi;
|
||||||
const shaderSnippets = Me.imports.src.shaderSnippets;
|
|
||||||
|
|
||||||
ShaderClass = GObject.registerClass({}, class ShaderClass extends Shell.GLSLEffect {
|
ShaderClass = GObject.registerClass({}, class ShaderClass extends Shell.GLSLEffect {
|
||||||
// This is called when the effect is used for the first time. This can be used to
|
// This is called when the effect is used for the first time. This can be used to
|
||||||
@@ -170,107 +169,11 @@ if (utils.isInShellProcess()) {
|
|||||||
// This is called by the constructor. This means, it's only called when the effect
|
// This is called by the constructor. This means, it's only called when the effect
|
||||||
// is used for the first time.
|
// is used for the first time.
|
||||||
vfunc_build_pipeline() {
|
vfunc_build_pipeline() {
|
||||||
const declarations = `
|
const decl =
|
||||||
// Inject some common shader snippets.
|
utils.loadGLSLResource(`/shaders/${Wisps.getNick()}-declarations.glsl`);
|
||||||
${shaderSnippets.standardUniforms()}
|
const code = utils.loadGLSLResource(`/shaders/${Wisps.getNick()}.glsl`);
|
||||||
${shaderSnippets.noise()}
|
|
||||||
${shaderSnippets.edgeMask()}
|
|
||||||
${shaderSnippets.compositing()}
|
|
||||||
|
|
||||||
uniform vec2 uSeed;
|
this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT, decl, code, true);
|
||||||
uniform vec3 uColor;
|
|
||||||
uniform float uScale;
|
|
||||||
|
|
||||||
const float WISPS_RADIUS = 20.0;
|
|
||||||
const float WISPS_SPEED = 10.0;
|
|
||||||
const float WISPS_SPACING = 40 + WISPS_RADIUS;
|
|
||||||
const int WISPS_LAYERS = 8;
|
|
||||||
const float WISPS_IN_TIME = 0.5;
|
|
||||||
const float WINDOW_OUT_TIME = 1.0;
|
|
||||||
|
|
||||||
// Returns a grid of randomly moving points. Each grid cell contains one point which
|
|
||||||
// moves on an ellipse.
|
|
||||||
float getWisps(vec2 texCoords, float gridSize, vec2 seed) {
|
|
||||||
|
|
||||||
// Shift coordinates by a random offset and make sure the have a 1:1 aspect ratio.
|
|
||||||
vec2 coords = (texCoords + hash22(seed)) * uSize;
|
|
||||||
|
|
||||||
// Apply global scale.
|
|
||||||
coords /= gridSize;
|
|
||||||
|
|
||||||
// Get grid cell coordinates in [0..1].
|
|
||||||
vec2 cellUV = mod(coords, vec2(1));
|
|
||||||
|
|
||||||
// This is unique for each cell.
|
|
||||||
vec2 cellID = coords-cellUV + vec2(362.456);
|
|
||||||
|
|
||||||
// Add random rotation, scale and offset to each grid cell.
|
|
||||||
float speed = mix(10.0, 15.0, hash12(cellID*seed*134.451)) / gridSize * WISPS_SPEED;
|
|
||||||
float rotation = mix( 0.0, 6.283, hash12(cellID*seed*54.4129));
|
|
||||||
float radius = mix( 0.5, 1.0, hash12(cellID*seed*19.1249)) * WISPS_RADIUS;
|
|
||||||
float roundness = mix(-1.0, 1.0, hash12(cellID*seed*7.51949));
|
|
||||||
|
|
||||||
vec2 offset = vec2(sin(speed * (uTime+1)) * roundness, cos(speed * (uTime+1)));
|
|
||||||
offset *= 0.5 - 0.5 * radius / gridSize;
|
|
||||||
offset = vec2(offset.x * cos(rotation) - offset.y * sin(rotation),
|
|
||||||
offset.x * sin(rotation) + offset.y * cos(rotation));
|
|
||||||
|
|
||||||
cellUV += offset;
|
|
||||||
|
|
||||||
// Use distance to center of shifted / rotated UV coordinates to draw a glaring point.
|
|
||||||
float dist = length(cellUV - 0.5) * gridSize / radius;
|
|
||||||
if (dist < 1.0) {
|
|
||||||
return min(5, 0.01 / pow(dist, 2.0));
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const code = `
|
|
||||||
float progress = uForOpening ? 1.0-uProgress : uProgress;
|
|
||||||
|
|
||||||
// Get the color of the window.
|
|
||||||
cogl_color_out = texture2D(uTexture, cogl_tex_coord_in[0].st);
|
|
||||||
|
|
||||||
// Shell.GLSLEffect uses straight alpha. So we have to convert from premultiplied.
|
|
||||||
if (cogl_color_out.a > 0) {
|
|
||||||
cogl_color_out.rgb /= cogl_color_out.a;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compute several layers of moving wisps.
|
|
||||||
vec2 uv = (cogl_tex_coord_in[0].st-0.5) / mix(1.0, 0.5, progress) + 0.5;
|
|
||||||
uv /= uScale;
|
|
||||||
float wisps = 0;
|
|
||||||
for (int i=0; i<WISPS_LAYERS; ++i) {
|
|
||||||
wisps += getWisps(uv*0.3, WISPS_SPACING, uSeed * (i+1));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compute shrinking edge mask.
|
|
||||||
float mask = getRelativeEdgeMask(mix(0.01, 0.5, progress));
|
|
||||||
|
|
||||||
// Compute three different progress values.
|
|
||||||
float wispsIn = smoothstep(0, 1, clamp(progress/WISPS_IN_TIME, 0, 1));
|
|
||||||
float wispsOut = smoothstep(0, 1, clamp((progress - WISPS_IN_TIME)/(1.0 - WISPS_IN_TIME), 0, 1));
|
|
||||||
float windowOut = smoothstep(0, 1, clamp(progress/WINDOW_OUT_TIME, 0, 1));
|
|
||||||
|
|
||||||
// Use a noise function to dissolve the window.
|
|
||||||
float noise = smoothstep(1.0, 0.0, abs(2.0 * simplex2DFractal(uv * uSize / 250) - 1.0));
|
|
||||||
float windowMask = 1.0 - (windowOut < 0.5 ? mix(0.0, noise, windowOut * 2.0) : mix(noise, 1.0, windowOut * 2.0 - 1.0));
|
|
||||||
cogl_color_out.a *= windowMask * mask;
|
|
||||||
|
|
||||||
// Add the wisps.
|
|
||||||
vec4 wispColor = wisps * vec4(uColor, min(wispsIn, 1.0 - wispsOut)*mask);
|
|
||||||
cogl_color_out = alphaOver(cogl_color_out, wispColor);
|
|
||||||
|
|
||||||
// These are pretty useful for understanding how this works.
|
|
||||||
// cogl_color_out = vec4(vec3(windowMask), 1.0);
|
|
||||||
// cogl_color_out = vec4(vec3(wisps), 1.0);
|
|
||||||
// cogl_color_out = vec4(vec3(noise), 1.0);
|
|
||||||
// cogl_color_out = vec4(vec3(mask*min(wispsIn, 1.0 - wispsOut)), 1.0);
|
|
||||||
`;
|
|
||||||
|
|
||||||
this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT, declarations, code, true);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1,304 +0,0 @@
|
|||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// ) ( //
|
|
||||||
// ( /( ( ( ) ( ( ( ( )\ ) ( ( //
|
|
||||||
// )\()) ))\ )( ( ( )\ ) )\))( )\ ( (()/( ( )\))( ( //
|
|
||||||
// ((_)\ /((_|()\ )\ ) )\ '(()/( ((_)()((_) )\ ) ((_)))\((_)()\ )\ //
|
|
||||||
// | |(_|_))( ((_)_(_/( _((_)) )(_)) _(()((_|_)_(_/( _| |((_)(()((_|(_) //
|
|
||||||
// | '_ \ || | '_| ' \)) | ' \()| || | \ V V / | ' \)) _` / _ \ V V (_-< //
|
|
||||||
// |_.__/\_,_|_| |_||_| |_|_|_| \_, | \_/\_/|_|_||_|\__,_\___/\_/\_//__/ //
|
|
||||||
// |__/ //
|
|
||||||
// Copyright (c) 2021 Simon Schneegans //
|
|
||||||
// Released under the GPLv3 or later. See LICENSE file for details. //
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// These functions return strings which can be injected to GLSL shader code. //
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// These should be included in every shader.
|
|
||||||
// uForOpening: True if a window-open animation is ongoing, false otherwise.
|
|
||||||
// uTexture: Contains the texture of the window.
|
|
||||||
// uProgress: A value which transitions from 0 to 1 during the entire animation.
|
|
||||||
// uTime: A steadily increasing value in seconds.
|
|
||||||
// uSize: The size of uTexture in pixels.
|
|
||||||
function standardUniforms() {
|
|
||||||
return `
|
|
||||||
uniform bool uForOpening;
|
|
||||||
uniform sampler2D uTexture;
|
|
||||||
uniform float uProgress;
|
|
||||||
uniform float uTime;
|
|
||||||
uniform vec2 uSize;
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function math2D() {
|
|
||||||
return `
|
|
||||||
float distToLine(vec2 origin, vec2 direction, vec2 point) {
|
|
||||||
vec2 perpendicular = vec2(direction.y, -direction.x);
|
|
||||||
return abs(dot(normalize(perpendicular), origin - point));
|
|
||||||
}
|
|
||||||
|
|
||||||
float getWinding(vec2 a, vec2 b) {
|
|
||||||
return cross(vec3(a, 0.0), vec3(b, 0.0)).z;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec2 rotate(vec2 a, float angle) {
|
|
||||||
return vec2(a.x * cos(angle) - a.y * sin(angle),
|
|
||||||
a.x * sin(angle) + a.y * cos(angle));
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The Shell.GLSLEffect uses straight alpha blending. This helper method allows
|
|
||||||
// compositing color values in the shader in the same way.
|
|
||||||
function compositing() {
|
|
||||||
return `
|
|
||||||
vec4 alphaOver(vec4 under, vec4 over) {
|
|
||||||
float alpha = over.a + under.a * (1.0 - over.a);
|
|
||||||
return vec4((over.rgb * over.a + under.rgb * under.a * (1.0 - over.a)) / alpha, alpha);
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This method returns a mask which smoothly transitions towards zero when approaching
|
|
||||||
// the window's borders. There is a variant which takes the transition area width in
|
|
||||||
// pixels and one which takes this as a percentage.
|
|
||||||
function edgeMask() {
|
|
||||||
return `
|
|
||||||
float getEdgeMask(vec2 uv, vec2 maxUV, float fadeWidth) {
|
|
||||||
float mask = 1.0;
|
|
||||||
mask *= smoothstep(0, 1, clamp(uv.x / fadeWidth, 0, 1));
|
|
||||||
mask *= smoothstep(0, 1, clamp(uv.y / fadeWidth, 0, 1));
|
|
||||||
mask *= smoothstep(0, 1, clamp((maxUV.x - uv.x) / fadeWidth, 0, 1));
|
|
||||||
mask *= smoothstep(0, 1, clamp((maxUV.y - uv.y) / fadeWidth, 0, 1));
|
|
||||||
|
|
||||||
return mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
float getAbsoluteEdgeMask(float fadePixels) {
|
|
||||||
vec2 uv = cogl_tex_coord_in[0].st * uSize;
|
|
||||||
return getEdgeMask(uv, uSize, fadePixels);
|
|
||||||
}
|
|
||||||
|
|
||||||
float getRelativeEdgeMask(float fadeAmount) {
|
|
||||||
vec2 uv = cogl_tex_coord_in[0].st;
|
|
||||||
return getEdgeMask(uv, vec2(1.0), fadeAmount);
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// These noise algorithms are based on implementations by various authors from
|
|
||||||
// shadertoy.com, which are all available under the MIT License. See the respective links
|
|
||||||
// in the comments below.
|
|
||||||
function noise() {
|
|
||||||
return `
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Hash without Sine //
|
|
||||||
// MIT License, https://www.shadertoy.com/view/4djSRW //
|
|
||||||
// Copyright (c) 2014 David Hoskins. //
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// 1 out, 1 in...
|
|
||||||
float hash11(float p) {
|
|
||||||
p = fract(p * .1031);
|
|
||||||
p *= p + 33.33;
|
|
||||||
p *= p + p;
|
|
||||||
return fract(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 1 out, 2 in...
|
|
||||||
float hash12(vec2 p) {
|
|
||||||
vec3 p3 = fract(vec3(p.xyx) * .1031);
|
|
||||||
p3 += dot(p3, p3.yzx + 33.33);
|
|
||||||
return fract((p3.x + p3.y) * p3.z);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 1 out, 3 in...
|
|
||||||
float hash13(vec3 p3) {
|
|
||||||
p3 = fract(p3 * .1031);
|
|
||||||
p3 += dot(p3, p3.zyx + 31.32);
|
|
||||||
return fract((p3.x + p3.y) * p3.z);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2 out, 1 in...
|
|
||||||
vec2 hash21(float p) {
|
|
||||||
vec3 p3 = fract(vec3(p) * vec3(.1031, .1030, .0973));
|
|
||||||
p3 += dot(p3, p3.yzx + 33.33);
|
|
||||||
return fract((p3.xx+p3.yz)*p3.zy);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2 out, 2 in...
|
|
||||||
vec2 hash22(vec2 p) {
|
|
||||||
vec3 p3 = fract(vec3(p.xyx) * vec3(.1031, .1030, .0973));
|
|
||||||
p3 += dot(p3, p3.yzx+33.33);
|
|
||||||
return fract((p3.xx+p3.yz)*p3.zy);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2 out, 3 in...
|
|
||||||
vec2 hash23(vec3 p3) {
|
|
||||||
p3 = fract(p3 * vec3(.1031, .1030, .0973));
|
|
||||||
p3 += dot(p3, p3.yzx+33.33);
|
|
||||||
return fract((p3.xx+p3.yz)*p3.zy);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3 out, 1 in...
|
|
||||||
vec3 hash31(float p) {
|
|
||||||
vec3 p3 = fract(vec3(p) * vec3(.1031, .1030, .0973));
|
|
||||||
p3 += dot(p3, p3.yzx+33.33);
|
|
||||||
return fract((p3.xxy+p3.yzz)*p3.zyx);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3 out, 2 in...
|
|
||||||
vec3 hash32(vec2 p) {
|
|
||||||
vec3 p3 = fract(vec3(p.xyx) * vec3(.1031, .1030, .0973));
|
|
||||||
p3 += dot(p3, p3.yxz+33.33);
|
|
||||||
return fract((p3.xxy+p3.yzz)*p3.zyx);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3 out, 3 in...
|
|
||||||
vec3 hash33(vec3 p3) {
|
|
||||||
p3 = fract(p3 * vec3(.1031, .1030, .0973));
|
|
||||||
p3 += dot(p3, p3.yxz+33.33);
|
|
||||||
return fract((p3.xxy + p3.yxx)*p3.zyx);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4 out, 1 in...
|
|
||||||
vec4 hash41(float p) {
|
|
||||||
vec4 p4 = fract(vec4(p) * vec4(.1031, .1030, .0973, .1099));
|
|
||||||
p4 += dot(p4, p4.wzxy+33.33);
|
|
||||||
return fract((p4.xxyz+p4.yzzw)*p4.zywx);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4 out, 2 in...
|
|
||||||
vec4 hash42(vec2 p) {
|
|
||||||
vec4 p4 = fract(vec4(p.xyxy) * vec4(.1031, .1030, .0973, .1099));
|
|
||||||
p4 += dot(p4, p4.wzxy+33.33);
|
|
||||||
return fract((p4.xxyz+p4.yzzw)*p4.zywx);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4 out, 3 in...
|
|
||||||
vec4 hash43(vec3 p) {
|
|
||||||
vec4 p4 = fract(vec4(p.xyzx) * vec4(.1031, .1030, .0973, .1099));
|
|
||||||
p4 += dot(p4, p4.wzxy+33.33);
|
|
||||||
return fract((p4.xxyz+p4.yzzw)*p4.zywx);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4 out, 4 in...
|
|
||||||
vec4 hash44(vec4 p4) {
|
|
||||||
p4 = fract(p4 * vec4(.1031, .1030, .0973, .1099));
|
|
||||||
p4 += dot(p4, p4.wzxy+33.33);
|
|
||||||
return fract((p4.xxyz+p4.yzzw)*p4.zywx);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// 2D Simplex Noise //
|
|
||||||
// MIT License, https://www.shadertoy.com/view/Msf3WH //
|
|
||||||
// Copyright © 2013 Inigo Quilez //
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
float simplex2D(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 * hash22(i+0.0)),
|
|
||||||
dot(b,-1.0 + 2.0 * hash22(i+o)),
|
|
||||||
dot(c,-1.0 + 2.0 * hash22(i+1.0)));
|
|
||||||
return 0.5 + 0.5 * dot( n, vec3(70.0) );
|
|
||||||
}
|
|
||||||
|
|
||||||
float simplex2DFractal(vec2 p) {
|
|
||||||
mat2 m = mat2( 1.6, 1.2, -1.2, 1.6 );
|
|
||||||
float f = 0.5000*simplex2D( p ); p = m*p;
|
|
||||||
f += 0.2500*simplex2D( p ); p = m*p;
|
|
||||||
f += 0.1250*simplex2D( p ); p = m*p;
|
|
||||||
f += 0.0625*simplex2D( p ); p = m*p;
|
|
||||||
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// 3D Simplex Noise //
|
|
||||||
// MIT License, https://www.shadertoy.com/view/XsX3zB //
|
|
||||||
// Copyright © 2013 Nikita Miropolskiy //
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
float simplex3D(vec3 p) {
|
|
||||||
|
|
||||||
// skew constants for 3D simplex functions
|
|
||||||
const float F3 = 0.3333333;
|
|
||||||
const float G3 = 0.1666667;
|
|
||||||
|
|
||||||
// 1. find current tetrahedron T and it's four vertices
|
|
||||||
// s, s+i1, s+i2, s+1.0 - absolute skewed (integer) coordinates of T vertices
|
|
||||||
// x, x1, x2, x3 - unskewed coordinates of p relative to each of T vertice
|
|
||||||
|
|
||||||
// calculate s and x
|
|
||||||
vec3 s = floor(p + dot(p, vec3(F3)));
|
|
||||||
vec3 x = p - s + dot(s, vec3(G3));
|
|
||||||
|
|
||||||
// calculate i1 and i2
|
|
||||||
vec3 e = step(vec3(0.0), x - x.yzx);
|
|
||||||
vec3 i1 = e*(1.0 - e.zxy);
|
|
||||||
vec3 i2 = 1.0 - e.zxy*(1.0 - e);
|
|
||||||
|
|
||||||
// x1, x2, x3
|
|
||||||
vec3 x1 = x - i1 + G3;
|
|
||||||
vec3 x2 = x - i2 + 2.0*G3;
|
|
||||||
vec3 x3 = x - 1.0 + 3.0*G3;
|
|
||||||
|
|
||||||
// 2. find four surflets and store them in d
|
|
||||||
vec4 w, d;
|
|
||||||
|
|
||||||
// calculate surflet weights
|
|
||||||
w.x = dot(x, x);
|
|
||||||
w.y = dot(x1, x1);
|
|
||||||
w.z = dot(x2, x2);
|
|
||||||
w.w = dot(x3, x3);
|
|
||||||
|
|
||||||
// w fades from 0.6 at the center of the surflet to 0.0 at the margin
|
|
||||||
w = max(0.6 - w, 0.0);
|
|
||||||
|
|
||||||
// calculate surflet components
|
|
||||||
d.x = dot(-0.5 + hash33(s), x);
|
|
||||||
d.y = dot(-0.5 + hash33(s + i1), x1);
|
|
||||||
d.z = dot(-0.5 + hash33(s + i2), x2);
|
|
||||||
d.w = dot(-0.5 + hash33(s + 1.0), x3);
|
|
||||||
|
|
||||||
// multiply d by w^4
|
|
||||||
w *= w;
|
|
||||||
w *= w;
|
|
||||||
d *= w;
|
|
||||||
|
|
||||||
// 3. return the sum of the four surflets
|
|
||||||
return dot(d, vec4(52.0)) * 0.5 + 0.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// directional artifacts can be reduced by rotating each octave
|
|
||||||
float simplex3DFractal(vec3 m) {
|
|
||||||
|
|
||||||
// const matrices for 3D rotation
|
|
||||||
const mat3 rot1 = mat3(-0.37, 0.36, 0.85,-0.14,-0.93, 0.34,0.92, 0.01,0.4);
|
|
||||||
const mat3 rot2 = mat3(-0.55,-0.39, 0.74, 0.33,-0.91,-0.24,0.77, 0.12,0.63);
|
|
||||||
const mat3 rot3 = mat3(-0.71, 0.52,-0.47,-0.08,-0.72,-0.68,-0.7,-0.45,0.56);
|
|
||||||
|
|
||||||
return 0.5333333*simplex3D(m*rot1)
|
|
||||||
+0.2666667*simplex3D(2.0*m*rot2)
|
|
||||||
+0.1333333*simplex3D(4.0*m*rot3)
|
|
||||||
+0.0666667*simplex3D(8.0*m);
|
|
||||||
}
|
|
||||||
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
+24
-1
@@ -13,7 +13,8 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const {Gtk} = imports.gi;
|
const {Gtk, Gio} = imports.gi;
|
||||||
|
const ByteArray = imports.byteArray;
|
||||||
|
|
||||||
// Returns the given argument, except for "alpha", "beta", and "rc". In these cases -3,
|
// Returns the given argument, except for "alpha", "beta", and "rc". In these cases -3,
|
||||||
// -2, and -1 are returned respectively.
|
// -2, and -1 are returned respectively.
|
||||||
@@ -89,4 +90,26 @@ function shellVersionIsAtLeast(major, minor) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This loads the file at 'path' contained in the extension's resources to a JavaScript
|
||||||
|
// string.
|
||||||
|
function loadStringResource(path) {
|
||||||
|
const data = Gio.resources_lookup_data(path, 0);
|
||||||
|
return ByteArray.toString(ByteArray.fromGBytes(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
// This loads a GLSL file from the extension's resources to a JavaScript string. Any
|
||||||
|
// #include statements in this file are replaced with the corresponding file contents.
|
||||||
|
function loadGLSLResource(path) {
|
||||||
|
let code = loadStringResource(path);
|
||||||
|
|
||||||
|
// This regex matches either #include "..." or #include <...>. The part between the
|
||||||
|
// brackets is captured in the named "file" capture group.
|
||||||
|
code = code.replaceAll(/#include ["<](?<file>.+)[">]/g, (m, p1, p2, str, groups) => {
|
||||||
|
return loadStringResource('/shaders/' + groups.file);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add a trailing newline. Else the GLSL compiler complains...
|
||||||
|
return code + '\n';
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user