From b8e11516ff559bab11df59073ae5712c726d2d70 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Thu, 29 May 2025 10:00:58 +0900 Subject: [PATCH] wip --- locales/index.d.ts | 4 + locales/ja-JP.yml | 1 + .../utility/image-effector/ImageEffector.ts | 3 + .../src/utility/image-effector/fxs.ts | 2 + .../src/utility/image-effector/fxs/distort.ts | 82 +++++++++++++++++++ 5 files changed, 92 insertions(+) create mode 100644 packages/frontend/src/utility/image-effector/fxs/distort.ts diff --git a/locales/index.d.ts b/locales/index.d.ts index d08af02dd9..247db9c0a8 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -12104,6 +12104,10 @@ export interface Locale extends ILocale { * 色の圧縮(高度) */ "colorClampAdvanced": string; + /** + * 歪み + */ + "distort": string; }; }; } diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 42e496a8ce..54bcecc958 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -3244,3 +3244,4 @@ _imageEffector: grayscale: "白黒" colorClamp: "色の圧縮" colorClampAdvanced: "色の圧縮(高度)" + distort: "歪み" diff --git a/packages/frontend/src/utility/image-effector/ImageEffector.ts b/packages/frontend/src/utility/image-effector/ImageEffector.ts index d36cd263e7..ce6bdef273 100644 --- a/packages/frontend/src/utility/image-effector/ImageEffector.ts +++ b/packages/frontend/src/utility/image-effector/ImageEffector.ts @@ -332,6 +332,9 @@ export class ImageEffector { gl.useProgram(shaderProgram); + const u_resolution = gl.getUniformLocation(shaderProgram, 'u_resolution'); + gl.uniform2fv(u_resolution, [this.renderWidth, this.renderHeight]); + fx.main({ gl: gl, program: shaderProgram, diff --git a/packages/frontend/src/utility/image-effector/fxs.ts b/packages/frontend/src/utility/image-effector/fxs.ts index 07d455d960..1927e0c8d8 100644 --- a/packages/frontend/src/utility/image-effector/fxs.ts +++ b/packages/frontend/src/utility/image-effector/fxs.ts @@ -6,6 +6,7 @@ import { FX_chromaticAberration } from './fxs/chromaticAberration.js'; import { FX_colorClamp } from './fxs/colorClamp.js'; import { FX_colorClampAdvanced } from './fxs/colorClampAdvanced.js'; +import { FX_distort } from './fxs/distort.js'; import { FX_glitch } from './fxs/glitch.js'; import { FX_grayscale } from './fxs/grayscale.js'; import { FX_invert } from './fxs/invert.js'; @@ -22,4 +23,5 @@ export const FXS = [ FX_grayscale, FX_colorClamp, FX_colorClampAdvanced, + FX_distort, ] as const satisfies ImageEffectorFx[]; diff --git a/packages/frontend/src/utility/image-effector/fxs/distort.ts b/packages/frontend/src/utility/image-effector/fxs/distort.ts new file mode 100644 index 0000000000..03f6c2bddb --- /dev/null +++ b/packages/frontend/src/utility/image-effector/fxs/distort.ts @@ -0,0 +1,82 @@ +/* + * 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 u_texture; +uniform vec2 u_resolution; +uniform float u_phase; +uniform float u_frequency; +uniform float u_strength; +uniform int u_direction; // 0: vertical, 1: horizontal +out vec4 out_color; + +void main() { + float v = u_direction == 0 ? + sin(u_phase + in_uv.y * u_frequency) * u_strength : + sin(u_phase + in_uv.x * u_frequency) * u_strength; + vec4 in_color = u_direction == 0 ? + texture(u_texture, vec2(in_uv.x + v, in_uv.y)) : + texture(u_texture, vec2(in_uv.x, in_uv.y + v)); + out_color = in_color; +} +`; + +export const FX_distort = defineImageEffectorFx({ + id: 'distort' as const, + name: i18n.ts._imageEffector._fxs.distort, + shader, + params: { + direction: { + type: 'number:enum' as const, + enum: [{ value: 0, label: 'v' }, { value: 1, label: 'h' }], + default: 0, + }, + phase: { + type: 'number' as const, + default: 50.0, + min: 0.0, + max: 100, + step: 0.01, + }, + frequency: { + type: 'number' as const, + default: 50, + min: 0, + max: 100, + step: 0.1, + }, + strength: { + type: 'number' as const, + default: 0.1, + min: 0, + max: 1, + step: 0.01, + }, + }, + main: ({ gl, program, params, preTexture }) => { + gl.activeTexture(gl.TEXTURE0); + gl.bindTexture(gl.TEXTURE_2D, preTexture); + const u_texture = gl.getUniformLocation(program, 'u_texture'); + gl.uniform1i(u_texture, 0); + + const u_phase = gl.getUniformLocation(program, 'u_phase'); + gl.uniform1f(u_phase, params.phase / 10); + + const u_frequency = gl.getUniformLocation(program, 'u_frequency'); + gl.uniform1f(u_frequency, params.frequency); + + const u_strength = gl.getUniformLocation(program, 'u_strength'); + gl.uniform1f(u_strength, params.strength); + + const u_direction = gl.getUniformLocation(program, 'u_direction'); + gl.uniform1i(u_direction, params.direction); + }, +});