Implement blur effect for image effector system

Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot] 2025-09-20 02:04:00 +00:00
parent 2fe422c10b
commit fa503d3f90
4 changed files with 72 additions and 0 deletions

View File

@ -3194,6 +3194,7 @@ _imageEffector:
mirror: "Mirror" mirror: "Mirror"
invert: "Invert Colors" invert: "Invert Colors"
grayscale: "Grayscale" grayscale: "Grayscale"
blur: "Blur"
colorAdjust: "Color Correction" colorAdjust: "Color Correction"
colorClamp: "Color Compression" colorClamp: "Color Compression"
colorClampAdvanced: "Color Compression (Advanced)" colorClampAdvanced: "Color Compression (Advanced)"
@ -3209,6 +3210,7 @@ _imageEffector:
angle: "Angle" angle: "Angle"
scale: "Size" scale: "Size"
size: "Size" size: "Size"
radius: "Radius"
color: "Color" color: "Color"
opacity: "Opacity" opacity: "Opacity"
normalize: "Normalize" normalize: "Normalize"

View File

@ -3306,6 +3306,7 @@ _imageEffector:
mirror: "ミラー" mirror: "ミラー"
invert: "色の反転" invert: "色の反転"
grayscale: "白黒" grayscale: "白黒"
blur: "ぼかし"
colorAdjust: "色調補正" colorAdjust: "色調補正"
colorClamp: "色の圧縮" colorClamp: "色の圧縮"
colorClampAdvanced: "色の圧縮(高度)" colorClampAdvanced: "色の圧縮(高度)"
@ -3323,6 +3324,7 @@ _imageEffector:
angle: "角度" angle: "角度"
scale: "サイズ" scale: "サイズ"
size: "サイズ" size: "サイズ"
radius: "半径"
offset: "位置" offset: "位置"
color: "色" color: "色"
opacity: "不透明度" opacity: "不透明度"

View File

@ -3,6 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-only * SPDX-License-Identifier: AGPL-3.0-only
*/ */
import { FX_blur } from './fxs/blur.js';
import { FX_checker } from './fxs/checker.js'; import { FX_checker } from './fxs/checker.js';
import { FX_chromaticAberration } from './fxs/chromaticAberration.js'; import { FX_chromaticAberration } from './fxs/chromaticAberration.js';
import { FX_colorAdjust } from './fxs/colorAdjust.js'; import { FX_colorAdjust } from './fxs/colorAdjust.js';
@ -25,6 +26,7 @@ export const FXS = [
FX_mirror, FX_mirror,
FX_invert, FX_invert,
FX_grayscale, FX_grayscale,
FX_blur,
FX_colorAdjust, FX_colorAdjust,
FX_colorClamp, FX_colorClamp,
FX_colorClampAdvanced, FX_colorClampAdvanced,

View File

@ -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);
},
});