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;