♻️ Make it possible to reuse the hexagon shader
This commit is contained in:
+1
-2
@@ -37,8 +37,7 @@ const ALL_EFFECTS = [
|
||||
// Me.imports.src.BrokenGlass.BrokenGlass,
|
||||
// Me.imports.src.EnergizeA.EnergizeA,
|
||||
// Me.imports.src.EnergizeB.EnergizeB,
|
||||
Me.imports.src.Fire.Fire,
|
||||
// Me.imports.src.Hexagon.Hexagon,
|
||||
Me.imports.src.Fire.Fire, Me.imports.src.Hexagon.Hexagon,
|
||||
// Me.imports.src.Matrix.Matrix,
|
||||
// Me.imports.src.SnapOfDisintegration.SnapOfDisintegration,
|
||||
// Me.imports.src.TRexAttack.TRexAttack,
|
||||
|
||||
@@ -36,8 +36,7 @@ const ALL_EFFECTS = [
|
||||
// Me.imports.src.BrokenGlass.BrokenGlass,
|
||||
// Me.imports.src.EnergizeA.EnergizeA,
|
||||
// Me.imports.src.EnergizeB.EnergizeB,
|
||||
Me.imports.src.Fire.Fire,
|
||||
// Me.imports.src.Hexagon.Hexagon,
|
||||
Me.imports.src.Fire.Fire, Me.imports.src.Hexagon.Hexagon,
|
||||
// Me.imports.src.Matrix.Matrix,
|
||||
// Me.imports.src.SnapOfDisintegration.SnapOfDisintegration,
|
||||
// Me.imports.src.TRexAttack.TRexAttack,
|
||||
|
||||
+122
-69
@@ -26,8 +26,11 @@ const utils = Me.imports.src.utils;
|
||||
// gradually shrink until the window is fully dissolved. //
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// The shader class for this effect is registered further down in this file.
|
||||
let Shader = null;
|
||||
// The shader class for this effect is registered further down in this file. When this
|
||||
// effect is used for the first time, shaderInstance will store one instance of
|
||||
// ShaderClass which will be used whenever this effect is used.
|
||||
let ShaderClass = null;
|
||||
let shaderInstance = null;
|
||||
|
||||
// The effect class is completely static. It can be used to get some metadata (like the
|
||||
// effect's name or supported GNOME Shell versions), to initialize the respective page of
|
||||
@@ -79,9 +82,16 @@ var Hexagon = class Hexagon {
|
||||
|
||||
// ---------------------------------------------------------------- API for extension.js
|
||||
|
||||
// This is called from extension.js whenever a window is closed with this effect.
|
||||
static createShader(actor, settings, forOpening) {
|
||||
return new Shader(settings, forOpening);
|
||||
// This is called from extension.js whenever a window is opened or closed with this
|
||||
// effect.
|
||||
static getShader(actor, settings, forOpening) {
|
||||
if (shaderInstance == null) {
|
||||
shaderInstance = new ShaderClass();
|
||||
}
|
||||
|
||||
shaderInstance.setUniforms(settings, forOpening);
|
||||
|
||||
return shaderInstance;
|
||||
}
|
||||
|
||||
// The tweakTransition() is called from extension.js to tweak a window's open / close
|
||||
@@ -101,6 +111,12 @@ var Hexagon = class Hexagon {
|
||||
'scale-y': {from: 1.0, to: 1.0, mode: 1}
|
||||
};
|
||||
}
|
||||
|
||||
// This is called from extension.js if the extension is disabled. This should free all
|
||||
// static resources.
|
||||
static cleanUp() {
|
||||
shaderInstance = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -112,34 +128,72 @@ var Hexagon = class Hexagon {
|
||||
|
||||
if (utils.isInShellProcess()) {
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const shaderSnippets = Me.imports.src.shaderSnippets;
|
||||
const {Clutter, Shell} = imports.gi;
|
||||
const shaderSnippets = Me.imports.src.shaderSnippets;
|
||||
|
||||
Shader = GObject.registerClass({}, class Shader extends Clutter.ShaderEffect {
|
||||
_init(settings, forOpening) {
|
||||
super._init({shader_type: Clutter.ShaderType.FRAGMENT_SHADER});
|
||||
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
|
||||
// store all required uniform locations.
|
||||
_init() {
|
||||
super._init();
|
||||
|
||||
this._uForOpening = this.get_uniform_location('uForOpening');
|
||||
this._uAdditiveBlending = this.get_uniform_location('uAdditiveBlending');
|
||||
this._uSeed = this.get_uniform_location('uSeed');
|
||||
this._uScale = this.get_uniform_location('uScale');
|
||||
this._uLineWidth = this.get_uniform_location('uLineWidth');
|
||||
this._uGlowColor = this.get_uniform_location('uGlowColor');
|
||||
this._uLineColor = this.get_uniform_location('uLineColor');
|
||||
}
|
||||
|
||||
// This is called each time the effect is used. This can be used to retrieve the
|
||||
// configuration from the settings and update all uniforms accordingly.
|
||||
setUniforms(settings, forOpening) {
|
||||
|
||||
// Get the two configurable colors. They are directly injected into the shader code
|
||||
// below.
|
||||
const glowColor =
|
||||
const glow =
|
||||
Clutter.Color.from_string(settings.get_string('hexagon-glow-color'))[1];
|
||||
const lineColor =
|
||||
const line =
|
||||
Clutter.Color.from_string(settings.get_string('hexagon-line-color'))[1];
|
||||
|
||||
// If we are currently performing integration test, the animation uses a fixed seed.
|
||||
const testMode = settings.get_boolean('test-mode');
|
||||
|
||||
this.set_uniform_float(this._uForOpening, 1, [forOpening]);
|
||||
this.set_uniform_float(this._uAdditiveBlending, 1,
|
||||
[settings.get_boolean('hexagon-additive-blending')]);
|
||||
this.set_uniform_float(
|
||||
this._uSeed, 2, [testMode ? 0 : Math.random(), testMode ? 0 : Math.random()]);
|
||||
this.set_uniform_float(this._uScale, 1, [settings.get_double('hexagon-scale')]);
|
||||
this.set_uniform_float(this._uLineWidth, 1,
|
||||
[settings.get_double('hexagon-line-width')]);
|
||||
this.set_uniform_float(
|
||||
this._uGlowColor, 4,
|
||||
[glow.red / 255, glow.green / 255, glow.blue / 255, glow.alpha / 255]);
|
||||
this.set_uniform_float(
|
||||
this._uLineColor, 4,
|
||||
[line.red / 255, line.green / 255, line.blue / 255, line.alpha / 255]);
|
||||
}
|
||||
|
||||
// This is called by the constructor. This is means it's only called when the effect
|
||||
// is used for the first time.
|
||||
vfunc_build_pipeline() {
|
||||
|
||||
// Feel free to read the inline comments below to learn how this shader works.
|
||||
this.set_shader_source(`
|
||||
const declarations = `
|
||||
|
||||
// Inject some common shader snippets.
|
||||
${shaderSnippets.standardUniforms()}
|
||||
${shaderSnippets.noise()}
|
||||
|
||||
const vec2 SEED = vec2(${testMode ? 0 : Math.random()},
|
||||
${testMode ? 0 : Math.random()});
|
||||
const float SCALE = 10.0 * ${settings.get_double('hexagon-scale')};
|
||||
const float LINE_WIDTH = 0.02 * ${settings.get_double('hexagon-line-width')};
|
||||
uniform bool uForOpening;
|
||||
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.
|
||||
@@ -182,69 +236,68 @@ if (utils.isInShellProcess()) {
|
||||
|
||||
return vec4(cellCoords, dist, glow);
|
||||
}
|
||||
`;
|
||||
|
||||
void main() {
|
||||
const code = `
|
||||
// We simply inverse the progress for opening windows.
|
||||
float progress = uForOpening ? 1.0-uProgress : uProgress;
|
||||
|
||||
// We simply inverse the progress for opening windows.
|
||||
float progress = ${forOpening ? '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);
|
||||
|
||||
// Add some smooth noise to the progress so that not every tile behaves the
|
||||
// same.
|
||||
float noise = simplex2D(cogl_tex_coord_in[0].st + SEED);
|
||||
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));
|
||||
|
||||
// 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 * vec2(uSizeX, uSizeY) / uScale;
|
||||
vec4 hex = getHexagons(cogl_tex_coord_in[0].st * texScale);
|
||||
|
||||
vec2 texScale = vec2(uSizeX, uSizeY) / SCALE;
|
||||
vec4 hex = getHexagons(cogl_tex_coord_in[0].st * texScale);
|
||||
if (tileProgress > hex.z) {
|
||||
|
||||
if (tileProgress > hex.z) {
|
||||
// Crop outer parts of the shrinking tiles.
|
||||
cogl_color_out *= vec4(0.0);
|
||||
|
||||
// Crop outer parts of the shrinking tiles.
|
||||
cogl_color_out *= vec4(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);
|
||||
|
||||
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 {
|
||||
|
||||
// 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);
|
||||
|
||||
vec4 glow = vec4(${glowColor.red / 255}, ${glowColor.green / 255},
|
||||
${glowColor.blue / 255}, ${glowColor.alpha / 255});
|
||||
vec4 line = vec4(${lineColor.red / 255}, ${lineColor.green / 255},
|
||||
${lineColor.blue / 255}, ${lineColor.alpha / 255});
|
||||
|
||||
// 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(LINE_WIDTH, hex.z) would be simpler, but the below creates some
|
||||
// fake antialiasing.
|
||||
line.a *= 1.0 - smoothstep(LINE_WIDTH*0.5, LINE_WIDTH, 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 (${settings.get_boolean('hexagon-additive-blending')}) {
|
||||
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);
|
||||
}
|
||||
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);
|
||||
};
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user