♻️ 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.BrokenGlass.BrokenGlass,
|
||||||
// Me.imports.src.EnergizeA.EnergizeA,
|
// Me.imports.src.EnergizeA.EnergizeA,
|
||||||
// Me.imports.src.EnergizeB.EnergizeB,
|
// Me.imports.src.EnergizeB.EnergizeB,
|
||||||
Me.imports.src.Fire.Fire,
|
Me.imports.src.Fire.Fire, Me.imports.src.Hexagon.Hexagon,
|
||||||
// Me.imports.src.Hexagon.Hexagon,
|
|
||||||
// Me.imports.src.Matrix.Matrix,
|
// Me.imports.src.Matrix.Matrix,
|
||||||
// Me.imports.src.SnapOfDisintegration.SnapOfDisintegration,
|
// Me.imports.src.SnapOfDisintegration.SnapOfDisintegration,
|
||||||
// Me.imports.src.TRexAttack.TRexAttack,
|
// Me.imports.src.TRexAttack.TRexAttack,
|
||||||
|
|||||||
@@ -36,8 +36,7 @@ const ALL_EFFECTS = [
|
|||||||
// Me.imports.src.BrokenGlass.BrokenGlass,
|
// Me.imports.src.BrokenGlass.BrokenGlass,
|
||||||
// Me.imports.src.EnergizeA.EnergizeA,
|
// Me.imports.src.EnergizeA.EnergizeA,
|
||||||
// Me.imports.src.EnergizeB.EnergizeB,
|
// Me.imports.src.EnergizeB.EnergizeB,
|
||||||
Me.imports.src.Fire.Fire,
|
Me.imports.src.Fire.Fire, Me.imports.src.Hexagon.Hexagon,
|
||||||
// Me.imports.src.Hexagon.Hexagon,
|
|
||||||
// Me.imports.src.Matrix.Matrix,
|
// Me.imports.src.Matrix.Matrix,
|
||||||
// Me.imports.src.SnapOfDisintegration.SnapOfDisintegration,
|
// Me.imports.src.SnapOfDisintegration.SnapOfDisintegration,
|
||||||
// Me.imports.src.TRexAttack.TRexAttack,
|
// 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. //
|
// gradually shrink until the window is fully dissolved. //
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// The shader class for this effect is registered further down in this file.
|
// The shader class for this effect is registered further down in this file. When this
|
||||||
let Shader = null;
|
// 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
|
// 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
|
// 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
|
// ---------------------------------------------------------------- API for extension.js
|
||||||
|
|
||||||
// This is called from extension.js whenever a window is closed with this effect.
|
// This is called from extension.js whenever a window is opened or closed with this
|
||||||
static createShader(actor, settings, forOpening) {
|
// effect.
|
||||||
return new Shader(settings, forOpening);
|
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
|
// 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}
|
'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()) {
|
if (utils.isInShellProcess()) {
|
||||||
|
|
||||||
const Clutter = imports.gi.Clutter;
|
const {Clutter, Shell} = imports.gi;
|
||||||
const shaderSnippets = Me.imports.src.shaderSnippets;
|
const shaderSnippets = Me.imports.src.shaderSnippets;
|
||||||
|
|
||||||
Shader = GObject.registerClass({}, class Shader extends Clutter.ShaderEffect {
|
ShaderClass = GObject.registerClass({}, class ShaderClass extends Shell.GLSLEffect {
|
||||||
_init(settings, forOpening) {
|
// This is called when the effect is used for the first time. This can be used to
|
||||||
super._init({shader_type: Clutter.ShaderType.FRAGMENT_SHADER});
|
// 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
|
// Get the two configurable colors. They are directly injected into the shader code
|
||||||
// below.
|
// below.
|
||||||
const glowColor =
|
const glow =
|
||||||
Clutter.Color.from_string(settings.get_string('hexagon-glow-color'))[1];
|
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];
|
Clutter.Color.from_string(settings.get_string('hexagon-line-color'))[1];
|
||||||
|
|
||||||
// If we are currently performing integration test, the animation uses a fixed seed.
|
// If we are currently performing integration test, the animation uses a fixed seed.
|
||||||
const testMode = settings.get_boolean('test-mode');
|
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.
|
// 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.
|
// Inject some common shader snippets.
|
||||||
${shaderSnippets.standardUniforms()}
|
${shaderSnippets.standardUniforms()}
|
||||||
${shaderSnippets.noise()}
|
${shaderSnippets.noise()}
|
||||||
|
|
||||||
const vec2 SEED = vec2(${testMode ? 0 : Math.random()},
|
uniform bool uForOpening;
|
||||||
${testMode ? 0 : Math.random()});
|
uniform bool uAdditiveBlending;
|
||||||
const float SCALE = 10.0 * ${settings.get_double('hexagon-scale')};
|
uniform vec2 uSeed;
|
||||||
const float LINE_WIDTH = 0.02 * ${settings.get_double('hexagon-line-width')};
|
uniform float uScale;
|
||||||
|
uniform float uLineWidth;
|
||||||
|
uniform vec4 uGlowColor;
|
||||||
|
uniform vec4 uLineColor;
|
||||||
|
|
||||||
// This methods generates a procedural hexagonal pattern. It returns four values:
|
// This methods generates a procedural hexagonal pattern. It returns four values:
|
||||||
// result.xy: This contains cell-relative coordinates for the given point.
|
// result.xy: This contains cell-relative coordinates for the given point.
|
||||||
@@ -182,69 +236,68 @@ if (utils.isInShellProcess()) {
|
|||||||
|
|
||||||
return vec4(cellCoords, dist, glow);
|
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.
|
// Add some smooth noise to the progress so that not every tile behaves the
|
||||||
float progress = ${forOpening ? '1.0-uProgress' : 'uProgress'};
|
// 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
|
// glowProgress fades in in the first half of the animation, tileProgress fades
|
||||||
// same.
|
// in in the second half.
|
||||||
float noise = simplex2D(cogl_tex_coord_in[0].st + SEED);
|
float glowProgress = smoothstep(0, 1, clamp(progress / 0.5, 0, 1));
|
||||||
progress = clamp(mix(noise - 1.0, noise + 1.0, progress), 0.0, 1.0);
|
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
|
vec2 texScale = 0.1 * vec2(uSizeX, uSizeY) / uScale;
|
||||||
// in in the second half.
|
vec4 hex = getHexagons(cogl_tex_coord_in[0].st * texScale);
|
||||||
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 = vec2(uSizeX, uSizeY) / SCALE;
|
if (tileProgress > hex.z) {
|
||||||
vec4 hex = getHexagons(cogl_tex_coord_in[0].st * texScale);
|
|
||||||
|
|
||||||
if (tileProgress > hex.z) {
|
// Crop outer parts of the shrinking tiles.
|
||||||
|
cogl_color_out *= vec4(0.0);
|
||||||
|
|
||||||
// Crop outer parts of the shrinking tiles.
|
} else {
|
||||||
cogl_color_out *= vec4(0.0);
|
|
||||||
|
|
||||||
|
// 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 {
|
} else {
|
||||||
|
cogl_color_out.rgb = mix(cogl_color_out.rgb, glow.rgb, glow.a);
|
||||||
// Make the tiles shrink by offsetting the texture lookup towards the edge
|
cogl_color_out.rgb = mix(cogl_color_out.rgb, line.rgb, line.a);
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`);
|
`;
|
||||||
|
|
||||||
|
this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT, declarations, code, true);
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user