diff --git a/locales/index.d.ts b/locales/index.d.ts index b05cda5c11..ff2019e871 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -12071,6 +12071,10 @@ export interface Locale extends ILocale { * エフェクト */ "title": string; + /** + * エフェクトを追加 + */ + "addEffect": string; "_fxs": { /** * 色収差 @@ -12084,6 +12088,10 @@ export interface Locale extends ILocale { * ミラー */ "mirror": string; + /** + * 色の反転 + */ + "invert": string; }; }; } diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 313dc6aa68..ad62d74c66 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -3234,8 +3234,10 @@ _watermarkEditor: _imageEffector: title: "エフェクト" + addEffect: "エフェクトを追加" _fxs: chromaticAberration: "色収差" glitch: "グリッチ" mirror: "ミラー" + invert: "色の反転" diff --git a/packages/frontend/src/components/MkImageEffectorDialog.vue b/packages/frontend/src/components/MkImageEffectorDialog.vue index e91c2be04f..a7c593f1b6 100644 --- a/packages/frontend/src/components/MkImageEffectorDialog.vue +++ b/packages/frontend/src/components/MkImageEffectorDialog.vue @@ -26,15 +26,17 @@ SPDX-License-Identifier: AGPL-3.0-only -
- +
+
+ - + {{ i18n.ts._imageEffector.addEffect }} +
@@ -212,7 +214,6 @@ function save() { } .controls { - padding: 24px; overflow-y: scroll; } diff --git a/packages/frontend/src/components/MkWatermarkEditorDialog.vue b/packages/frontend/src/components/MkWatermarkEditorDialog.vue index 07fe0c45e2..e7659405d3 100644 --- a/packages/frontend/src/components/MkWatermarkEditorDialog.vue +++ b/packages/frontend/src/components/MkWatermarkEditorDialog.vue @@ -28,14 +28,16 @@ SPDX-License-Identifier: AGPL-3.0-only -
- +
+
+ - + +
@@ -284,7 +286,6 @@ async function save() { } .controls { - padding: 24px; overflow-y: scroll; } diff --git a/packages/frontend/src/utility/image-effector/ImageEffector.ts b/packages/frontend/src/utility/image-effector/ImageEffector.ts index dca61632e8..d80f921097 100644 --- a/packages/frontend/src/utility/image-effector/ImageEffector.ts +++ b/packages/frontend/src/utility/image-effector/ImageEffector.ts @@ -6,6 +6,7 @@ import { getProxiedImageUrl } from '../media-proxy.js'; import { FX_chromaticAberration } from './fxs/chromaticAberration.js'; import { FX_glitch } from './fxs/glitch.js'; +import { FX_invert } from './fxs/invert.js'; import { FX_mirror } from './fxs/mirror.js'; import { FX_watermarkPlacement } from './fxs/watermarkPlacement.js'; @@ -53,6 +54,7 @@ export const FXS = [ FX_chromaticAberration, FX_glitch, FX_mirror, + FX_invert, ] as const satisfies ImageEffectorFx[]; export type ImageEffectorLayerOf< @@ -134,7 +136,7 @@ export class ImageEffector { gl_Position = vec4(position, 0.0, 1.0); } `, `#version 300 es - precision highp float; + precision mediump float; in vec2 in_uv; uniform sampler2D u_texture; @@ -155,7 +157,7 @@ export class ImageEffector { gl_Position = vec4(position, 0.0, 1.0); } `, `#version 300 es - precision highp float; + precision mediump float; in vec2 in_uv; uniform sampler2D u_texture; diff --git a/packages/frontend/src/utility/image-effector/fxs/chromaticAberration.ts b/packages/frontend/src/utility/image-effector/fxs/chromaticAberration.ts index 70811c7b95..09109ac79f 100644 --- a/packages/frontend/src/utility/image-effector/fxs/chromaticAberration.ts +++ b/packages/frontend/src/utility/image-effector/fxs/chromaticAberration.ts @@ -7,7 +7,7 @@ import { defineImageEffectorFx } from '../ImageEffector.js'; import { i18n } from '@/i18n.js'; const shader = `#version 300 es -precision highp float; +precision mediump float; in vec2 in_uv; uniform sampler2D u_texture; diff --git a/packages/frontend/src/utility/image-effector/fxs/glitch.ts b/packages/frontend/src/utility/image-effector/fxs/glitch.ts index 437601e592..b6a26b2a8a 100644 --- a/packages/frontend/src/utility/image-effector/fxs/glitch.ts +++ b/packages/frontend/src/utility/image-effector/fxs/glitch.ts @@ -8,7 +8,7 @@ import { defineImageEffectorFx } from '../ImageEffector.js'; import { i18n } from '@/i18n.js'; const shader = `#version 300 es -precision highp float; +precision mediump float; in vec2 in_uv; uniform sampler2D u_texture; diff --git a/packages/frontend/src/utility/image-effector/fxs/invert.ts b/packages/frontend/src/utility/image-effector/fxs/invert.ts new file mode 100644 index 0000000000..52fb093622 --- /dev/null +++ b/packages/frontend/src/utility/image-effector/fxs/invert.ts @@ -0,0 +1,70 @@ +/* + * 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 bool u_r; +uniform bool u_g; +uniform bool u_b; +uniform bool u_a; +out vec4 out_color; + +void main() { + vec4 in_color = texture(u_texture, in_uv); + out_color.r = u_r ? 1.0 - in_color.r : in_color.r; + out_color.g = u_g ? 1.0 - in_color.g : in_color.g; + out_color.b = u_b ? 1.0 - in_color.b : in_color.b; + out_color.a = u_a ? 1.0 - in_color.a : in_color.a; +} +`; + +export const FX_invert = defineImageEffectorFx({ + id: 'invert' as const, + name: i18n.ts._imageEffector._fxs.invert, + shader, + params: { + r: { + type: 'boolean' as const, + default: true, + }, + g: { + type: 'boolean' as const, + default: true, + }, + b: { + type: 'boolean' as const, + default: true, + }, + a: { + type: 'boolean' as const, + default: false, + }, + }, + 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_r = gl.getUniformLocation(program, 'u_r'); + gl.uniform1i(u_r, params.r ? 1 : 0); + + const u_g = gl.getUniformLocation(program, 'u_g'); + gl.uniform1i(u_g, params.g ? 1 : 0); + + const u_b = gl.getUniformLocation(program, 'u_b'); + gl.uniform1i(u_b, params.b ? 1 : 0); + + const u_a = gl.getUniformLocation(program, 'u_a'); + gl.uniform1i(u_a, params.a ? 1 : 0); + }, +}); diff --git a/packages/frontend/src/utility/image-effector/fxs/mirror.ts b/packages/frontend/src/utility/image-effector/fxs/mirror.ts index 5083d17eab..6d273073d4 100644 --- a/packages/frontend/src/utility/image-effector/fxs/mirror.ts +++ b/packages/frontend/src/utility/image-effector/fxs/mirror.ts @@ -7,7 +7,7 @@ import { defineImageEffectorFx } from '../ImageEffector.js'; import { i18n } from '@/i18n.js'; const shader = `#version 300 es -precision highp float; +precision mediump float; in vec2 in_uv; uniform sampler2D u_texture; @@ -17,7 +17,6 @@ uniform int u_v; out vec4 out_color; void main() { - vec4 pixel = texture(u_texture, in_uv); vec2 uv = in_uv; if (u_h == -1 && in_uv.x > 0.5) { uv.x = 1.0 - uv.x; diff --git a/packages/frontend/src/utility/image-effector/fxs/watermarkPlacement.ts b/packages/frontend/src/utility/image-effector/fxs/watermarkPlacement.ts index 00e3f339a2..9f500aea83 100644 --- a/packages/frontend/src/utility/image-effector/fxs/watermarkPlacement.ts +++ b/packages/frontend/src/utility/image-effector/fxs/watermarkPlacement.ts @@ -6,7 +6,7 @@ import { defineImageEffectorFx } from '../ImageEffector.js'; const shader = `#version 300 es -precision highp float; +precision mediump float; in vec2 in_uv; uniform sampler2D u_texture_src; @@ -23,7 +23,7 @@ uniform int u_fitMode; // 0: contain, 1: cover out vec4 out_color; void main() { - vec4 pixel = texture(u_texture_src, in_uv); + vec4 in_color = texture(u_texture_src, in_uv); bool contain = u_fitMode == 0; @@ -49,25 +49,26 @@ void main() { bool isInside = in_uv.x > x_offset - (x_scale / 2.0) && in_uv.x < x_offset + (x_scale / 2.0) && in_uv.y > y_offset - (y_scale / 2.0) && in_uv.y < y_offset + (y_scale / 2.0); if (!isInside) { - out_color = pixel; + out_color = in_color; return; } } - vec4 watermarkPixel = texture(u_texture_watermark, vec2( + vec4 watermark_color = texture(u_texture_watermark, vec2( (in_uv.x - (x_offset - (x_scale / 2.0))) / x_scale, (in_uv.y - (y_offset - (y_scale / 2.0))) / y_scale )); - out_color.r = mix(pixel.r, watermarkPixel.r, u_opacity * watermarkPixel.a); - out_color.g = mix(pixel.g, watermarkPixel.g, u_opacity * watermarkPixel.a); - out_color.b = mix(pixel.b, watermarkPixel.b, u_opacity * watermarkPixel.a); - out_color.a = pixel.a * (1.0 - u_opacity * watermarkPixel.a) + watermarkPixel.a * u_opacity; + out_color.r = mix(in_color.r, watermark_color.r, u_opacity * watermark_color.a); + out_color.g = mix(in_color.g, watermark_color.g, u_opacity * watermark_color.a); + out_color.b = mix(in_color.b, watermark_color.b, u_opacity * watermark_color.a); + out_color.a = in_color.a * (1.0 - u_opacity * watermark_color.a) + watermark_color.a * u_opacity; } `; export const FX_watermarkPlacement = defineImageEffectorFx({ id: 'watermarkPlacement' as const, + name: '(internal)', shader, params: { cover: { diff --git a/packages/frontend/src/utility/snowfall-effect.ts b/packages/frontend/src/utility/snowfall-effect.ts index 5c86969876..65398e6a43 100644 --- a/packages/frontend/src/utility/snowfall-effect.ts +++ b/packages/frontend/src/utility/snowfall-effect.ts @@ -38,7 +38,7 @@ export class SnowfallEffect { `; private FRAGMENT_SOURCE = `#version 300 es - precision highp float; + precision mediump float; in vec4 v_color; in float v_rotation;