From fa503d3f9069042991dc09d9df5caadfb5fb7687 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 20 Sep 2025 02:04:00 +0000 Subject: [PATCH] Implement blur effect for image effector system Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com> --- locales/en-US.yml | 2 + locales/ja-JP.yml | 2 + .../src/utility/image-effector/fxs.ts | 2 + .../src/utility/image-effector/fxs/blur.ts | 66 +++++++++++++++++++ 4 files changed, 72 insertions(+) create mode 100644 packages/frontend/src/utility/image-effector/fxs/blur.ts diff --git a/locales/en-US.yml b/locales/en-US.yml index 9c02e83021..e54060c267 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -3194,6 +3194,7 @@ _imageEffector: mirror: "Mirror" invert: "Invert Colors" grayscale: "Grayscale" + blur: "Blur" colorAdjust: "Color Correction" colorClamp: "Color Compression" colorClampAdvanced: "Color Compression (Advanced)" @@ -3209,6 +3210,7 @@ _imageEffector: angle: "Angle" scale: "Size" size: "Size" + radius: "Radius" color: "Color" opacity: "Opacity" normalize: "Normalize" diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 4ae52990e5..dcb1701a06 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -3306,6 +3306,7 @@ _imageEffector: mirror: "ミラー" invert: "色の反転" grayscale: "白黒" + blur: "ぼかし" colorAdjust: "色調補正" colorClamp: "色の圧縮" colorClampAdvanced: "色の圧縮(高度)" @@ -3323,6 +3324,7 @@ _imageEffector: angle: "角度" scale: "サイズ" size: "サイズ" + radius: "半径" offset: "位置" color: "色" opacity: "不透明度" diff --git a/packages/frontend/src/utility/image-effector/fxs.ts b/packages/frontend/src/utility/image-effector/fxs.ts index 43e10a22fc..b954bd370d 100644 --- a/packages/frontend/src/utility/image-effector/fxs.ts +++ b/packages/frontend/src/utility/image-effector/fxs.ts @@ -3,6 +3,7 @@ * SPDX-License-Identifier: AGPL-3.0-only */ +import { FX_blur } from './fxs/blur.js'; import { FX_checker } from './fxs/checker.js'; import { FX_chromaticAberration } from './fxs/chromaticAberration.js'; import { FX_colorAdjust } from './fxs/colorAdjust.js'; @@ -25,6 +26,7 @@ export const FXS = [ FX_mirror, FX_invert, FX_grayscale, + FX_blur, FX_colorAdjust, FX_colorClamp, FX_colorClampAdvanced, diff --git a/packages/frontend/src/utility/image-effector/fxs/blur.ts b/packages/frontend/src/utility/image-effector/fxs/blur.ts new file mode 100644 index 0000000000..31324e08d3 --- /dev/null +++ b/packages/frontend/src/utility/image-effector/fxs/blur.ts @@ -0,0 +1,66 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { defineImageEffectorFx } from '../ImageEffector.js'; +import { i18n } from '@/i18n.js'; + +const shader = `#version 300 es +precision mediump float; + +in vec2 in_uv; +uniform sampler2D in_texture; +uniform vec2 in_resolution; +uniform float u_radius; +out vec4 out_color; + +void main() { + vec2 texelSize = 1.0 / in_resolution; + vec4 result = vec4(0.0); + + // Simple box blur with fixed kernel size for better performance + // This avoids dynamic loops which can be slow on some GPUs + float radius = min(u_radius, 8.0); // Clamp to reasonable maximum + + // Sample in a cross pattern for efficiency + result += texture(in_texture, in_uv); // Center + + // Horizontal samples + result += texture(in_texture, in_uv + vec2(-radius * texelSize.x, 0.0)); + result += texture(in_texture, in_uv + vec2(radius * texelSize.x, 0.0)); + + // Vertical samples + result += texture(in_texture, in_uv + vec2(0.0, -radius * texelSize.y)); + result += texture(in_texture, in_uv + vec2(0.0, radius * texelSize.y)); + + // Diagonal samples for better quality + result += texture(in_texture, in_uv + vec2(-radius * texelSize.x, -radius * texelSize.y)); + result += texture(in_texture, in_uv + vec2(radius * texelSize.x, -radius * texelSize.y)); + result += texture(in_texture, in_uv + vec2(-radius * texelSize.x, radius * texelSize.y)); + result += texture(in_texture, in_uv + vec2(radius * texelSize.x, radius * texelSize.y)); + + // Average the samples + out_color = result / 9.0; +} +`; + +export const FX_blur = defineImageEffectorFx({ + id: 'blur', + name: i18n.ts._imageEffector._fxs.blur, + shader, + uniforms: ['radius'] as const, + params: { + radius: { + label: i18n.ts._imageEffector._fxProps.radius, + type: 'number', + default: 3.0, + min: 0.0, + max: 10.0, + step: 0.5, + }, + }, + main: ({ gl, u, params }) => { + gl.uniform1f(u.radius, params.radius); + }, +}); \ No newline at end of file