♻️ Use a single GLSL files for each effect

This commit is contained in:
Simon Schneegans
2022-05-13 09:17:26 +02:00
parent 84d5ad9caf
commit 7b8d6e18b2
34 changed files with 1006 additions and 915 deletions
@@ -1,13 +0,0 @@
// 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;
+41 -25
View File
@@ -1,33 +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"
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;
// 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;
void main() {
// 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;
// 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);
// 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;
// "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)));
// 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;
}
// 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;
// Fade out the window texture.
cogl_color_out.a *= 1.0 - progress;
}
@@ -1,15 +0,0 @@
// 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;
+53 -35
View File
@@ -1,49 +1,67 @@
cogl_color_out = vec4(0, 0, 0, 0);
// 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"
float progress = uForOpening ? 1.0 - uProgress : uProgress;
uniform sampler2D uShardTexture;
uniform vec2 uSeed;
uniform vec2 uEpicenter;
uniform float uShardScale;
uniform float uBlowForce;
uniform float uGravity;
// Draw the individual shard layers.
for (float i = 0; i < SHARD_LAYERS; ++i) {
const float SHARD_LAYERS = 5;
const float ACTOR_SCALE = 2.0;
const float PADDING = ACTOR_SCALE / 2.0 - 0.5;
// 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;
void main() {
cogl_color_out = vec4(0, 0, 0, 0);
// Scale and rotate around our epicenter.
coords -= uEpicenter;
float progress = uForOpening ? 1.0 - uProgress : uProgress;
// Scale each layer a bit differently.
coords /= mix(1.0, 1.0 + uBlowForce * (i + 2) / SHARD_LAYERS, progress);
// Draw the individual shard layers.
for (float i = 0; i < SHARD_LAYERS; ++i) {
// 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));
// 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;
// Move down each layer a bit.
float gravity =
(uForOpening ? -1.0 : 1.0) * uGravity * 0.1 * (i + 1) * progress * progress;
coords += vec2(0, gravity);
// Scale and rotate around our epicenter.
coords -= uEpicenter;
// Restore correct position.
coords += uEpicenter;
// Scale each layer a bit differently.
coords /= mix(1.0, 1.0 + uBlowForce * (i + 2) / SHARD_LAYERS, progress);
// Retrieve information from the shard texture for our layer.
vec2 shardCoords = (coords + uSeed) * uSize / uShardScale / 500.0;
vec2 shardMap = texture2D(uShardTexture, shardCoords).rg;
// 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));
// 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);
// Move down each layer a bit.
float gravity =
(uForOpening ? -1.0 : 1.0) * uGravity * 0.1 * (i + 1) * progress * progress;
coords += vec2(0, gravity);
if (shardGroup == i && (shardMap.x - pow(progress + 0.1, 2)) > 0) {
cogl_color_out = texture2D(uTexture, coords);
// 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;
// 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;
}
}
@@ -1,50 +0,0 @@
// 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/easing.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 progress) {
float fadeInProgress = clamp(progress / FADE_IN_TIME, 0, 1);
float fadeOutProgress = clamp((progress - FADE_IN_TIME) / FADE_OUT_TIME, 0, 1);
float heartProgress =
clamp((progress - (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);
}
+81 -28
View File
@@ -1,37 +1,90 @@
float progress = easeOutQuad(uProgress);
// 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/easing.glsl"
vec2 masks = getMasks(progress);
vec4 windowColor = texture2D(uTexture, cogl_tex_coord_in[0].st);
uniform vec3 uColor;
uniform float uScale;
// Shell.GLSLEffect uses straight alpha. So we have to convert from premultiplied.
if (windowColor.a > 0) {
windowColor.rgb /= windowColor.a;
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 progress) {
float fadeInProgress = clamp(progress / FADE_IN_TIME, 0, 1);
float fadeOutProgress = clamp((progress - FADE_IN_TIME) / FADE_OUT_TIME, 0, 1);
float heartProgress =
clamp((progress - (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);
}
// 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;
void main() {
float progress = easeOutQuad(uProgress);
vec2 scaledUV = (cogl_tex_coord_in[0].st - 0.5) * (1.0 + 0.1 * progress);
scaledUV /= uScale;
vec2 masks = getMasks(progress);
vec4 windowColor = texture2D(uTexture, cogl_tex_coord_in[0].st);
// 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);
// Shell.GLSLEffect uses straight alpha. So we have to convert from premultiplied.
if (windowColor.a > 0) {
windowColor.rgb /= windowColor.a;
}
// 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);
}
// 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;
cogl_color_out.rgb += uColor * particles * masks.x;
cogl_color_out.a += particles * masks.x;
vec2 scaledUV = (cogl_tex_coord_in[0].st - 0.5) * (1.0 + 0.1 * progress);
scaledUV /= uScale;
// 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);
// 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);
}
@@ -1,67 +0,0 @@
// 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/easing.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 progress) {
float showerProgress = progress / SHOWER_TIME;
float streakProgress = clamp((progress - SHOWER_TIME) / STREAK_TIME, 0, 1);
float fadeProgress = clamp((progress - 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);
}
+106 -36
View File
@@ -1,44 +1,114 @@
float progress = easeOutQuad(uProgress);
// 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/easing.glsl"
vec4 masks = getMasks(progress);
vec4 windowColor = texture2D(uTexture, cogl_tex_coord_in[0].st);
uniform vec3 uColor;
uniform float uScale;
// Shell.GLSLEffect uses straight alpha. So we have to convert from premultiplied.
if (windowColor.a > 0) {
windowColor.rgb /= windowColor.a;
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 progress) {
float showerProgress = progress / SHOWER_TIME;
float streakProgress = clamp((progress - SHOWER_TIME) / STREAK_TIME, 0, 1);
float fadeProgress = clamp((progress - 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);
}
// 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;
void main() {
float progress = easeOutQuad(uProgress);
// Add leading shower particles.
vec2 showerUV = cogl_tex_coord_in[0].st + vec2(0, -0.7 * progress / 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;
vec4 masks = getMasks(progress);
vec4 windowColor = texture2D(uTexture, cogl_tex_coord_in[0].st);
// Add trailing streak lines.
vec2 streakUV = cogl_tex_coord_in[0].st + vec2(0, -progress / 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;
// Shell.GLSLEffect uses straight alpha. So we have to convert from premultiplied.
if (windowColor.a > 0) {
windowColor.rgb /= windowColor.a;
}
// Add glimmering atoms.
vec2 atomUV = cogl_tex_coord_in[0].st + vec2(0, -0.025 * progress / 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;
// 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;
// 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);
// Add leading shower particles.
vec2 showerUV = cogl_tex_coord_in[0].st + vec2(0, -0.7 * progress / 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, -progress / 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 * progress / 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);
}
-82
View File
@@ -1,82 +0,0 @@
// 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"
#include "common/easing.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 progress = easeOutQuad(uProgress);
float burnProgress = clamp(progress / hideTime, 0, 1);
float afterBurnProgress = clamp((progress - 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 (progress > 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);
}
+108 -23
View File
@@ -1,32 +1,117 @@
// 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;
// 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"
#include "common/easing.glsl"
float noise = u3DNoise ? simplex3DFractal(vec3(uv * 4.0, uTime* uMovementSpeed * 1.5))
: simplex2DFractal(uv * 4.0);
uniform bool u3DNoise;
uniform float uScale;
uniform float uMovementSpeed;
uniform vec4 uGradient1;
uniform vec4 uGradient2;
uniform vec4 uGradient3;
uniform vec4 uGradient4;
uniform vec4 uGradient5;
// Modulate noise by effect mask.
vec2 effectMask = effectMask(HIDE_TIME, FADE_WIDTH, EDGE_FADE);
noise *= effectMask.y;
// These may be configurable in the future.
const float EDGE_FADE = 70;
const float FADE_WIDTH = 0.1;
const float HIDE_TIME = 0.4;
// Map noise value to color.
vec4 fire = getFireColor(noise);
// 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);
// Get the window texture.
cogl_color_out = texture2D(uTexture, cogl_tex_coord_in[0].st);
if (v < steps[0]) {
return colors[0];
}
// 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;
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];
}
// Fade the window according to the effect mask.
cogl_color_out.a *= effectMask.x;
// 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 progress = easeOutQuad(uProgress);
// Add the fire to the window.
cogl_color_out = alphaOver(cogl_color_out, fire);
float burnProgress = clamp(progress / hideTime, 0, 1);
float afterBurnProgress = clamp((progress - hideTime) / (1 - hideTime), 0, 1);
// 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);
// 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 (progress > 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);
}
void main() {
// 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);
}
@@ -1,54 +0,0 @@
// 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);
}
+99 -42
View File
@@ -1,59 +1,116 @@
// We simply inverse the progress for opening windows.
float progress = uForOpening ? 1.0 - uProgress : uProgress;
// 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"
// 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);
uniform bool uAdditiveBlending;
uniform vec2 uSeed;
uniform float uScale;
uniform float uLineWidth;
uniform vec4 uGlowColor;
uniform vec4 uLineColor;
// 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));
// 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) {
vec2 texScale = 0.1 * uSize / uScale;
vec4 hex = getHexagons(cogl_tex_coord_in[0].st * texScale);
// Length of a cell's edge.
const float edgeLength = sqrt(4.0 / 3.0);
if (tileProgress > hex.z) {
// The hexgrid repeats after this distance.
const vec2 scale = vec2(3.0 * edgeLength, 2.0);
// Crop outer parts of the shrinking tiles.
cogl_color_out.a = 0.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);
} else {
// 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);
// 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);
// 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);
// 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;
}
// Minimum of both is distance to closest edge.
float dist = 1.0 - min(distA, distB);
vec4 glow = uGlowColor;
vec4 line = uLineColor;
// We use the radial distance to the center for glow.
float glow = min(dot(a, a), dot(b, b)) / 1.5;
// 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;
// Take cell-relative coordinates from the closer cell.
vec2 cellCoords = distA < distB ? a : b;
// 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);
return vec4(cellCoords, dist, glow);
}
// Fade in the glowing lines.
glow.a *= glowProgress;
line.a *= glowProgress;
void main() {
// We simply inverse the progress for opening windows.
float progress = uForOpening ? 1.0 - uProgress : uProgress;
// Do not add the hexagon lines onto transparent parts of the window.
glow *= cogl_color_out.a;
line *= cogl_color_out.a;
// 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;
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);
// 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);
}
}
}
@@ -1,68 +0,0 @@
// 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);
}
+95 -24
View File
@@ -1,32 +1,103 @@
vec2 coords = cogl_tex_coord_in[0].st;
coords.y = coords.y * (uOverShoot + 1.0) - uOverShoot * 0.5;
// 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"
// Get a cool matrix effect. See comments for those methods above.
vec2 rainMask = getRain(coords);
float textMask = getText(coords);
uniform sampler2D uFontTexture;
uniform vec3 uTrailColor;
uniform vec3 uTipColor;
uniform float uLetterSize;
uniform float uRandomness;
uniform float uOverShoot;
// Get the window texture.
cogl_color_out = texture2D(uTexture, coords);
// 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;
// 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 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;
}
// Fade the window according to the effect mask.
cogl_color_out.a *= rainMask.y;
// 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);
// 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;
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;
// 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);
float distToDrop = (uProgress * 2 - delay) * speed - cogl_tex_coord_in[0].y;
// 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);
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);
}
void main() {
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);
}
-18
View File
@@ -1,18 +0,0 @@
// 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;
+77 -56
View File
@@ -1,71 +1,92 @@
// We simply inverse the progress for opening windows.
float progress = uForOpening ? uProgress : 1.0 - uProgress;
// 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"
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);
uniform sampler2D uDustTexture;
uniform vec4 uDustColor;
uniform vec2 uSeed;
uniform float uDustScale;
// This may help you to understand how this effect works.
// cogl_color_out = vec4(progress, 0, 0, 0);
// return;
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;
cogl_color_out = vec4(0, 0, 0, 0);
void main() {
// We simply inverse the progress for opening windows.
float progress = uForOpening ? uProgress : 1.0 - uProgress;
for (float i = 0; i < DUST_LAYERS; ++i) {
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);
// 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);
// This may help you to understand how this effect works.
// cogl_color_out = vec4(progress, 0, 0, 0);
// return;
// 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;
}
cogl_color_out = vec4(0, 0, 0, 0);
// Flip direction for half the layers.
if (factor > 0.5) {
direction *= -1;
}
for (float i = 0; i < DUST_LAYERS; ++i) {
// 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;
// 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);
// 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;
// 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;
}
// Fade the window color to uDustColor.
vec3 dustColor = mix(windowColor.rgb, uDustColor.rgb, uDustColor.a);
windowColor.rgb = mix(windowColor.rgb, dustColor, progress);
// Flip direction for half the layers.
if (factor > 0.5) {
direction *= -1;
}
// Dissolve and blend the layers.
if (dustMap.x - progress > 0) {
cogl_color_out = windowColor;
// 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;
}
}
}
}
-58
View File
@@ -1,58 +0,0 @@
// 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"
#include "common/easing.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));
}
+104 -43
View File
@@ -1,55 +1,116 @@
float progress = uForOpening ? 1.0 - easeOutQuad(uProgress) : easeOutQuad(uProgress);
// 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"
#include "common/easing.glsl"
// 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);
// 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;
// Scale down the window according to the warp.
float scale = 0.5 * uWarpIntensity * (1.0 - progress);
coords = coords * (scale + 1.0) - scale * 0.5;
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.
// 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));
// 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));
}
// 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);
void main() {
float progress = uForOpening ? 1.0 - easeOutQuad(uProgress) : easeOutQuad(uProgress);
// 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;
}
// 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);
// Add colorful flashes.
float flashIntensity = 1.0 / FLASH_INTENSITY * (scratchMap - progress) + 1;
if (flashIntensity < 0 || flashIntensity >= 1) {
flashIntensity = 0;
}
// Scale down the window according to the warp.
float scale = 0.5 * uWarpIntensity * (1.0 - progress);
coords = coords * (scale + 1.0) - scale * 0.5;
// Hide flashes where there is now window.
vec4 flash = uFlashColor;
flash.a *= flashIntensity * cogl_color_out.a * (1.0 - 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));
}
// Hide scratched out parts.
cogl_color_out.a *= (scratchMap > progress ? 1 : 0);
// 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);
// Add flash color.
cogl_color_out = alphaOver(cogl_color_out, flash);
// 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 out the remaining shards.
float fadeProgress = smoothstep(0, 1, (progress - 1.0 + FF_TIME) / FF_TIME);
cogl_color_out.a *= sqrt(1 - fadeProgress * fadeProgress);
// Add colorful flashes.
float flashIntensity = 1.0 / FLASH_INTENSITY * (scratchMap - progress) + 1;
if (flashIntensity < 0 || flashIntensity >= 1) {
flashIntensity = 0;
}
// These are pretty useful for understanding how this works.
// cogl_color_out = vec4(vec3(flashIntensity), 1);
// cogl_color_out = vec4(vec3(scratchMap), 1);
// 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);
}
-14
View File
@@ -1,14 +0,0 @@
// 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/easing.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.
const float SCALING = 0.5; // Additional vertical scaling of the window.
+54 -37
View File
@@ -1,47 +1,64 @@
float progress = uForOpening ? 1.0 - easeOutQuad(uProgress) : easeOutQuad(uProgress);
// 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/easing.glsl"
// Scale down the window vertically.
float scale = 1.0 / mix(1.0, SCALING, progress) - 1.0;
vec2 coords = cogl_tex_coord_in[0].st;
coords.y = coords.y * (scale + 1.0) - scale * 0.5;
uniform vec3 uColor;
// 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));
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 float SCALING = 0.5; // Additional vertical scaling of the window.
// This is a top-center-bottom gradient in [0..1..0]
float tb = coords.y * 2;
tb = tb < 1 ? tb : 2 - tb;
void main() {
float progress = uForOpening ? 1.0 - easeOutQuad(uProgress) : easeOutQuad(uProgress);
// This is a left-center-right gradient in [0..1..0]
float lr = coords.x * 2;
lr = lr < 1 ? lr : 2 - lr;
// Scale down the window vertically.
float scale = 1.0 / mix(1.0, SCALING, progress) - 1.0;
vec2 coords = cogl_tex_coord_in[0].st;
coords.y = coords.y * (scale + 1.0) - scale * 0.5;
// 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);
// 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));
// Assemble the final alpha value.
float mask = tbMask * lrMask * ffMask;
// This is a top-center-bottom gradient in [0..1..0]
float tb = coords.y * 2;
tb = tb < 1 ? tb : 2 - tb;
cogl_color_out = texture2D(uTexture, coords);
// This is a left-center-right gradient in [0..1..0]
float lr = coords.x * 2;
lr = lr < 1 ? lr : 2 - lr;
// 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;
}
// 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);
cogl_color_out.rgb =
mix(cogl_color_out.rgb, uColor* cogl_color_out.a, smoothstep(0, 1, progress));
cogl_color_out.a *= mask;
// Assemble the final alpha value.
float mask = tbMask * lrMask * ffMask;
// 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);
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;
}
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);
}
-58
View File
@@ -1,58 +0,0 @@
// 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"
#include "common/easing.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;
const float SCALING = 0.9;
// 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;
}
+97 -36
View File
@@ -1,46 +1,107 @@
float progress = uForOpening ? 1.0 - easeOutQuad(uProgress) : easeOutQuad(uProgress);
// 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"
#include "common/easing.glsl"
// Scale down the window slightly.
float scale = 1.0 / mix(1.0, SCALING, progress) - 1.0;
vec2 coords = cogl_tex_coord_in[0].st * (scale + 1.0) - scale * 0.5;
uniform vec2 uSeed;
uniform vec3 uColor;
uniform float uScale;
// Get the color of the window.
cogl_color_out = texture2D(uTexture, coords);
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;
const float SCALING = 0.9;
// 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;
// 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;
}
// 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));
}
void main() {
float progress = uForOpening ? 1.0 - easeOutQuad(uProgress) : easeOutQuad(uProgress);
// Compute shrinking edge mask.
float mask = getRelativeEdgeMask(mix(0.01, 0.5, progress));
// Scale down the window slightly.
float scale = 1.0 / mix(1.0, SCALING, progress) - 1.0;
vec2 coords = cogl_tex_coord_in[0].st * (scale + 1.0) - scale * 0.5;
// 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));
// Get the color of the window.
cogl_color_out = texture2D(uTexture, coords);
// 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;
// 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 the wisps.
vec4 wispColor = wisps * vec4(uColor, min(wispsIn, 1.0 - wispsOut) * mask);
cogl_color_out = alphaOver(cogl_color_out, wispColor);
// 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));
}
// 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);
// 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);
}
+8 -3
View File
@@ -164,11 +164,16 @@ if (utils.isInShellProcess()) {
// This is called by the constructor. This means, it's only called when the effect
// is used for the first time.
vfunc_build_pipeline() {
const decl =
utils.loadGLSLResource(`/shaders/${Apparition.getNick()}-declarations.glsl`);
const code = utils.loadGLSLResource(`/shaders/${Apparition.getNick()}.glsl`);
this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT, decl, code, true);
// Match anything between the curly brackets of "void main() {...}".
const regex = RegExp('void main *\\(\\) *\\{([\\S\\s]+)\\}', 'd');
const match = regex.exec(code);
const declarations = code.substr(0, match.index);
const main = match[1];
this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT, declarations, main, true);
}
});
}
+8 -3
View File
@@ -201,11 +201,16 @@ if (utils.isInShellProcess()) {
// This is called by the constructor. This means, it's only called when the effect
// is used for the first time.
vfunc_build_pipeline() {
const decl =
utils.loadGLSLResource(`/shaders/${BrokenGlass.getNick()}-declarations.glsl`);
const code = utils.loadGLSLResource(`/shaders/${BrokenGlass.getNick()}.glsl`);
this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT, decl, code, true);
// Match anything between the curly brackets of "void main() {...}".
const regex = RegExp('void main *\\(\\) *\\{([\\S\\s]+)\\}', 'd');
const match = regex.exec(code);
const declarations = code.substr(0, match.index);
const main = match[1];
this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT, declarations, main, true);
}
// This is overridden to bind the shard texture for drawing. Sadly, this seems to be
+8 -3
View File
@@ -152,11 +152,16 @@ if (utils.isInShellProcess()) {
// This is called by the constructor. This means, it's only called when the effect
// is used for the first time.
vfunc_build_pipeline() {
const decl =
utils.loadGLSLResource(`/shaders/${EnergizeA.getNick()}-declarations.glsl`);
const code = utils.loadGLSLResource(`/shaders/${EnergizeA.getNick()}.glsl`);
this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT, decl, code, true);
// Match anything between the curly brackets of "void main() {...}".
const regex = RegExp('void main *\\(\\) *\\{([\\S\\s]+)\\}', 'd');
const match = regex.exec(code);
const declarations = code.substr(0, match.index);
const main = match[1];
this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT, declarations, main, true);
}
});
}
+8 -3
View File
@@ -152,11 +152,16 @@ if (utils.isInShellProcess()) {
// This is called by the constructor. This means, it's only called when the effect
// is used for the first time.
vfunc_build_pipeline() {
const decl =
utils.loadGLSLResource(`/shaders/${EnergizeB.getNick()}-declarations.glsl`);
const code = utils.loadGLSLResource(`/shaders/${EnergizeB.getNick()}.glsl`);
this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT, decl, code, true);
// Match anything between the curly brackets of "void main() {...}".
const regex = RegExp('void main *\\(\\) *\\{([\\S\\s]+)\\}', 'd');
const match = regex.exec(code);
const declarations = code.substr(0, match.index);
const main = match[1];
this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT, declarations, main, true);
}
});
}
+8 -2
View File
@@ -279,10 +279,16 @@ if (utils.isInShellProcess()) {
// This is called by the constructor. This means, it's only called when the effect
// is used for the first time.
vfunc_build_pipeline() {
const decl = utils.loadGLSLResource(`/shaders/${Fire.getNick()}-declarations.glsl`);
const code = utils.loadGLSLResource(`/shaders/${Fire.getNick()}.glsl`);
this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT, decl, code, true);
// Match anything between the curly brackets of "void main() {...}".
const regex = RegExp('void main *\\(\\) *\\{([\\S\\s]+)\\}', 'd');
const match = regex.exec(code);
const declarations = code.substr(0, match.index);
const main = match[1];
this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT, declarations, main, true);
}
});
}
+8 -3
View File
@@ -171,11 +171,16 @@ if (utils.isInShellProcess()) {
// This is called by the constructor. This means, it's only called when the effect
// is used for the first time.
vfunc_build_pipeline() {
const decl =
utils.loadGLSLResource(`/shaders/${Hexagon.getNick()}-declarations.glsl`);
const code = utils.loadGLSLResource(`/shaders/${Hexagon.getNick()}.glsl`);
this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT, decl, code, true);
// Match anything between the curly brackets of "void main() {...}".
const regex = RegExp('void main *\\(\\) *\\{([\\S\\s]+)\\}', 'd');
const match = regex.exec(code);
const declarations = code.substr(0, match.index);
const main = match[1];
this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT, declarations, main, true);
}
});
}
+8 -3
View File
@@ -183,11 +183,16 @@ if (utils.isInShellProcess()) {
// 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.
vfunc_build_pipeline() {
const decl =
utils.loadGLSLResource(`/shaders/${Matrix.getNick()}-declarations.glsl`);
const code = utils.loadGLSLResource(`/shaders/${Matrix.getNick()}.glsl`);
this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT, decl, code, true);
// Match anything between the curly brackets of "void main() {...}".
const regex = RegExp('void main *\\(\\) *\\{([\\S\\s]+)\\}', 'd');
const match = regex.exec(code);
const declarations = code.substr(0, match.index);
const main = match[1];
this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT, declarations, main, true);
}
// This is overridden to bind the font texture for drawing. Sadly, this seems to be
+8 -3
View File
@@ -177,12 +177,17 @@ if (utils.isInShellProcess()) {
// This is called by the constructor. This means, it's only called when the effect
// is used for the first time.
vfunc_build_pipeline() {
const decl = utils.loadGLSLResource(
`/shaders/${SnapOfDisintegration.getNick()}-declarations.glsl`);
const code =
utils.loadGLSLResource(`/shaders/${SnapOfDisintegration.getNick()}.glsl`);
this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT, decl, code, true);
// Match anything between the curly brackets of "void main() {...}".
const regex = RegExp('void main *\\(\\) *\\{([\\S\\s]+)\\}', 'd');
const match = regex.exec(code);
const declarations = code.substr(0, match.index);
const main = match[1];
this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT, declarations, main, true);
}
// This is overridden to bind the dust texture for drawing. Sadly, this seems to be
+8 -3
View File
@@ -179,11 +179,16 @@ if (utils.isInShellProcess()) {
// This is called by the constructor. This means, it's only called when the effect
// is used for the first time.
vfunc_build_pipeline() {
const decl =
utils.loadGLSLResource(`/shaders/${TRexAttack.getNick()}-declarations.glsl`);
const code = utils.loadGLSLResource(`/shaders/${TRexAttack.getNick()}.glsl`);
this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT, decl, code, true);
// Match anything between the curly brackets of "void main() {...}".
const regex = RegExp('void main *\\(\\) *\\{([\\S\\s]+)\\}', 'd');
const match = regex.exec(code);
const declarations = code.substr(0, match.index);
const main = match[1];
this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT, declarations, main, true);
}
// This is overridden to bind the claw texture for drawing. Sadly, this seems to be
+8 -3
View File
@@ -148,11 +148,16 @@ if (utils.isInShellProcess()) {
// This is called by the constructor. This means, it's only called when the effect
// is used for the first time.
vfunc_build_pipeline() {
const decl =
utils.loadGLSLResource(`/shaders/${TVEffect.getNick()}-declarations.glsl`);
const code = utils.loadGLSLResource(`/shaders/${TVEffect.getNick()}.glsl`);
this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT, decl, code, true);
// Match anything between the curly brackets of "void main() {...}".
const regex = RegExp('void main *\\(\\) *\\{([\\S\\s]+)\\}', 'd');
const match = regex.exec(code);
const declarations = code.substr(0, match.index);
const main = match[1];
this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT, declarations, main, true);
}
});
}
+8 -3
View File
@@ -158,11 +158,16 @@ if (utils.isInShellProcess()) {
// This is called by the constructor. This means, it's only called when the effect
// is used for the first time.
vfunc_build_pipeline() {
const decl =
utils.loadGLSLResource(`/shaders/${Wisps.getNick()}-declarations.glsl`);
const code = utils.loadGLSLResource(`/shaders/${Wisps.getNick()}.glsl`);
this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT, decl, code, true);
// Match anything between the curly brackets of "void main() {...}".
const regex = RegExp('void main *\\(\\) *\\{([\\S\\s]+)\\}', 'd');
const match = regex.exec(code);
const declarations = code.substr(0, match.index);
const main = match[1];
this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT, declarations, main, true);
}
});
}
+3 -1
View File
@@ -106,7 +106,9 @@ function loadGLSLResource(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) => {
const regex = RegExp('#include ["<](?<file>.+)[">]', 'g');
code = code.replaceAll(regex, (m, p1, p2, str, groups) => {
return loadStringResource('/shaders/' + groups.file);
});