From 70ca3fef77ee8bdc6e3ac28589a6fa08c024cc69 Mon Sep 17 00:00:00 2001 From: AlexanderCurl Date: Sat, 18 Apr 2026 17:46:06 +0100 Subject: Replaced file structures for themes in the correct format --- .../blur-my-shell@aunetx/effects/color.glsl | 111 +++++++ .../blur-my-shell@aunetx/effects/color.js | 168 ++++++++++ .../blur-my-shell@aunetx/effects/corner.glsl | 93 ++++++ .../blur-my-shell@aunetx/effects/corner.js | 211 ++++++++++++ .../blur-my-shell@aunetx/effects/derivative.glsl | 71 ++++ .../blur-my-shell@aunetx/effects/derivative.js | 120 +++++++ .../blur-my-shell@aunetx/effects/downscale.glsl | 76 +++++ .../blur-my-shell@aunetx/effects/downscale.js | 140 ++++++++ .../blur-my-shell@aunetx/effects/effects.js | 362 +++++++++++++++++++++ .../effects/gaussian_blur.glsl | 70 ++++ .../blur-my-shell@aunetx/effects/gaussian_blur.js | 213 ++++++++++++ .../blur-my-shell@aunetx/effects/hsl_to_rgb.glsl | 14 + .../blur-my-shell@aunetx/effects/hsl_to_rgb.js | 31 ++ .../effects/monte_carlo_blur.glsl | 52 +++ .../effects/monte_carlo_blur.js | 207 ++++++++++++ .../effects/native_dynamic_gaussian_blur.js | 43 +++ .../effects/native_static_gaussian_blur.js | 43 +++ .../blur-my-shell@aunetx/effects/noise.glsl | 20 ++ .../blur-my-shell@aunetx/effects/noise.js | 76 +++++ .../blur-my-shell@aunetx/effects/pixelize.js | 88 +++++ .../blur-my-shell@aunetx/effects/rgb_to_hsl.glsl | 18 + .../blur-my-shell@aunetx/effects/rgb_to_hsl.js | 31 ++ .../blur-my-shell@aunetx/effects/upscale.glsl | 57 ++++ .../blur-my-shell@aunetx/effects/upscale.js | 120 +++++++ 24 files changed, 2435 insertions(+) create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/color.glsl create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/color.js create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/corner.glsl create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/corner.js create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/derivative.glsl create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/derivative.js create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/downscale.glsl create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/downscale.js create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/effects.js create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/gaussian_blur.glsl create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/gaussian_blur.js create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/hsl_to_rgb.glsl create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/hsl_to_rgb.js create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/monte_carlo_blur.glsl create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/monte_carlo_blur.js create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/native_dynamic_gaussian_blur.js create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/native_static_gaussian_blur.js create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/noise.glsl create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/noise.js create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/pixelize.js create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/rgb_to_hsl.glsl create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/rgb_to_hsl.js create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/upscale.glsl create mode 100644 raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/upscale.js (limited to 'raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects') diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/color.glsl b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/color.glsl new file mode 100644 index 0000000..5df6512 --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/color.glsl @@ -0,0 +1,111 @@ +uniform sampler2D tex; +uniform float red; +uniform float green; +uniform float blue; +uniform float blend; +uniform int mode; + +const int NORMAL = 0; +const int MULTIPLY = 1; +const int SCREEN = 2; +const int OVERLAY = 3; +const int DARKEN = 4; +const int LIGHTEN = 5; +const int PLUS_DARKER = 6; +const int PLUS_LIGHTER = 7; +const int COLOR_DODGE = 8; +const int COLOR_BURN = 9; +const int HARD_LIGHT = 10; +const int SOFT_LIGHT = 11; +const int DIFFERENCE = 12; +const int EXCLUSION = 13; +const int HUE = 14; +const int SATURATION = 15; +const int COLOR = 16; +const int LUMINOSITY = 17; + +vec3 rgb_to_hsl(vec3 c) { + vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0); + vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g)); + vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r)); + + float d = q.x - min(q.w, q.y); + float e = 1.0e-10; + return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x); +} + +vec3 hsl_to_rgb(vec3 c) { + vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); + vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www); + return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y); +} + +float soft_light_channel(float base, float _blend) { + if (_blend < 0.5) { + return base - (1.0 - 2.0 * _blend) * base * (1.0 - base); + } else { + float d = (base < 0.25) + ? ((16.0 * base - 12.0) * base + 4.0) * base + : sqrt(base); + return base + (2.0 * _blend - 1.0) * (d - base); + } +} + +vec3 get_blend(vec3 base, vec3 _blend) { + if (mode == MULTIPLY) return base * _blend; + if (mode == SCREEN) return 1 - (1 - base) * (1 - _blend); + if (mode == OVERLAY) { + vec3 result; + result.r = base.r < 0.5 ? (2.0 * base.r * _blend.r) : (1.0 - 2.0 * (1.0 - base.r) * (1.0 - _blend.r)); + result.g = base.g < 0.5 ? (2.0 * base.g * _blend.g) : (1.0 - 2.0 * (1.0 - base.g) * (1.0 - _blend.g)); + result.b = base.b < 0.5 ? (2.0 * base.b * _blend.b) : (1.0 - 2.0 * (1.0 - base.b) * (1.0 - _blend.b)); + return result; + } + if (mode == DARKEN) return min(base, _blend); + if (mode == LIGHTEN) return max(base, _blend); + if (mode == PLUS_DARKER) return base + _blend - 1; + if (mode == PLUS_LIGHTER) return base + _blend; + if (mode == COLOR_DODGE) return base / (1 - _blend); + if (mode == COLOR_BURN) return 1 - (1 - base) / _blend; + if (mode == HARD_LIGHT) { + vec3 result; + result.r = _blend.r < 0.5 ? (2.0 * base.r * _blend.r) : (1.0 - 2.0 * (1.0 - base.r) * (1.0 - _blend.r)); + result.g = _blend.g < 0.5 ? (2.0 * base.g * _blend.g) : (1.0 - 2.0 * (1.0 - base.g) * (1.0 - _blend.g)); + result.b = _blend.b < 0.5 ? (2.0 * base.b * _blend.b) : (1.0 - 2.0 * (1.0 - base.b) * (1.0 - _blend.b)); + return result; + } + if (mode == SOFT_LIGHT) { + return vec3(soft_light_channel(base.r, _blend.r), soft_light_channel(base.g, _blend.g), soft_light_channel(base.b, _blend.b)); + } + if (mode == DIFFERENCE) return abs(base - _blend); + if (mode == EXCLUSION) return 0.5 - 2 * (base - 0.5) * (_blend - 0.5); + if (mode == HUE) { + vec3 base_hsl = rgb_to_hsl(base); + vec3 blend_hsl = rgb_to_hsl(_blend); + return hsl_to_rgb(vec3(blend_hsl.x, base_hsl.y, base_hsl.z)); + } + if (mode == SATURATION) { + vec3 base_hsl = rgb_to_hsl(base); + vec3 blend_hsl = rgb_to_hsl(_blend); + return hsl_to_rgb(vec3(base_hsl.x, blend_hsl.y, base_hsl.z)); + } + if (mode == COLOR) { + vec3 base_hsl = rgb_to_hsl(base); + vec3 blend_hsl = rgb_to_hsl(_blend); + return hsl_to_rgb(vec3(blend_hsl.x, blend_hsl.y, base_hsl.z)); + } + if (mode == LUMINOSITY) { + vec3 base_hsl = rgb_to_hsl(base); + vec3 blend_hsl = rgb_to_hsl(_blend); + return hsl_to_rgb(vec3(base_hsl.x, base_hsl.y, blend_hsl.z)); + } + return _blend; // For NORMAL +} + +void main() { + vec4 c = texture2D(tex, cogl_tex_coord_in[0].st); + vec3 pix_color = c.xyz; + vec3 color = get_blend(pix_color, vec3(red, green, blue)); + + cogl_color_out = vec4(mix(pix_color, color, blend), 1.); +} \ No newline at end of file diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/color.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/color.js new file mode 100644 index 0000000..1f4bdf4 --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/color.js @@ -0,0 +1,168 @@ +import GObject from 'gi://GObject'; + +import * as utils from '../conveniences/utils.js'; + +const Shell = await utils.import_in_shell_only('gi://Shell'); +const Clutter = await utils.import_in_shell_only('gi://Clutter'); + +const SHADER_FILENAME = 'color.glsl'; +const DEFAULT_PARAMS = { + color: [0.0, 0.0, 0.0, 0.0], + blend_mode: 0 +}; + + +export const ColorEffect = utils.IS_IN_PREFERENCES ? + { default_params: DEFAULT_PARAMS } : + new GObject.registerClass({ + GTypeName: "ColorEffect", + Properties: { + 'red': GObject.ParamSpec.double( + `red`, + `Red`, + `Red value in shader`, + GObject.ParamFlags.READWRITE, + 0.0, 1.0, + 0.0, + ), + 'green': GObject.ParamSpec.double( + `green`, + `Green`, + `Green value in shader`, + GObject.ParamFlags.READWRITE, + 0.0, 1.0, + 0.0, + ), + 'blue': GObject.ParamSpec.double( + `blue`, + `Blue`, + `Blue value in shader`, + GObject.ParamFlags.READWRITE, + 0.0, 1.0, + 0.0, + ), + 'blend': GObject.ParamSpec.double( + `blend`, + `Blend`, + `Amount of blending between the colors`, + GObject.ParamFlags.READWRITE, + 0.0, 1.0, + 0.0, + ), + 'blend_mode': GObject.ParamSpec.int( + `blend_mode`, + `Blend mode`, + `Blend mode`, + GObject.ParamFlags.READWRITE, + 0, 17, + 0, + ) + } + // Normal (0), Multiply (1), Screen (2), Overlay (3), Darken (4), Lighten (5), Plus darker (6), Plus lighter (7), Color dodge (8), + // Color burn (9), Hard light (10), Soft light (11), Difference (12), Exclusion (13), Hue (14), Saturation (15), Color (16), + // Luminosity (17) + }, class ColorEffect extends Clutter.ShaderEffect { + constructor(params) { + // initialize without color as a parameter + const { color, ...parent_params } = params; + super(parent_params); + + this._red = null; + this._green = null; + this._blue = null; + this._blend = null; + this._blend_mode = null; + + // set shader source + this._source = utils.get_shader_source(Shell, SHADER_FILENAME, import.meta.url); + if (this._source) + this.set_shader_source(this._source); + + // set params; utils.setup_params doesn't work here with color + this.color = 'color' in params ? color : this.constructor.default_params.color; + this.blend_mode = 'blend_mode' in params ? params.blend_mode : this.constructor.default_params.blend_mode; + } + + static get default_params() { + return DEFAULT_PARAMS; + } + + get red() { + return this._red; + } + + set red(value) { + if (this._red !== value) { + this._red = value; + + this.set_uniform_value('red', parseFloat(this._red - 1e-6)); + } + } + + get green() { + return this._green; + } + + set green(value) { + if (this._green !== value) { + this._green = value; + + this.set_uniform_value('green', parseFloat(this._green - 1e-6)); + } + } + + get blue() { + return this._blue; + } + + set blue(value) { + if (this._blue !== value) { + this._blue = value; + + this.set_uniform_value('blue', parseFloat(this._blue - 1e-6)); + } + } + + get blend() { + return this._blend; + } + + set blend(value) { + if (this._blend !== value) { + this._blend = value; + + this.set_uniform_value('blend', parseFloat(this._blend - 1e-6)); + this.set_enabled(this.blend > 0); + } + } + + get blend_mode() { + return this._blend_mode; + } + + set blend_mode(value) { + if (this._blend_mode !== value) { + this._blend_mode = value; + + this.set_uniform_value('mode', this._blend_mode); + } + } + + set color(rgba) { + let [r, g, b, a] = rgba; + this.red = r; + this.green = g; + this.blue = b; + this.blend = a; + } + + get color() { + return [this.red, this.green, this.blue, this.blend]; + } + + /// False set function, only cares about the color. Too hard to change. + set(params) { + this.color = params.color; + this.blend_mode = params.blend_mode; + } + }); \ No newline at end of file diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/corner.glsl b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/corner.glsl new file mode 100644 index 0000000..760798a --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/corner.glsl @@ -0,0 +1,93 @@ +// Heavily based on https://github.com/yilozt/rounded-window-corners +// which is itself based on upstream Mutter code + +uniform sampler2D tex; +uniform float radius; +uniform float width; +uniform float height; +uniform bool corners_top; +uniform bool corners_bottom; + +uniform float clip_x0; +uniform float clip_y0; +uniform float clip_width; +uniform float clip_height; + +float circle_bounds(vec2 p, vec2 center, float clip_radius) { + vec2 delta = p - center; + float dist_squared = dot(delta, delta); + + float outer_radius = clip_radius + 0.5; + if (dist_squared >= (outer_radius * outer_radius)) + return 0.0; + + float inner_radius = clip_radius - 0.5; + if (dist_squared <= (inner_radius * inner_radius)) + return 1.0; + + return outer_radius - sqrt(dist_squared); +} + +vec4 getTexture(vec2 uv) { + if (uv.x < 2. / width) + uv.x = 2. / width; + + if (uv.y < 2. / height) + uv.y = 2. / height; + + if (uv.x > 1. - 3. / width) + uv.x = 1. - 3. / width; + + if (uv.y > 1. - 3. / height) + uv.y = 1. - 3. / height; + + return texture2D(tex, uv); +} + +float rounded_rect_coverage(vec2 p, vec4 bounds, float clip_radius) { + // Outside the bounds + if (p.x < bounds.x || p.x > bounds.z || p.y < bounds.y || p.y > bounds.w) { + return 0.; + } + + vec2 center; + + float center_left = bounds.x + clip_radius; + float center_right = bounds.z - clip_radius; + + if (p.x < center_left) + center.x = center_left + 2.; + else if (p.x > center_right) + center.x = center_right - 1.; + else + return 1.0; + + float center_top = bounds.y + clip_radius; + float center_bottom = bounds.w - clip_radius; + + if (corners_top && p.y < center_top) + center.y = center_top + 2.; + else if (corners_bottom && p.y > center_bottom) + center.y = center_bottom - 1.; + else + return 1.0; + + return circle_bounds(p, center, clip_radius); +} + +void main(void) { + vec2 uv = cogl_tex_coord_in[0].xy; + vec2 pos = uv * vec2(width, height); + vec4 c = getTexture(uv); + + vec4 bounds; + if (clip_width < 0. || clip_height < 0.) { + bounds = vec4(clip_x0, clip_y0, clip_x0 + width, clip_y0 + height); + } else { + bounds = vec4(clip_x0, clip_y0, clip_x0 + clip_width, clip_y0 + clip_height); + } + + float alpha = rounded_rect_coverage(pos, bounds, radius); + + cogl_color_out = vec4(c.rgb * alpha, min(alpha, c.a)); +} \ No newline at end of file diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/corner.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/corner.js new file mode 100644 index 0000000..109be12 --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/corner.js @@ -0,0 +1,211 @@ +import GObject from 'gi://GObject'; + +import * as utils from '../conveniences/utils.js'; +const St = await utils.import_in_shell_only('gi://St'); +const Shell = await utils.import_in_shell_only('gi://Shell'); +const Clutter = await utils.import_in_shell_only('gi://Clutter'); + +const SHADER_FILENAME = 'corner.glsl'; +const DEFAULT_PARAMS = { + radius: 12, width: 0, height: 0, + corners_top: true, corners_bottom: true, + clip: [0, 0, -1, -1] +}; + + +export const CornerEffect = utils.IS_IN_PREFERENCES ? + { default_params: DEFAULT_PARAMS } : + new GObject.registerClass({ + GTypeName: "CornerEffect", + Properties: { + 'radius': GObject.ParamSpec.double( + `radius`, + `Corner Radius`, + `Corner Radius`, + GObject.ParamFlags.READWRITE, + 0, Number.MAX_SAFE_INTEGER, + 12, + ), + 'width': GObject.ParamSpec.double( + `width`, + `Width`, + `Width`, + GObject.ParamFlags.READWRITE, + 0.0, Number.MAX_SAFE_INTEGER, + 0.0, + ), + 'height': GObject.ParamSpec.double( + `height`, + `Height`, + `Height`, + GObject.ParamFlags.READWRITE, + 0.0, Number.MAX_SAFE_INTEGER, + 0.0, + ), + 'corners_top': GObject.ParamSpec.boolean( + `corners_top`, + `Round top corners`, + `Round top corners`, + GObject.ParamFlags.READWRITE, + true, + ), + 'corners_bottom': GObject.ParamSpec.boolean( + `corners_bottom`, + `Round bottom corners`, + `Round bottom corners`, + GObject.ParamFlags.READWRITE, + true, + ), + // FIXME this works but it logs an error, because I'm not a double... + // I don't want to fiddle with GVariants again + 'clip': GObject.ParamSpec.double( + `clip`, + `Clip`, + `Clip`, + GObject.ParamFlags.READWRITE, + 0.0, Number.MAX_SAFE_INTEGER, + 0.0, + ), + } + }, class CornerEffect extends Clutter.ShaderEffect { + constructor(params) { + super(params); + + this._clip_x0 = null; + this._clip_y0 = null; + this._clip_width = null; + this._clip_height = null; + + utils.setup_params(this, params); + + // set shader source + this._source = utils.get_shader_source(Shell, SHADER_FILENAME, import.meta.url); + if (this._source) + this.set_shader_source(this._source); + + const theme_context = St.ThemeContext.get_for_stage(global.stage); + theme_context.connectObject('notify::scale-factor', _ => this.update_radius(), this); + } + + static get default_params() { + return DEFAULT_PARAMS; + } + + get radius() { + return this._radius; + } + + set radius(value) { + if (this._radius !== value) { + this._radius = value; + + this.update_radius(); + } + } + + update_radius() { + const theme_context = St.ThemeContext.get_for_stage(global.stage); + let radius = Math.min( + this.radius * theme_context.scale_factor, + this.width / 2, this.height / 2 + ); + if (this._clip_width >= 0 || this._clip_height >= 0) + radius = Math.min(radius, this._clip_width / 2, this._clip_height / 2); + + this.set_uniform_value('radius', parseFloat(radius - 1e-6)); + } + + get width() { + return this._width; + } + + set width(value) { + if (this._width !== value) { + this._width = value; + + this.set_uniform_value('width', parseFloat(this._width + 3.0 - 1e-6)); + this.update_radius(); + } + } + + get height() { + return this._height; + } + + set height(value) { + if (this._height !== value) { + this._height = value; + + this.set_uniform_value('height', parseFloat(this._height + 3.0 - 1e-6)); + this.update_radius(); + } + } + + get corners_top() { + return this._corners_top; + } + + set corners_top(value) { + if (this._corners_top !== value) { + this._corners_top = value; + + this.set_uniform_value('corners_top', this._corners_top ? 1 : 0); + } + } + + get corners_bottom() { + return this._corners_bottom; + } + + set corners_bottom(value) { + if (this._corners_bottom !== value) { + this._corners_bottom = value; + + this.set_uniform_value('corners_bottom', this._corners_bottom ? 1 : 0); + } + } + + get clip() { + return [this._clip_x0, this._clip_y0, this._clip_width, this._clip_height]; + } + + set clip(value) { + [this._clip_x0, this._clip_y0, this._clip_width, this._clip_height] = value; + this.set_uniform_value('clip_x0', parseFloat(this._clip_x0 - 1e-6)); + this.set_uniform_value('clip_y0', parseFloat(this._clip_y0 - 1e-6)); + this.set_uniform_value('clip_width', parseFloat(this._clip_width + 3 - 1e-6)); + this.set_uniform_value('clip_height', parseFloat(this._clip_height + 3 - 1e-6)); + this.update_radius(); + } + + vfunc_set_actor(actor) { + if (this._actor_connection_size_id) { + let old_actor = this.get_actor(); + old_actor?.disconnect(this._actor_connection_size_id); + } + if (this._actor_connection_clip_rect_id) { + let old_actor = this.get_actor(); + old_actor?.disconnect(this._actor_connection_clip_rect_id); + } + + if (actor) { + this.width = actor.width; + this.height = actor.height; + this._actor_connection_size_id = actor.connect('notify::size', _ => { + this.width = actor.width; + this.height = actor.height; + }); + + this.clip = actor.has_clip ? actor.get_clip() : [0, 0, -10, -10]; + this._actor_connection_clip_rect_id = actor.connect('notify::clip-rect', _ => { + this.clip = actor.has_clip ? actor.get_clip() : [0, 0, -10, -10]; + }); + } + else { + this._actor_connection_size_id = null; + this._actor_connection_clip_rect_id = null; + } + + super.vfunc_set_actor(actor); + } + }); \ No newline at end of file diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/derivative.glsl b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/derivative.glsl new file mode 100644 index 0000000..64c1682 --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/derivative.glsl @@ -0,0 +1,71 @@ +uniform sampler2D tex; +uniform int operation; +uniform float width; +uniform float height; + +#define CORRECTION 2.25 +#define SIZE_ADDITION 3 + +vec4 get_texture_at_position(vec2 position) { + vec2 raw_position = position + vec2(CORRECTION, CORRECTION); + vec2 raw_uv = raw_position / vec2(width + SIZE_ADDITION, height + SIZE_ADDITION); + + return texture2D(tex, raw_uv); +} + +vec4 try_get_texture_at_position(vec2 position, inout int count) { + if (any(greaterThanEqual(position, vec2(width, height))) || + any(lessThan(position, vec2(0, 0)))) { + return vec4(0); + } else { + count++; + return get_texture_at_position(position); + } +} + +ivec2 get_corrected_position() { + vec2 raw_uv = cogl_tex_coord0_in.st; + vec2 raw_position = raw_uv * vec2(width + SIZE_ADDITION, height + SIZE_ADDITION); + return ivec2(raw_position - vec2(CORRECTION, CORRECTION)); +} + +void main() { + ivec2 corrected_position = get_corrected_position(); + + // 1-step derivative + if (operation == 0) { + vec4 color = vec4(0); + int c = 0; + color += try_get_texture_at_position(corrected_position + vec2(0, 1), c); + color -= try_get_texture_at_position(corrected_position + vec2(0, 0), c); + color += try_get_texture_at_position(corrected_position + vec2(1, 0), c); + color -= try_get_texture_at_position(corrected_position + vec2(0, 0), c); + if (c < 4) { + color = vec4(0); + } + cogl_color_out = vec4(color.xyz, 1); + } else + // 2-step derivative + if (operation == 1) { + vec4 color = vec4(0); + int c = 0; + color += try_get_texture_at_position(corrected_position + vec2(0, 1), c); + color -= try_get_texture_at_position(corrected_position + vec2(0, -1), c); + color += try_get_texture_at_position(corrected_position + vec2(1, 0), c); + color -= try_get_texture_at_position(corrected_position + vec2(-1, 0), c); + if (c < 4) { + color = vec4(0); + } + cogl_color_out = vec4(color.xyz / 2, 1); + } else + // laplacian + if (operation == 2) { + vec4 color = vec4(0); + color = -4 * get_texture_at_position(corrected_position); + color += get_texture_at_position(corrected_position + vec2(0, 1)); + color += get_texture_at_position(corrected_position + vec2(0, -1)); + color += get_texture_at_position(corrected_position + vec2(1, 0)); + color += get_texture_at_position(corrected_position + vec2(-1, 0)); + cogl_color_out = vec4(color.xyz, 1); + } +} \ No newline at end of file diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/derivative.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/derivative.js new file mode 100644 index 0000000..04d6100 --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/derivative.js @@ -0,0 +1,120 @@ +import GObject from 'gi://GObject'; + +import * as utils from '../conveniences/utils.js'; +const Shell = await utils.import_in_shell_only('gi://Shell'); +const Clutter = await utils.import_in_shell_only('gi://Clutter'); + +const SHADER_FILENAME = 'derivative.glsl'; +const DEFAULT_PARAMS = { + operation: 0, width: 0, height: 0 +}; + + +export const DerivativeEffect = utils.IS_IN_PREFERENCES ? + { default_params: DEFAULT_PARAMS } : + new GObject.registerClass({ + GTypeName: "DerivativeEffect", + Properties: { + 'operation': GObject.ParamSpec.int( + `operation`, + `Operation`, + `Operation`, + GObject.ParamFlags.READWRITE, + 0, 2, + 0, + ), + 'width': GObject.ParamSpec.double( + `width`, + `Width`, + `Width`, + GObject.ParamFlags.READWRITE, + 0.0, Number.MAX_SAFE_INTEGER, + 0.0, + ), + 'height': GObject.ParamSpec.double( + `height`, + `Height`, + `Height`, + GObject.ParamFlags.READWRITE, + 0.0, Number.MAX_SAFE_INTEGER, + 0.0, + ) + } + }, class DerivativeEffect extends Clutter.ShaderEffect { + constructor(params) { + super(params); + + utils.setup_params(this, params); + + // set shader source + this._source = utils.get_shader_source(Shell, SHADER_FILENAME, import.meta.url); + if (this._source) + this.set_shader_source(this._source); + } + + static get default_params() { + return DEFAULT_PARAMS; + } + + get operation() { + return this._operation; + } + + set operation(value) { + if (this._operation !== value) { + this._operation = value; + + this.set_uniform_value('operation', this._operation); + } + } + + get width() { + return this._width; + } + + set width(value) { + if (this._width !== value) { + this._width = value; + + this.set_uniform_value('width', parseFloat(this._width - 1e-6)); + } + } + + get height() { + return this._height; + } + + set height(value) { + if (this._height !== value) { + this._height = value; + + this.set_uniform_value('height', parseFloat(this._height - 1e-6)); + } + } + + vfunc_set_actor(actor) { + if (this._actor_connection_size_id) { + let old_actor = this.get_actor(); + old_actor?.disconnect(this._actor_connection_size_id); + } + if (actor) { + this.width = actor.width; + this.height = actor.height; + this._actor_connection_size_id = actor.connect('notify::size', _ => { + this.width = actor.width; + this.height = actor.height; + }); + } + else + this._actor_connection_size_id = null; + + super.vfunc_set_actor(actor); + } + + vfunc_paint_target(paint_node, paint_context) { + // force setting nearest-neighbour texture filtering + this.get_pipeline().set_layer_filters(0, 9728, 9728); + + super.vfunc_paint_target(paint_node, paint_context); + } + }); \ No newline at end of file diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/downscale.glsl b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/downscale.glsl new file mode 100644 index 0000000..9871268 --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/downscale.glsl @@ -0,0 +1,76 @@ +uniform sampler2D tex; +uniform int divider; +uniform float width; +uniform float height; +uniform int downsampling_mode; + +#define CORRECTION 2.25 +#define SIZE_ADDITION 3 + +vec4 get_texture_at_position(vec2 position) { + vec2 raw_position = position + vec2(CORRECTION, CORRECTION); + vec2 raw_uv = raw_position / vec2(width + SIZE_ADDITION, height + SIZE_ADDITION); + + return texture2D(tex, raw_uv); +} + +vec2 get_corrected_position() { + vec2 raw_uv = cogl_tex_coord0_in.st; + vec2 raw_position = raw_uv * vec2(width + SIZE_ADDITION, height + SIZE_ADDITION); + return raw_position - vec2(CORRECTION, CORRECTION); +} + +void main() { + ivec2 corrected_position = ivec2(get_corrected_position()); + vec2 multiplied_position = corrected_position * divider; + + if (any(greaterThan(multiplied_position, vec2(width, height)))) { + discard; + } + + // mode 0: boxcar downsampling + if (downsampling_mode == 0) { + + vec4 color = vec4(0.); + int count = 0; + for (int i = 0; i < divider; i++) { + for (int j = 0; j < divider; j++) { + vec2 lookup_position = multiplied_position + vec2(i, j); + if (all(greaterThanEqual(lookup_position, vec2(0, 0))) && + all(lessThan(lookup_position, vec2(width, height)))) { + color += get_texture_at_position(lookup_position); + count += 1; + } + } + } + cogl_color_out = color / count; + + } else + // mode 1: triangular downsampling + if (downsampling_mode == 1) { + + vec4 color = vec4(0.); + int count = 0; + int force = 1; + for (int i = 0; i < divider; i++) { + for (int j = 0; j < divider; j++) { + vec2 lookup_position = multiplied_position + vec2(i, j); + if (all(greaterThanEqual(lookup_position, vec2(0, 0))) && + all(lessThan(lookup_position, vec2(width, height)))) { + force = 1 + divider - int(abs(divider - i - j)); + color += get_texture_at_position(lookup_position) * force; + count += force; + } + } + } + cogl_color_out = color / count; + + } else + // mode 2: Dirac downsampling + if (downsampling_mode == 2) { + + vec2 lookup_position = min(multiplied_position + vec2(divider, divider) / 2, vec2(width - 1, height - 1)); + cogl_color_out = get_texture_at_position(lookup_position); + + } +} \ No newline at end of file diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/downscale.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/downscale.js new file mode 100644 index 0000000..8103486 --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/downscale.js @@ -0,0 +1,140 @@ +import GObject from 'gi://GObject'; + +import * as utils from '../conveniences/utils.js'; +const Shell = await utils.import_in_shell_only('gi://Shell'); +const Clutter = await utils.import_in_shell_only('gi://Clutter'); + +const SHADER_FILENAME = 'downscale.glsl'; +const DEFAULT_PARAMS = { + divider: 8, downsampling_mode: 0, width: 0, height: 0 +}; + + +export const DownscaleEffect = utils.IS_IN_PREFERENCES ? + { default_params: DEFAULT_PARAMS } : + new GObject.registerClass({ + GTypeName: "DownscaleEffect", + Properties: { + 'divider': GObject.ParamSpec.int( + `divider`, + `Divider`, + `Divider`, + GObject.ParamFlags.READWRITE, + 0, 64, + 8, + ), + 'downsampling_mode': GObject.ParamSpec.int( + `downsampling_mode`, + `Downsampling mode`, + `Downsampling mode`, + GObject.ParamFlags.READWRITE, + 0, 2, + 0, + ), + 'width': GObject.ParamSpec.double( + `width`, + `Width`, + `Width`, + GObject.ParamFlags.READWRITE, + 0.0, Number.MAX_SAFE_INTEGER, + 0.0, + ), + 'height': GObject.ParamSpec.double( + `height`, + `Height`, + `Height`, + GObject.ParamFlags.READWRITE, + 0.0, Number.MAX_SAFE_INTEGER, + 0.0, + ) + } + }, class DownscaleEffect extends Clutter.ShaderEffect { + constructor(params) { + super(params); + + utils.setup_params(this, params); + + // set shader source + this._source = utils.get_shader_source(Shell, SHADER_FILENAME, import.meta.url); + if (this._source) + this.set_shader_source(this._source); + } + + static get default_params() { + return DEFAULT_PARAMS; + } + + get divider() { + return this._divider; + } + + set divider(value) { + if (this._divider !== value) { + this._divider = value; + + this.set_uniform_value('divider', this._divider); + } + } + + get downsampling_mode() { + return this._downsampling_mode; + } + + set downsampling_mode(value) { + if (this._downsampling_mode !== value) { + this._downsampling_mode = value; + + this.set_uniform_value('downsampling_mode', this._downsampling_mode); + } + } + + get width() { + return this._width; + } + + set width(value) { + if (this._width !== value) { + this._width = value; + + this.set_uniform_value('width', parseFloat(this._width - 1e-6)); + } + } + + get height() { + return this._height; + } + + set height(value) { + if (this._height !== value) { + this._height = value; + + this.set_uniform_value('height', parseFloat(this._height - 1e-6)); + } + } + + vfunc_set_actor(actor) { + if (this._actor_connection_size_id) { + let old_actor = this.get_actor(); + old_actor?.disconnect(this._actor_connection_size_id); + } + if (actor) { + this.width = actor.width; + this.height = actor.height; + this._actor_connection_size_id = actor.connect('notify::size', _ => { + this.width = actor.width; + this.height = actor.height; + }); + } + else + this._actor_connection_size_id = null; + + super.vfunc_set_actor(actor); + } + + vfunc_paint_target(paint_node, paint_context) { + // force setting nearest-neighbour texture filtering + this.get_pipeline().set_layer_filters(0, 9728, 9728); + + super.vfunc_paint_target(paint_node, paint_context); + } + }); \ No newline at end of file diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/effects.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/effects.js new file mode 100644 index 0000000..e35588d --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/effects.js @@ -0,0 +1,362 @@ +import { NativeDynamicBlurEffect } from '../effects/native_dynamic_gaussian_blur.js'; +import { NativeStaticBlurEffect } from '../effects/native_static_gaussian_blur.js'; +import { GaussianBlurEffect } from '../effects/gaussian_blur.js'; +import { MonteCarloBlurEffect } from '../effects/monte_carlo_blur.js'; +import { ColorEffect } from '../effects/color.js'; +import { NoiseEffect } from '../effects/noise.js'; +import { CornerEffect } from '../effects/corner.js'; +import { DownscaleEffect } from './downscale.js'; +import { UpscaleEffect } from './upscale.js'; +import { PixelizeEffect } from './pixelize.js'; +import { DerivativeEffect } from './derivative.js'; +import { RgbToHslEffect } from './rgb_to_hsl.js'; +import { HslToRgbEffect } from './hsl_to_rgb.js'; + +// We do in this way because I've not found another way to store our preferences in a dictionnary +// while calling `gettext` on it while in preferences. Not so pretty, but works. +export function get_effects_groups(_ = _ => "") { + return { + blur_effects: { + name: _("Blur effects"), + contains: [ + "native_static_gaussian_blur", + "gaussian_blur", + "monte_carlo_blur" + ] + }, + texture_effects: { + name: _("Texture effects"), + contains: [ + "downscale", + "upscale", + "pixelize", + "derivative", + "noise", + "color", + "rgb_to_hsl", + "hsl_to_rgb" + ] + }, + shape_effects: { + name: _("Shape effects"), + contains: [ + "corner" + ] + } + }; +}; + +export function get_supported_effects(_ = () => "") { + return { + native_dynamic_gaussian_blur: { + class: NativeDynamicBlurEffect + }, + + native_static_gaussian_blur: { + class: NativeStaticBlurEffect, + name: _("Native gaussian blur"), + description: _("An optimized blur effect that smoothly blends pixels within a given radius."), + is_advanced: false, + editable_params: { + unscaled_radius: { + name: _("Radius"), + description: _("The intensity of the blur effect."), + type: "float", + min: 0., + max: 100., + increment: 1.0, + big_increment: 10., + digits: 0 + }, + brightness: { + name: _("Brightness"), + description: _("The brightness of the blur effect, a high value might make the text harder to read."), + type: "float", + min: 0., + max: 1., + increment: 0.01, + big_increment: 0.1, + digits: 2 + }, + } + }, + + gaussian_blur: { + class: GaussianBlurEffect, + name: _("Gaussian blur (advanced effect)"), + description: _("A blur effect that smoothly blends pixels within a given radius. This effect is more precise, but way less optimized."), + is_advanced: true, + editable_params: { + radius: { + name: _("Radius"), + description: _("The intensity of the blur effect. The bigger it is, the slower it will be."), + type: "float", + min: 0., + max: 100., + increment: .1, + big_increment: 10., + digits: 1 + }, + brightness: { + name: _("Brightness"), + description: _("The brightness of the blur effect, a high value might make the text harder to read."), + type: "float", + min: 0., + max: 1., + increment: 0.01, + big_increment: 0.1, + digits: 2 + }, + } + }, + + monte_carlo_blur: { + class: MonteCarloBlurEffect, + name: _("Monte Carlo blur"), + description: _("A blur effect that mimics a random walk, by picking pixels further and further away from its origin and mixing them all together."), + is_advanced: false, + editable_params: { + radius: { + name: _("Radius"), + description: _("The maximum travel distance for each step in the random walk. A higher value will make the blur more randomized."), + type: "float", + min: 0., + max: 10., + increment: 0.01, + big_increment: 0.1, + digits: 2 + }, + iterations: { + name: _("Iterations"), + description: _("The number of iterations. The more there are, the smoother the blur is."), + type: "integer", + min: 0, + max: 50, + increment: 1 + }, + brightness: { + name: _("Brightness"), + description: _("The brightness of the blur effect, a high value might make the text harder to read."), + type: "float", + min: 0., + max: 1., + increment: 0.01, + big_increment: 0.1, + digits: 2 + }, + use_base_pixel: { + name: _("Use base pixel"), + description: _("Whether or not the original pixel is counted for the blur. If it is, the image will be more legible."), + type: "boolean" + }, + prefer_closer_pixels: { + name: _("Prefer closer pixels"), + description: _("Whether or not the pixels that are closer to the original pixel will have more weight."), + type: "boolean" + } + } + }, + + color: { + class: ColorEffect, + name: _("Color"), + description: _("An effect that blends a color into the pipeline."), + is_advanced: false, + // TODO make this RGB + blend + editable_params: { + color: { + name: _("Color"), + description: _("The color to blend in. The blending amount is controled by the opacity of the color."), + type: "rgba" + }, + blend_mode: { + name: _("Blend mode"), + description: _("How the color is blended in."), + type: "dropdown", + options: [ + _("Normal"), + _("Multiply"), + _("Screen"), + _("Overlay"), + _("Darken"), + _("Lighten"), + _("Plus darker"), + _("Plus lighter"), + _("Color dodge"), + _("Color burn"), + _("Hard light"), + _("Soft light"), + _("Difference"), + _("Exclusion"), + _("Hue"), + _("Saturation"), + _("Color"), + _("Luminosity") + ] + } + } + }, + + pixelize: { + class: PixelizeEffect, + name: _("Pixelize"), + description: _("An effect that pixelizes the image."), + is_advanced: false, + editable_params: { + factor: { + name: _("Factor"), + description: _("How much to scale down the image."), + type: "integer", + min: 1, + max: 50, + increment: 1 + }, + downsampling_mode: { + name: _("Downsampling mode"), + description: _("The downsampling method that is used."), + type: "dropdown", + options: [ + _("Boxcar"), + _("Triangular"), + _("Dirac") + ] + } + } + }, + + downscale: { + class: DownscaleEffect, + name: _("Downscale (advanced effect)"), + description: _("An effect that downscales the image and put it on the top-left corner."), + is_advanced: true, + editable_params: { + divider: { + name: _("Factor"), + description: _("How much to scale down the image."), + type: "integer", + min: 1, + max: 50, + increment: 1 + }, + downsampling_mode: { + name: _("Downsampling mode"), + description: _("The downsampling method that is used."), + type: "dropdown", + options: [ + _("Boxcar"), + _("Triangular"), + _("Dirac") + ] + } + } + }, + + upscale: { + class: UpscaleEffect, + name: _("Upscale (advanced effect)"), + description: _("An effect that upscales the image from the top-left corner."), + is_advanced: true, + editable_params: { + factor: { + name: _("Factor"), + description: _("How much to scale up the image."), + type: "integer", + min: 1, + max: 50, + increment: 1 + } + } + }, + + derivative: { + class: DerivativeEffect, + name: _("Derivative"), + description: _("Apply a spatial derivative, or a laplacian."), + is_advanced: false, + editable_params: { + operation: { + name: _("Operation"), + description: _("The mathematical operation to apply."), + type: "dropdown", + options: [ + _("1-step derivative"), + _("2-step derivative"), + _("Laplacian") + ] + } + } + }, + + noise: { + class: NoiseEffect, + name: _("Noise"), + description: _("An effect that adds a random noise. Prefer the Monte Carlo blur for a more organic effect if needed."), + is_advanced: false, + editable_params: { + noise: { + name: _("Noise"), + description: _("The amount of noise to add."), + type: "float", + min: 0., + max: 1., + increment: 0.01, + big_increment: 0.1, + digits: 2 + }, + lightness: { + name: _("Lightness"), + description: _("The luminosity of the noise. A setting of '1.0' will make the effect transparent."), + type: "float", + min: 0., + max: 2., + increment: 0.01, + big_increment: 0.1, + digits: 2 + } + } + }, + + rgb_to_hsl: { + class: RgbToHslEffect, + name: _("RGB to HSL (advanced effect)"), + description: _("Converts the image from RGBA colorspace to HSLA."), + is_advanced: true, + editable_params: {} + }, + + hsl_to_rgb: { + class: HslToRgbEffect, + name: _("HSL to RGB (advanced effect)"), + description: _("Converts the image from HSLA colorspace to RGBA."), + is_advanced: true, + editable_params: {} + }, + + corner: { + class: CornerEffect, + name: _("Corner"), + description: _("An effect that draws corners. Add it last not to have the other effects perturb the corners."), + is_advanced: false, + editable_params: { + radius: { + name: _("Radius"), + description: _("The radius of the corner. GNOME apps use a radius of 12 px by default."), + type: "integer", + min: 0, + max: 50, + increment: 1, + }, + corners_top: { + name: _("Top corners"), + description: _("Whether or not to round the top corners."), + type: "boolean" + }, + corners_bottom: { + name: _("Bottom corners"), + description: _("Whether or not to round the bottom corners."), + type: "boolean" + } + } + } + }; +}; \ No newline at end of file diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/gaussian_blur.glsl b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/gaussian_blur.glsl new file mode 100644 index 0000000..809cc93 --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/gaussian_blur.glsl @@ -0,0 +1,70 @@ +uniform sampler2D tex; +uniform float sigma; +uniform int dir; +uniform float brightness; +uniform float width; +uniform float height; + +vec4 getTexture(vec2 uv) { + if (uv.x < 3. / width) + uv.x = 3. / width; + + if (uv.y < 3. / height) + uv.y = 3. / height; + + if (uv.x > 1. - 3. / width) + uv.x = 1. - 3. / width; + + if (uv.y > 1. - 3. / height) + uv.y = 1. - 3. / height; + + return texture2D(tex, uv); +} + +void main(void) { + vec2 uv = cogl_tex_coord_in[0].xy; + vec2 direction = vec2(dir, (1.0 - dir)); + + float pixel_step; + if (dir == 0) + pixel_step = 1.0 / height; + else + pixel_step = 1.0 / width; + + vec3 gauss_coefficient; + gauss_coefficient.x = 1.0 / (sqrt(2.0 * 3.14159265) * sigma); + gauss_coefficient.y = exp(-0.5 / (sigma * sigma)); + gauss_coefficient.z = gauss_coefficient.y * gauss_coefficient.y; + + float gauss_coefficient_total = gauss_coefficient.x; + + vec4 ret = getTexture(uv) * gauss_coefficient.x; + gauss_coefficient.xy *= gauss_coefficient.yz; + + int n_steps = int(ceil(1.5 * sigma)) * 2; + + for (int i = 1; i <= n_steps; i += 2) { + float coefficient_subtotal = gauss_coefficient.x; + gauss_coefficient.xy *= gauss_coefficient.yz; + coefficient_subtotal += gauss_coefficient.x; + + float gauss_ratio = gauss_coefficient.x / coefficient_subtotal; + + float foffset = float(i) + gauss_ratio; + vec2 offset = direction * foffset * pixel_step; + + ret += getTexture(uv + offset) * coefficient_subtotal; + ret += getTexture(uv - offset) * coefficient_subtotal; + + gauss_coefficient_total += 2.0 * coefficient_subtotal; + gauss_coefficient.xy *= gauss_coefficient.yz; + } + vec4 outColor = ret / gauss_coefficient_total; + + // apply brightness on the second pass (dir==0 comes last) + if (dir == 0) { + outColor.rgb *= brightness; + } + + cogl_color_out = outColor; +} \ No newline at end of file diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/gaussian_blur.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/gaussian_blur.js new file mode 100644 index 0000000..113a6fd --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/gaussian_blur.js @@ -0,0 +1,213 @@ +import GObject from 'gi://GObject'; + +import * as utils from '../conveniences/utils.js'; +const St = await utils.import_in_shell_only('gi://St'); +const Shell = await utils.import_in_shell_only('gi://Shell'); +const Clutter = await utils.import_in_shell_only('gi://Clutter'); + +const SHADER_FILENAME = 'gaussian_blur.glsl'; +const DEFAULT_PARAMS = { + radius: 30, brightness: .6, + width: 0, height: 0, direction: 0, chained_effect: null +}; + + +export const GaussianBlurEffect = utils.IS_IN_PREFERENCES ? + { default_params: DEFAULT_PARAMS } : + new GObject.registerClass({ + GTypeName: "GaussianBlurEffect", + Properties: { + 'radius': GObject.ParamSpec.double( + `radius`, + `Radius`, + `Blur radius`, + GObject.ParamFlags.READWRITE, + 0.0, 2000.0, + 30.0, + ), + 'brightness': GObject.ParamSpec.double( + `brightness`, + `Brightness`, + `Blur brightness`, + GObject.ParamFlags.READWRITE, + 0.0, 1.0, + 0.6, + ), + 'width': GObject.ParamSpec.double( + `width`, + `Width`, + `Width`, + GObject.ParamFlags.READWRITE, + 0.0, Number.MAX_SAFE_INTEGER, + 0.0, + ), + 'height': GObject.ParamSpec.double( + `height`, + `Height`, + `Height`, + GObject.ParamFlags.READWRITE, + 0.0, Number.MAX_SAFE_INTEGER, + 0.0, + ), + 'direction': GObject.ParamSpec.int( + `direction`, + `Direction`, + `Direction`, + GObject.ParamFlags.READWRITE, + 0, 1, + 0, + ), + 'chained_effect': GObject.ParamSpec.object( + `chained_effect`, + `Chained Effect`, + `Chained Effect`, + GObject.ParamFlags.READWRITE, + GObject.Object, + ), + } + }, class GaussianBlurEffect extends Clutter.ShaderEffect { + constructor(params) { + super(params); + + utils.setup_params(this, params); + + // set shader source + this._source = utils.get_shader_source(Shell, SHADER_FILENAME, import.meta.url); + if (this._source) + this.set_shader_source(this._source); + + const theme_context = St.ThemeContext.get_for_stage(global.stage); + theme_context.connectObject( + 'notify::scale-factor', _ => + this.set_uniform_value('sigma', + parseFloat(this.radius * theme_context.scale_factor / 2 - 1e-6) + ), + this + ); + } + + static get default_params() { + return DEFAULT_PARAMS; + } + + get radius() { + return this._radius; + } + + set radius(value) { + if (this._radius !== value) { + this._radius = value; + + const scale_factor = St.ThemeContext.get_for_stage(global.stage).scale_factor; + + // like Clutter, we use the assumption radius = 2*sigma + this.set_uniform_value('sigma', parseFloat(this._radius * scale_factor / 2 - 1e-6)); + this.set_enabled(this.radius > 0.); + + if (this.chained_effect) + this.chained_effect.radius = value; + } + } + + get brightness() { + return this._brightness; + } + + set brightness(value) { + if (this._brightness !== value) { + this._brightness = value; + + this.set_uniform_value('brightness', parseFloat(this._brightness - 1e-6)); + + if (this.chained_effect) + this.chained_effect.brightness = value; + } + } + + get width() { + return this._width; + } + + set width(value) { + if (this._width !== value) { + this._width = value; + + this.set_uniform_value('width', parseFloat(this._width + 3.0 - 1e-6)); + + if (this.chained_effect) + this.chained_effect.width = value; + } + } + + get height() { + return this._height; + } + + set height(value) { + if (this._height !== value) { + this._height = value; + + this.set_uniform_value('height', parseFloat(this._height + 3.0 - 1e-6)); + + if (this.chained_effect) + this.chained_effect.height = value; + } + } + + get direction() { + return this._direction; + } + + set direction(value) { + if (this._direction !== value) + this._direction = value; + } + + get chained_effect() { + return this._chained_effect; + } + + set chained_effect(value) { + this._chained_effect = value; + } + + vfunc_set_actor(actor) { + if (this._actor_connection_size_id) { + let old_actor = this.get_actor(); + old_actor?.disconnect(this._actor_connection_size_id); + } + if (actor) { + this.width = actor.width; + this.height = actor.height; + this._actor_connection_size_id = actor.connect('notify::size', _ => { + this.width = actor.width; + this.height = actor.height; + }); + } + else + this._actor_connection_size_id = null; + + super.vfunc_set_actor(actor); + + if (this.direction == 0) { + if (this.chained_effect) + this.chained_effect.get_actor()?.remove_effect(this.chained_effect); + else + this.chained_effect = new GaussianBlurEffect({ + radius: this.radius, + brightness: this.brightness, + width: this.width, + height: this.height, + direction: 1 + }); + if (actor !== null) + actor.add_effect(this.chained_effect); + } + } + + vfunc_paint_target(paint_node, paint_context) { + this.set_uniform_value("dir", this.direction); + + super.vfunc_paint_target(paint_node, paint_context); + } + }); \ No newline at end of file diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/hsl_to_rgb.glsl b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/hsl_to_rgb.glsl new file mode 100644 index 0000000..58d2694 --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/hsl_to_rgb.glsl @@ -0,0 +1,14 @@ +uniform sampler2D tex; + +vec3 hsl_to_rgb(vec3 c) { + vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); + vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www); + return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y); +} + +void main(void) { + vec2 uv = cogl_tex_coord_in[0].xy; + vec4 hsla = texture2D(tex, uv); + vec4 rgba = vec4(hsl_to_rgb(hsla.xyz), hsla.w); + cogl_color_out = rgba; +} \ No newline at end of file diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/hsl_to_rgb.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/hsl_to_rgb.js new file mode 100644 index 0000000..fe53114 --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/hsl_to_rgb.js @@ -0,0 +1,31 @@ +import GObject from 'gi://GObject'; + +import * as utils from '../conveniences/utils.js'; +const Shell = await utils.import_in_shell_only('gi://Shell'); +const Clutter = await utils.import_in_shell_only('gi://Clutter'); + +const SHADER_FILENAME = 'hsl_to_rgb.glsl'; +const DEFAULT_PARAMS = {}; + + +export const HslToRgbEffect = utils.IS_IN_PREFERENCES ? + { default_params: DEFAULT_PARAMS } : + new GObject.registerClass({ + GTypeName: "HslToRgbEffect", + Properties: {} + }, class HslToRgbEffect extends Clutter.ShaderEffect { + constructor(params) { + super(params); + + utils.setup_params(this, params); + + // set shader source + this._source = utils.get_shader_source(Shell, SHADER_FILENAME, import.meta.url); + if (this._source) + this.set_shader_source(this._source); + } + + static get default_params() { + return DEFAULT_PARAMS; + } + }); \ No newline at end of file diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/monte_carlo_blur.glsl b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/monte_carlo_blur.glsl new file mode 100644 index 0000000..27b3806 --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/monte_carlo_blur.glsl @@ -0,0 +1,52 @@ +uniform sampler2D tex; +uniform float radius; +uniform int iterations; +uniform float brightness; +uniform float width; +uniform float height; +uniform bool use_base_pixel; +uniform bool prefer_closer_pixels; + +float srand(vec2 a) { + return sin(dot(a, vec2(1233.224, 1743.335))); +} + +float rand(inout float r) { + r = fract(3712.65 * r + 0.61432); + return (r - 0.5) * 2.0; +} + +void main() { + vec2 uv = cogl_tex_coord0_in.st; + vec2 p = 16 * radius / vec2(width, height); + float r = srand(uv); + + vec2 rv; + vec2 dir; + vec2 new_uv; + int strength; + + int count = 0; + vec4 c = vec4(0.); + + for (int i = 0; i < iterations; i++) { + rv.x = rand(r); + rv.y = rand(r) * 3.141592; + dir = vec2(cos(rv.y), sin(rv.y)); + new_uv = uv + rv.x * dir * p; + if (new_uv.x > 2. / width && new_uv.y > 2. / height && new_uv.x < 1. - 3. / width && new_uv.y < 1. - 3. / height) { + strength = prefer_closer_pixels ? (iterations - i)^2 : 1; + c += strength * texture2D(tex, new_uv); + count += strength; + } + } + + if (count == 0 || use_base_pixel) { + strength = prefer_closer_pixels ? (iterations + 1)^2 : 1; + c += strength * texture2D(tex, uv); + count += strength; + } + + c.xyz *= brightness; + cogl_color_out = c / count; +} \ No newline at end of file diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/monte_carlo_blur.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/monte_carlo_blur.js new file mode 100644 index 0000000..0da56ed --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/monte_carlo_blur.js @@ -0,0 +1,207 @@ +import GObject from 'gi://GObject'; + +import * as utils from '../conveniences/utils.js'; +const St = await utils.import_in_shell_only('gi://St'); +const Shell = await utils.import_in_shell_only('gi://Shell'); +const Clutter = await utils.import_in_shell_only('gi://Clutter'); + +const SHADER_FILENAME = 'monte_carlo_blur.glsl'; +const DEFAULT_PARAMS = { + radius: 2., iterations: 5, brightness: .6, + width: 0, height: 0, use_base_pixel: true, + prefer_closer_pixels: true, +}; + + +export const MonteCarloBlurEffect = utils.IS_IN_PREFERENCES ? + { default_params: DEFAULT_PARAMS } : + new GObject.registerClass({ + GTypeName: "MonteCarloBlurEffect", + Properties: { + 'radius': GObject.ParamSpec.double( + `radius`, + `Radius`, + `Blur radius`, + GObject.ParamFlags.READWRITE, + 0.0, 2000.0, + 2.0, + ), + 'iterations': GObject.ParamSpec.int( + `iterations`, + `Iterations`, + `Blur iterations`, + GObject.ParamFlags.READWRITE, + 0, 64, + 5, + ), + 'brightness': GObject.ParamSpec.double( + `brightness`, + `Brightness`, + `Blur brightness`, + GObject.ParamFlags.READWRITE, + 0.0, 1.0, + 0.6, + ), + 'width': GObject.ParamSpec.double( + `width`, + `Width`, + `Width`, + GObject.ParamFlags.READWRITE, + 0.0, Number.MAX_SAFE_INTEGER, + 0.0, + ), + 'height': GObject.ParamSpec.double( + `height`, + `Height`, + `Height`, + GObject.ParamFlags.READWRITE, + 0.0, Number.MAX_SAFE_INTEGER, + 0.0, + ), + 'use_base_pixel': GObject.ParamSpec.boolean( + `use_base_pixel`, + `Use base pixel`, + `Use base pixel`, + GObject.ParamFlags.READWRITE, + true, + ), + 'prefer_closer_pixels': GObject.ParamSpec.boolean( + `prefer_closer_pixels`, + `Prefer closer pixels`, + `Prefer closer pixels`, + GObject.ParamFlags.READWRITE, + true, + ), + } + }, class MonteCarloBlurEffect extends Clutter.ShaderEffect { + constructor(params) { + super(params); + + utils.setup_params(this, params); + + // set shader source + this._source = utils.get_shader_source(Shell, SHADER_FILENAME, import.meta.url); + if (this._source) + this.set_shader_source(this._source); + + const theme_context = St.ThemeContext.get_for_stage(global.stage); + theme_context.connectObject( + 'notify::scale-factor', + _ => this.set_uniform_value('radius', + parseFloat(this._radius * theme_context.scale_factor - 1e-6) + ), + this + ); + } + + static get default_params() { + return DEFAULT_PARAMS; + } + + get radius() { + return this._radius; + } + + set radius(value) { + if (this._radius !== value) { + this._radius = value; + + const scale_factor = St.ThemeContext.get_for_stage(global.stage).scale_factor; + + this.set_uniform_value('radius', parseFloat(this._radius * scale_factor - 1e-6)); + this.set_enabled(this.radius > 0. && this.iterations > 0); + } + } + + get iterations() { + return this._iterations; + } + + set iterations(value) { + if (this._iterations !== value) { + this._iterations = value; + + this.set_uniform_value('iterations', this._iterations); + this.set_enabled(this.radius > 0. && this.iterations > 0); + } + } + + get brightness() { + return this._brightness; + } + + set brightness(value) { + if (this._brightness !== value) { + this._brightness = value; + + this.set_uniform_value('brightness', parseFloat(this._brightness - 1e-6)); + } + } + + get width() { + return this._width; + } + + set width(value) { + if (this._width !== value) { + this._width = value; + + this.set_uniform_value('width', parseFloat(this._width + 3.0 - 1e-6)); + } + } + + get height() { + return this._height; + } + + set height(value) { + if (this._height !== value) { + this._height = value; + + this.set_uniform_value('height', parseFloat(this._height + 3.0 - 1e-6)); + } + } + + get use_base_pixel() { + return this._use_base_pixel; + } + + set use_base_pixel(value) { + if (this._use_base_pixel !== value) { + this._use_base_pixel = value; + + this.set_uniform_value('use_base_pixel', this._use_base_pixel ? 1 : 0); + } + } + + get prefer_closer_pixels() { + return this._prefer_closer_pixels; + } + + set prefer_closer_pixels(value) { + if (this._prefer_closer_pixels !== value) { + this._prefer_closer_pixels = value; + + this.set_uniform_value('prefer_closer_pixels', this._prefer_closer_pixels ? 1 : 0); + } + } + + vfunc_set_actor(actor) { + if (this._actor_connection_size_id) { + let old_actor = this.get_actor(); + old_actor?.disconnect(this._actor_connection_size_id); + } + if (actor) { + this.width = actor.width; + this.height = actor.height; + this._actor_connection_size_id = actor.connect('notify::size', _ => { + this.width = actor.width; + this.height = actor.height; + }); + } + else + this._actor_connection_size_id = null; + + super.vfunc_set_actor(actor); + } + }); \ No newline at end of file diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/native_dynamic_gaussian_blur.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/native_dynamic_gaussian_blur.js new file mode 100644 index 0000000..556ffa4 --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/native_dynamic_gaussian_blur.js @@ -0,0 +1,43 @@ +import GObject from 'gi://GObject'; + +import * as utils from '../conveniences/utils.js'; +const St = await utils.import_in_shell_only('gi://St'); +const Shell = await utils.import_in_shell_only('gi://Shell'); + +const DEFAULT_PARAMS = { + unscaled_radius: 30, brightness: 0.6 +}; + + +export const NativeDynamicBlurEffect = utils.IS_IN_PREFERENCES ? + { default_params: DEFAULT_PARAMS } : + new GObject.registerClass({ + GTypeName: "NativeDynamicBlurEffect" + }, class NativeDynamicBlurEffect extends Shell.BlurEffect { + constructor(params) { + const { unscaled_radius, brightness, ...parent_params } = params; + super({ ...parent_params, mode: Shell.BlurMode.BACKGROUND }); + + this._theme_context = St.ThemeContext.get_for_stage(global.stage); + this._theme_context.connectObject( + 'notify::scale-factor', + _ => this.radius = this.unscaled_radius * this._theme_context.scale_factor, + this + ); + + utils.setup_params(this, params); + } + + static get default_params() { + return DEFAULT_PARAMS; + } + + get unscaled_radius() { + return this._unscaled_radius; + } + + set unscaled_radius(value) { + this._unscaled_radius = value; + this.radius = value * this._theme_context.scale_factor; + } + }); \ No newline at end of file diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/native_static_gaussian_blur.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/native_static_gaussian_blur.js new file mode 100644 index 0000000..fe003f5 --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/native_static_gaussian_blur.js @@ -0,0 +1,43 @@ +import GObject from 'gi://GObject'; + +import * as utils from '../conveniences/utils.js'; +const St = await utils.import_in_shell_only('gi://St'); +const Shell = await utils.import_in_shell_only('gi://Shell'); + +const DEFAULT_PARAMS = { + unscaled_radius: 30, brightness: 0.6 +}; + + +export const NativeStaticBlurEffect = utils.IS_IN_PREFERENCES ? + { default_params: DEFAULT_PARAMS } : + new GObject.registerClass({ + GTypeName: "NativeStaticBlurEffect" + }, class NativeStaticBlurEffect extends Shell.BlurEffect { + constructor(params) { + const { unscaled_radius, brightness, ...parent_params } = params; + super({ ...parent_params, mode: Shell.BlurMode.ACTOR }); + + this._theme_context = St.ThemeContext.get_for_stage(global.stage); + this._theme_context.connectObject( + 'notify::scale-factor', + _ => this.radius = this.unscaled_radius * this._theme_context.scale_factor, + this + ); + + utils.setup_params(this, params); + } + + static get default_params() { + return DEFAULT_PARAMS; + } + + get unscaled_radius() { + return this._unscaled_radius; + } + + set unscaled_radius(value) { + this._unscaled_radius = value; + this.radius = value * this._theme_context.scale_factor; + } + }); \ No newline at end of file diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/noise.glsl b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/noise.glsl new file mode 100644 index 0000000..6d701b6 --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/noise.glsl @@ -0,0 +1,20 @@ +uniform sampler2D tex; +uniform float noise; +uniform float lightness; + +float PHI = 1.61803398874989484820459; +float SEED = 24; + +float noise_gen(in vec2 xy) { + float r = fract(tan(distance(xy * PHI, xy) * SEED) * xy.x); + r = r != r ? 0.0 : r; + return r; +} + +void main() { + vec4 c = texture2D(tex, cogl_tex_coord_in[0].st); + vec3 pix_color = c.xyz; + float blend = noise * (1. - noise_gen(gl_FragCoord.xy)); + + cogl_color_out = vec4(mix(pix_color, lightness * pix_color, blend), 1.); +} \ No newline at end of file diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/noise.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/noise.js new file mode 100644 index 0000000..3049fa1 --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/noise.js @@ -0,0 +1,76 @@ +import GObject from 'gi://GObject'; + +import * as utils from '../conveniences/utils.js'; +const Shell = await utils.import_in_shell_only('gi://Shell'); +const Clutter = await utils.import_in_shell_only('gi://Clutter'); + +const SHADER_FILENAME = 'noise.glsl'; +const DEFAULT_PARAMS = { + noise: 0.4, lightness: 0.4 +}; + + +export const NoiseEffect = utils.IS_IN_PREFERENCES ? + { default_params: DEFAULT_PARAMS } : + new GObject.registerClass({ + GTypeName: "NoiseEffect", + Properties: { + 'noise': GObject.ParamSpec.double( + `noise`, + `Noise`, + `Amount of noise integrated with the image`, + GObject.ParamFlags.READWRITE, + 0.0, 1.0, + 0.4, + ), + 'lightness': GObject.ParamSpec.double( + `lightness`, + `Lightness`, + `Lightness of the grey used for the noise`, + GObject.ParamFlags.READWRITE, + 0.0, 2.0, + 0.4, + ), + } + }, class NoiseEffect extends Clutter.ShaderEffect { + constructor(params) { + super(params); + + utils.setup_params(this, params); + + // set shader source + this._source = utils.get_shader_source(Shell, SHADER_FILENAME, import.meta.url); + if (this._source) + this.set_shader_source(this._source); + } + + static get default_params() { + return DEFAULT_PARAMS; + } + + get noise() { + return this._noise; + } + + set noise(value) { + if (this._noise !== value) { + this._noise = value; + + this.set_uniform_value('noise', parseFloat(this._noise - 1e-6)); + this.set_enabled(this.noise > 0. && this.lightness != 1); + } + } + + get lightness() { + return this._lightness; + } + + set lightness(value) { + if (this._lightness !== value) { + this._lightness = value; + + this.set_uniform_value('lightness', parseFloat(this._lightness - 1e-6)); + this.set_enabled(this.noise > 0. && this.lightness != 1); + } + } + }); \ No newline at end of file diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/pixelize.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/pixelize.js new file mode 100644 index 0000000..e9cad9b --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/pixelize.js @@ -0,0 +1,88 @@ +import GObject from 'gi://GObject'; + +import * as utils from '../conveniences/utils.js'; +const Clutter = await utils.import_in_shell_only('gi://Clutter'); + +import { UpscaleEffect } from './upscale.js'; +import { DownscaleEffect } from './downscale.js'; + +const DEFAULT_PARAMS = { + factor: 8, downsampling_mode: 0 +}; + + +export const PixelizeEffect = utils.IS_IN_PREFERENCES ? + { default_params: DEFAULT_PARAMS } : + new GObject.registerClass({ + GTypeName: "PixelizeEffect", + Properties: { + 'factor': GObject.ParamSpec.int( + `factor`, + `Factor`, + `Factor`, + GObject.ParamFlags.READWRITE, + 0, 64, + 8, + ), + 'downsampling_mode': GObject.ParamSpec.int( + `downsampling_mode`, + `Downsampling mode`, + `Downsampling mode`, + GObject.ParamFlags.READWRITE, + 0, 2, + 0, + ) + } + }, class PixelizeEffect extends Clutter.Effect { + constructor(params) { + super(); + + this.upscale_effect = new UpscaleEffect({}); + this.downscale_effect = new DownscaleEffect({}); + + utils.setup_params(this, params); + } + + static get default_params() { + return DEFAULT_PARAMS; + } + + get factor() { + // should be the same as `this.downscale_effect.divider` + return this.upscale_effect.factor; + } + + set factor(value) { + this.upscale_effect.factor = value; + this.downscale_effect.divider = value; + } + + get downsampling_mode() { + return this.downscale_effect.downsampling_mode; + } + + set downsampling_mode(value) { + this.downscale_effect.downsampling_mode = value; + } + + vfunc_set_actor(actor) { + // deattach effects from old actor + this.upscale_effect?.actor?.remove_effect(this.upscale_effect); + this.downscale_effect?.actor?.remove_effect(this.downscale_effect); + // attach effects to new actor + if (actor) { + if (this.upscale_effect) + actor.add_effect(this.upscale_effect); + if (this.downscale_effect) + actor.add_effect(this.downscale_effect); + } + + super.vfunc_set_actor(actor); + } + + vfunc_set_enabled(is_enabled) { + this.upscale_effect?.set_enabled(is_enabled); + this.downscale_effect?.set_enabled(is_enabled); + super.vfunc_set_enabled(is_enabled); + } + }); \ No newline at end of file diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/rgb_to_hsl.glsl b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/rgb_to_hsl.glsl new file mode 100644 index 0000000..b7a35ac --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/rgb_to_hsl.glsl @@ -0,0 +1,18 @@ +uniform sampler2D tex; + +vec3 rgb_to_hsl(vec3 c) { + vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0); + vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g)); + vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r)); + + float d = q.x - min(q.w, q.y); + float e = 1.0e-10; + return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x); +} + +void main(void) { + vec2 uv = cogl_tex_coord_in[0].xy; + vec4 rgba = texture2D(tex, uv); + vec4 hsla = vec4(rgb_to_hsl(rgba.xyz), rgba.w); + cogl_color_out = hsla; +} \ No newline at end of file diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/rgb_to_hsl.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/rgb_to_hsl.js new file mode 100644 index 0000000..5c4eb05 --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/rgb_to_hsl.js @@ -0,0 +1,31 @@ +import GObject from 'gi://GObject'; + +import * as utils from '../conveniences/utils.js'; +const Shell = await utils.import_in_shell_only('gi://Shell'); +const Clutter = await utils.import_in_shell_only('gi://Clutter'); + +const SHADER_FILENAME = 'rgb_to_hsl.glsl'; +const DEFAULT_PARAMS = {}; + + +export const RgbToHslEffect = utils.IS_IN_PREFERENCES ? + { default_params: DEFAULT_PARAMS } : + new GObject.registerClass({ + GTypeName: "RgbToHslEffect", + Properties: {} + }, class RgbToHslEffect extends Clutter.ShaderEffect { + constructor(params) { + super(params); + + utils.setup_params(this, params); + + // set shader source + this._source = utils.get_shader_source(Shell, SHADER_FILENAME, import.meta.url); + if (this._source) + this.set_shader_source(this._source); + } + + static get default_params() { + return DEFAULT_PARAMS; + } + }); \ No newline at end of file diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/upscale.glsl b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/upscale.glsl new file mode 100644 index 0000000..5cc06ec --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/upscale.glsl @@ -0,0 +1,57 @@ +uniform sampler2D tex; +uniform int factor; +uniform float width; +uniform float height; + +#define CORRECTION 2.25 +#define SIZE_ADDITION 3 + +vec4 get_texture_at_position(vec2 position) { + vec2 raw_position = position + vec2(CORRECTION, CORRECTION); + vec2 raw_uv = raw_position / vec2(width + SIZE_ADDITION, height + SIZE_ADDITION); + + return texture2D(tex, raw_uv); +} + +ivec2 get_corrected_position() { + vec2 raw_uv = cogl_tex_coord0_in.st; + vec2 raw_position = raw_uv * vec2(width + SIZE_ADDITION, height + SIZE_ADDITION); + return ivec2(raw_position - vec2(CORRECTION, CORRECTION)); +} + +void main() { + ivec2 corrected_position = get_corrected_position(); + + vec2 adjusted_position = corrected_position / factor; + + cogl_color_out = get_texture_at_position(adjusted_position); + + // round + if (distance(corrected_position, (floor(adjusted_position) + 0.5) * factor) < factor / 2.5) { + //cogl_color_out = get_texture_at_position(adjusted_position); + } else { + //cogl_color_out = vec4(0, 0, 0, 1); + } + + // square + if (mod(corrected_position.x, factor) >= 2 && mod(corrected_position.y, factor) >= 2) { + //cogl_color_out = get_texture_at_position(adjusted_position); + } else { + //cogl_color_out = vec4(0, 0, 0, 1); + } + + // local mix + vec4 color = vec4(0); + int count = 0; + for (int i = -1; i <= 1; i++) { + for (int j = -1; j <= 1; j++) { + vec2 lookup_position = adjusted_position + vec2(i, j); + if (all(greaterThanEqual(lookup_position, vec2(0, 0))) && + all(lessThan(lookup_position, vec2(width, height) / factor))) { + color += get_texture_at_position(lookup_position); + count += 1; + } + } + } + //cogl_color_out = color / count; +} \ No newline at end of file diff --git a/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/upscale.js b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/upscale.js new file mode 100644 index 0000000..fb719c3 --- /dev/null +++ b/raveos-gnome-theme/theme-data/extensions/installed/blur-my-shell@aunetx/effects/upscale.js @@ -0,0 +1,120 @@ +import GObject from 'gi://GObject'; + +import * as utils from '../conveniences/utils.js'; +const Shell = await utils.import_in_shell_only('gi://Shell'); +const Clutter = await utils.import_in_shell_only('gi://Clutter'); + +const SHADER_FILENAME = 'upscale.glsl'; +const DEFAULT_PARAMS = { + factor: 8, width: 0, height: 0 +}; + + +export const UpscaleEffect = utils.IS_IN_PREFERENCES ? + { default_params: DEFAULT_PARAMS } : + new GObject.registerClass({ + GTypeName: "UpscaleEffect", + Properties: { + 'factor': GObject.ParamSpec.int( + `factor`, + `Factor`, + `Factor`, + GObject.ParamFlags.READWRITE, + 0, 64, + 8, + ), + 'width': GObject.ParamSpec.double( + `width`, + `Width`, + `Width`, + GObject.ParamFlags.READWRITE, + 0.0, Number.MAX_SAFE_INTEGER, + 0.0, + ), + 'height': GObject.ParamSpec.double( + `height`, + `Height`, + `Height`, + GObject.ParamFlags.READWRITE, + 0.0, Number.MAX_SAFE_INTEGER, + 0.0, + ) + } + }, class UpscaleEffect extends Clutter.ShaderEffect { + constructor(params) { + super(params); + + utils.setup_params(this, params); + + // set shader source + this._source = utils.get_shader_source(Shell, SHADER_FILENAME, import.meta.url); + if (this._source) + this.set_shader_source(this._source); + } + + static get default_params() { + return DEFAULT_PARAMS; + } + + get factor() { + return this._factor; + } + + set factor(value) { + if (this._factor !== value) { + this._factor = value; + + this.set_uniform_value('factor', this._factor); + } + } + + get width() { + return this._width; + } + + set width(value) { + if (this._width !== value) { + this._width = value; + + this.set_uniform_value('width', parseFloat(this._width - 1e-6)); + } + } + + get height() { + return this._height; + } + + set height(value) { + if (this._height !== value) { + this._height = value; + + this.set_uniform_value('height', parseFloat(this._height - 1e-6)); + } + } + + vfunc_set_actor(actor) { + if (this._actor_connection_size_id) { + let old_actor = this.get_actor(); + old_actor?.disconnect(this._actor_connection_size_id); + } + if (actor) { + this.width = actor.width; + this.height = actor.height; + this._actor_connection_size_id = actor.connect('notify::size', _ => { + this.width = actor.width; + this.height = actor.height; + }); + } + else + this._actor_connection_size_id = null; + + super.vfunc_set_actor(actor); + } + + vfunc_paint_target(paint_node, paint_context) { + // force setting nearest-neighbour texture filtering + this.get_pipeline().set_layer_filters(0, 9728, 9728); + + super.vfunc_paint_target(paint_node, paint_context); + } + }); \ No newline at end of file -- cgit v1.3