From 4f8ea38e8439666b7b823b0441224692683a24dc Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Tue, 3 Jun 2025 15:25:06 +0900 Subject: [PATCH] wip --- locales/index.d.ts | 8 + locales/ja-JP.yml | 2 + .../src/utility/image-effector/fxs.ts | 2 + .../utility/image-effector/fxs/dottedGrid.ts | 151 ++++++++++++++++++ .../src/utility/image-effector/fxs/stripe.ts | 10 +- .../image-effector/fxs/watermarkPlacement.ts | 11 +- 6 files changed, 176 insertions(+), 8 deletions(-) create mode 100644 packages/frontend/src/utility/image-effector/fxs/dottedGrid.ts diff --git a/locales/index.d.ts b/locales/index.d.ts index b0eb81aa7b..a316930c7e 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -12101,6 +12101,10 @@ export interface Locale extends ILocale { * 角度 */ "angle": string; + /** + * 点グリッド + */ + "dottedGrid": string; }; "_imageEffector": { /** @@ -12160,6 +12164,10 @@ export interface Locale extends ILocale { * ストライプ */ "stripe": string; + /** + * 点グリッド + */ + "dottedGrid": string; }; }; } diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 841137c9b5..59d15cb51a 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -3240,6 +3240,7 @@ _watermarkEditor: stripeWidth: "ラインの幅" stripeFrequency: "ラインの数" angle: "角度" + dottedGrid: "点グリッド" _imageEffector: title: "エフェクト" @@ -3258,3 +3259,4 @@ _imageEffector: threshold: "二値化" zoomLines: "集中線" stripe: "ストライプ" + dottedGrid: "点グリッド" diff --git a/packages/frontend/src/utility/image-effector/fxs.ts b/packages/frontend/src/utility/image-effector/fxs.ts index 320e6271e9..d17684d11e 100644 --- a/packages/frontend/src/utility/image-effector/fxs.ts +++ b/packages/frontend/src/utility/image-effector/fxs.ts @@ -7,6 +7,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_dottedGrid } from './fxs/dottedGrid.js'; import { FX_glitch } from './fxs/glitch.js'; import { FX_grayscale } from './fxs/grayscale.js'; import { FX_invert } from './fxs/invert.js'; @@ -30,4 +31,5 @@ export const FXS = [ FX_threshold, FX_zoomLines, FX_stripe, + FX_dottedGrid, ] as const satisfies ImageEffectorFx[]; diff --git a/packages/frontend/src/utility/image-effector/fxs/dottedGrid.ts b/packages/frontend/src/utility/image-effector/fxs/dottedGrid.ts new file mode 100644 index 0000000000..d68db94452 --- /dev/null +++ b/packages/frontend/src/utility/image-effector/fxs/dottedGrid.ts @@ -0,0 +1,151 @@ +/* + * 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; + +const float PI = 3.141592653589793; +const float TWO_PI = 6.283185307179586; +const float HALF_PI = 1.5707963267948966; + +in vec2 in_uv; +uniform sampler2D in_texture; +uniform vec2 in_resolution; +uniform float u_angle; +uniform float u_scale; +uniform float u_major_radius; +uniform float u_major_opacity; +uniform float u_minor_divisions; +uniform float u_minor_radius; +uniform float u_minor_opacity; +uniform bool u_black; +out vec4 out_color; + +void main() { + vec4 in_color = texture(in_texture, in_uv); + float x_ratio = max(in_resolution.x / in_resolution.y, 1.0); + float y_ratio = max(in_resolution.y / in_resolution.x, 1.0); + + float angle = -(u_angle * PI); + vec2 centeredUv = (in_uv - vec2(0.5, 0.5)) * vec2(x_ratio, y_ratio); + vec2 rotatedUV = vec2( + centeredUv.x * cos(angle) - centeredUv.y * sin(angle), + centeredUv.x * sin(angle) + centeredUv.y * cos(angle) + ); + + float major_modX = mod(rotatedUV.x, (1.0 / u_scale)); + float major_modY = mod(rotatedUV.y, (1.0 / u_scale)); + float major_threshold = ((u_major_radius / 2.0) / u_scale); + if ( + length(vec2(major_modX, major_modY)) < major_threshold || + length(vec2((1.0 / u_scale) - major_modX, major_modY)) < major_threshold || + length(vec2(major_modX, (1.0 / u_scale) - major_modY)) < major_threshold || + length(vec2((1.0 / u_scale) - major_modX, (1.0 / u_scale) - major_modY)) < major_threshold + ) { + out_color = vec4( + mix(in_color.r, u_black ? 0.0 : 1.0, u_major_opacity), + mix(in_color.g, u_black ? 0.0 : 1.0, u_major_opacity), + mix(in_color.b, u_black ? 0.0 : 1.0, u_major_opacity), + in_color.a + ); + return; + } + + float minor_modX = mod(rotatedUV.x, (1.0 / u_scale / u_minor_divisions)); + float minor_modY = mod(rotatedUV.y, (1.0 / u_scale / u_minor_divisions)); + float minor_threshold = ((u_minor_radius / 2.0) / (u_minor_divisions * u_scale)); + if ( + length(vec2(minor_modX, minor_modY)) < minor_threshold || + length(vec2((1.0 / u_scale / u_minor_divisions) - minor_modX, minor_modY)) < minor_threshold || + length(vec2(minor_modX, (1.0 / u_scale / u_minor_divisions) - minor_modY)) < minor_threshold || + length(vec2((1.0 / u_scale / u_minor_divisions) - minor_modX, (1.0 / u_scale / u_minor_divisions) - minor_modY)) < minor_threshold + ) { + out_color = vec4( + mix(in_color.r, u_black ? 0.0 : 1.0, u_minor_opacity), + mix(in_color.g, u_black ? 0.0 : 1.0, u_minor_opacity), + mix(in_color.b, u_black ? 0.0 : 1.0, u_minor_opacity), + in_color.a + ); + return; + } + + out_color = in_color; +} +`; + +export const FX_dottedGrid = defineImageEffectorFx({ + id: 'dottedGrid' as const, + name: i18n.ts._imageEffector._fxs.dottedGrid, + shader, + uniforms: ['angle', 'scale', 'major_radius', 'major_opacity', 'minor_divisions', 'minor_radius', 'minor_opacity', 'black'] as const, + params: { + angle: { + type: 'number' as const, + default: 0, + min: -1.0, + max: 1.0, + step: 0.01, + }, + scale: { + type: 'number' as const, + default: 3.0, + min: 1.0, + max: 10.0, + step: 0.1, + }, + majorRadius: { + type: 'number' as const, + default: 0.1, + min: 0.0, + max: 1.0, + step: 0.01, + }, + majorOpacity: { + type: 'number' as const, + default: 0.75, + min: 0.0, + max: 1.0, + step: 0.01, + }, + minorDivisions: { + type: 'number' as const, + default: 4, + min: 0, + max: 16, + step: 1, + }, + minorRadius: { + type: 'number' as const, + default: 0.25, + min: 0.0, + max: 1.0, + step: 0.01, + }, + minorOpacity: { + type: 'number' as const, + default: 0.5, + min: 0.0, + max: 1.0, + step: 0.01, + }, + black: { + type: 'boolean' as const, + default: false, + }, + }, + main: ({ gl, u, params }) => { + gl.uniform1f(u.angle, params.angle / 2); + gl.uniform1f(u.scale, params.scale * params.scale); + gl.uniform1f(u.major_radius, params.majorRadius); + gl.uniform1f(u.major_opacity, params.majorOpacity); + gl.uniform1f(u.minor_divisions, params.minorDivisions); + gl.uniform1f(u.minor_radius, params.minorRadius); + gl.uniform1f(u.minor_opacity, params.minorOpacity); + gl.uniform1i(u.black, params.black ? 1 : 0); + }, +}); diff --git a/packages/frontend/src/utility/image-effector/fxs/stripe.ts b/packages/frontend/src/utility/image-effector/fxs/stripe.ts index 530cc2fe8a..5c4c84dec1 100644 --- a/packages/frontend/src/utility/image-effector/fxs/stripe.ts +++ b/packages/frontend/src/utility/image-effector/fxs/stripe.ts @@ -29,9 +29,13 @@ void main() { float x_ratio = max(in_resolution.x / in_resolution.y, 1.0); float y_ratio = max(in_resolution.y / in_resolution.x, 1.0); - float angle = u_angle * PI; - mat2 rotationMatrix = mat2(cos(angle), -sin(angle), sin(angle), cos(angle)); - vec2 rotatedUV = rotationMatrix * (vec2(in_uv.x * x_ratio, in_uv.y * y_ratio) - 0.5); + float angle = -(u_angle * PI); + vec2 centeredUv = (in_uv - vec2(0.5, 0.5)) * vec2(x_ratio, y_ratio); + vec2 rotatedUV = vec2( + centeredUv.x * cos(angle) - centeredUv.y * sin(angle), + centeredUv.x * sin(angle) + centeredUv.y * cos(angle) + ); + float phase = u_phase * TWO_PI; float value = (1.0 + sin((rotatedUV.x * u_frequency - HALF_PI) + phase)) / 2.0; value = value < u_threshold ? 1.0 : 0.0; diff --git a/packages/frontend/src/utility/image-effector/fxs/watermarkPlacement.ts b/packages/frontend/src/utility/image-effector/fxs/watermarkPlacement.ts index faeaf61d54..1c1c95b0c5 100644 --- a/packages/frontend/src/utility/image-effector/fxs/watermarkPlacement.ts +++ b/packages/frontend/src/utility/image-effector/fxs/watermarkPlacement.ts @@ -28,6 +28,8 @@ out vec4 out_color; void main() { vec4 in_color = texture(in_texture, in_uv); + float in_x_ratio = max(in_resolution.x / in_resolution.y, 1.0); + float in_y_ratio = max(in_resolution.y / in_resolution.x, 1.0); bool contain = u_fitMode == 0; @@ -51,12 +53,11 @@ void main() { float angle = -(u_angle * PI); vec2 center = vec2(x_offset, y_offset); - vec2 centeredUv = in_uv - center; - float cosAngle = cos(angle); - float sinAngle = sin(angle); + //vec2 centeredUv = (in_uv - center) * vec2(in_x_ratio, in_y_ratio); + vec2 centeredUv = (in_uv - center); vec2 rotatedUV = vec2( - centeredUv.x * cosAngle - centeredUv.y * sinAngle, - centeredUv.x * sinAngle + centeredUv.y * cosAngle + centeredUv.x * cos(angle) - centeredUv.y * sin(angle), + centeredUv.x * sin(angle) + centeredUv.y * cos(angle) ) + center; // trim