wip
This commit is contained in:
parent
a2e391d6e4
commit
7627017a42
|
@ -29,6 +29,16 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<template #label>{{ i18n.ts._watermarkEditor.scale }}</template>
|
<template #label>{{ i18n.ts._watermarkEditor.scale }}</template>
|
||||||
</MkRange>
|
</MkRange>
|
||||||
|
|
||||||
|
<MkRange
|
||||||
|
v-model="layer.angle"
|
||||||
|
:min="-1"
|
||||||
|
:max="1"
|
||||||
|
:step="0.01"
|
||||||
|
continuousUpdate
|
||||||
|
>
|
||||||
|
<template #label>{{ i18n.ts._watermarkEditor.angle }}</template>
|
||||||
|
</MkRange>
|
||||||
|
|
||||||
<MkRange
|
<MkRange
|
||||||
v-model="layer.opacity"
|
v-model="layer.opacity"
|
||||||
:min="0"
|
:min="0"
|
||||||
|
@ -66,6 +76,16 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<template #label>{{ i18n.ts._watermarkEditor.scale }}</template>
|
<template #label>{{ i18n.ts._watermarkEditor.scale }}</template>
|
||||||
</MkRange>
|
</MkRange>
|
||||||
|
|
||||||
|
<MkRange
|
||||||
|
v-model="layer.angle"
|
||||||
|
:min="-1"
|
||||||
|
:max="1"
|
||||||
|
:step="0.01"
|
||||||
|
continuousUpdate
|
||||||
|
>
|
||||||
|
<template #label>{{ i18n.ts._watermarkEditor.angle }}</template>
|
||||||
|
</MkRange>
|
||||||
|
|
||||||
<MkRange
|
<MkRange
|
||||||
v-model="layer.opacity"
|
v-model="layer.opacity"
|
||||||
:min="0"
|
:min="0"
|
||||||
|
|
|
@ -94,6 +94,7 @@ function createTextLayer(): WatermarkPreset['layers'][number] {
|
||||||
text: `(c) @${$i.username}`,
|
text: `(c) @${$i.username}`,
|
||||||
align: { x: 'right', y: 'bottom' },
|
align: { x: 'right', y: 'bottom' },
|
||||||
scale: 0.3,
|
scale: 0.3,
|
||||||
|
angle: 0,
|
||||||
opacity: 0.75,
|
opacity: 0.75,
|
||||||
repeat: false,
|
repeat: false,
|
||||||
};
|
};
|
||||||
|
@ -107,6 +108,7 @@ function createImageLayer(): WatermarkPreset['layers'][number] {
|
||||||
imageUrl: null,
|
imageUrl: null,
|
||||||
align: { x: 'right', y: 'bottom' },
|
align: { x: 'right', y: 'bottom' },
|
||||||
scale: 0.3,
|
scale: 0.3,
|
||||||
|
angle: 0,
|
||||||
opacity: 0.75,
|
opacity: 0.75,
|
||||||
repeat: false,
|
repeat: false,
|
||||||
cover: false,
|
cover: false,
|
||||||
|
|
|
@ -8,6 +8,10 @@ import { defineImageEffectorFx } from '../ImageEffector.js';
|
||||||
const shader = `#version 300 es
|
const shader = `#version 300 es
|
||||||
precision mediump float;
|
precision mediump float;
|
||||||
|
|
||||||
|
const float PI = 3.141592653589793;
|
||||||
|
const float TWO_PI = 6.283185307179586;
|
||||||
|
const float HALF_PI = 1.5707963267948966;
|
||||||
|
|
||||||
in vec2 in_uv;
|
in vec2 in_uv;
|
||||||
uniform sampler2D in_texture;
|
uniform sampler2D in_texture;
|
||||||
uniform vec2 in_resolution;
|
uniform vec2 in_resolution;
|
||||||
|
@ -45,9 +49,20 @@ void main() {
|
||||||
float x_offset = u_alignX == 0 ? x_scale / 2.0 : u_alignX == 2 ? 1.0 - (x_scale / 2.0) : 0.5;
|
float x_offset = u_alignX == 0 ? x_scale / 2.0 : u_alignX == 2 ? 1.0 - (x_scale / 2.0) : 0.5;
|
||||||
float y_offset = u_alignY == 0 ? y_scale / 2.0 : u_alignY == 2 ? 1.0 - (y_scale / 2.0) : 0.5;
|
float y_offset = u_alignY == 0 ? y_scale / 2.0 : u_alignY == 2 ? 1.0 - (y_scale / 2.0) : 0.5;
|
||||||
|
|
||||||
|
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 rotatedUV = vec2(
|
||||||
|
centeredUv.x * cosAngle - centeredUv.y * sinAngle,
|
||||||
|
centeredUv.x * sinAngle + centeredUv.y * cosAngle
|
||||||
|
) + center;
|
||||||
|
|
||||||
|
// trim
|
||||||
if (!u_repeat) {
|
if (!u_repeat) {
|
||||||
bool isInside = in_uv.x > x_offset - (x_scale / 2.0) && in_uv.x < x_offset + (x_scale / 2.0) &&
|
bool isInside = rotatedUV.x > x_offset - (x_scale / 2.0) && rotatedUV.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);
|
rotatedUV.y > y_offset - (y_scale / 2.0) && rotatedUV.y < y_offset + (y_scale / 2.0);
|
||||||
if (!isInside) {
|
if (!isInside) {
|
||||||
out_color = in_color;
|
out_color = in_color;
|
||||||
return;
|
return;
|
||||||
|
@ -55,8 +70,8 @@ void main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
vec4 watermark_color = texture(u_texture_watermark, vec2(
|
vec4 watermark_color = texture(u_texture_watermark, vec2(
|
||||||
(in_uv.x - (x_offset - (x_scale / 2.0))) / x_scale,
|
(rotatedUV.x - (x_offset - (x_scale / 2.0))) / x_scale,
|
||||||
(in_uv.y - (y_offset - (y_scale / 2.0))) / y_scale
|
(rotatedUV.y - (y_offset - (y_scale / 2.0))) / y_scale
|
||||||
));
|
));
|
||||||
|
|
||||||
out_color.r = mix(in_color.r, watermark_color.r, u_opacity * watermark_color.a);
|
out_color.r = mix(in_color.r, watermark_color.r, u_opacity * watermark_color.a);
|
||||||
|
@ -87,6 +102,13 @@ export const FX_watermarkPlacement = defineImageEffectorFx({
|
||||||
max: 1.0,
|
max: 1.0,
|
||||||
step: 0.01,
|
step: 0.01,
|
||||||
},
|
},
|
||||||
|
angle: {
|
||||||
|
type: 'number' as const,
|
||||||
|
default: 0,
|
||||||
|
min: -1.0,
|
||||||
|
max: 1.0,
|
||||||
|
step: 0.01,
|
||||||
|
},
|
||||||
align: {
|
align: {
|
||||||
type: 'align' as const,
|
type: 'align' as const,
|
||||||
default: { x: 'right', y: 'bottom' },
|
default: { x: 'right', y: 'bottom' },
|
||||||
|
@ -114,8 +136,9 @@ export const FX_watermarkPlacement = defineImageEffectorFx({
|
||||||
|
|
||||||
gl.uniform2fv(u.resolution_watermark, [textures.watermark.width, textures.watermark.height]);
|
gl.uniform2fv(u.resolution_watermark, [textures.watermark.width, textures.watermark.height]);
|
||||||
gl.uniform1f(u.scale, params.scale);
|
gl.uniform1f(u.scale, params.scale);
|
||||||
|
|
||||||
gl.uniform1f(u.opacity, params.opacity);
|
gl.uniform1f(u.opacity, params.opacity);
|
||||||
gl.uniform1f(u.angle, 0.0);
|
gl.uniform1f(u.angle, params.angle);
|
||||||
gl.uniform1i(u.repeat, params.repeat ? 1 : 0);
|
gl.uniform1i(u.repeat, params.repeat ? 1 : 0);
|
||||||
gl.uniform1i(u.alignX, params.align.x === 'left' ? 0 : params.align.x === 'right' ? 2 : 1);
|
gl.uniform1i(u.alignX, params.align.x === 'left' ? 0 : params.align.x === 'right' ? 2 : 1);
|
||||||
gl.uniform1i(u.alignY, params.align.y === 'top' ? 0 : params.align.y === 'bottom' ? 2 : 1);
|
gl.uniform1i(u.alignY, params.align.y === 'top' ? 0 : params.align.y === 'bottom' ? 2 : 1);
|
||||||
|
|
|
@ -17,6 +17,7 @@ export type WatermarkPreset = {
|
||||||
text: string;
|
text: string;
|
||||||
repeat: boolean;
|
repeat: boolean;
|
||||||
scale: number;
|
scale: number;
|
||||||
|
angle: number;
|
||||||
align: { x: 'left' | 'center' | 'right'; y: 'top' | 'center' | 'bottom' };
|
align: { x: 'left' | 'center' | 'right'; y: 'top' | 'center' | 'bottom' };
|
||||||
opacity: number;
|
opacity: number;
|
||||||
} | {
|
} | {
|
||||||
|
@ -27,6 +28,7 @@ export type WatermarkPreset = {
|
||||||
cover: boolean;
|
cover: boolean;
|
||||||
repeat: boolean;
|
repeat: boolean;
|
||||||
scale: number;
|
scale: number;
|
||||||
|
angle: number;
|
||||||
align: { x: 'left' | 'center' | 'right'; y: 'top' | 'center' | 'bottom' };
|
align: { x: 'left' | 'center' | 'right'; y: 'top' | 'center' | 'bottom' };
|
||||||
opacity: number;
|
opacity: number;
|
||||||
} | {
|
} | {
|
||||||
|
@ -69,6 +71,7 @@ export class WatermarkRenderer {
|
||||||
repeat: layer.repeat,
|
repeat: layer.repeat,
|
||||||
scale: layer.scale,
|
scale: layer.scale,
|
||||||
align: layer.align,
|
align: layer.align,
|
||||||
|
angle: layer.angle,
|
||||||
opacity: layer.opacity,
|
opacity: layer.opacity,
|
||||||
cover: false,
|
cover: false,
|
||||||
watermark: {
|
watermark: {
|
||||||
|
@ -85,6 +88,7 @@ export class WatermarkRenderer {
|
||||||
repeat: layer.repeat,
|
repeat: layer.repeat,
|
||||||
scale: layer.scale,
|
scale: layer.scale,
|
||||||
align: layer.align,
|
align: layer.align,
|
||||||
|
angle: layer.angle,
|
||||||
opacity: layer.opacity,
|
opacity: layer.opacity,
|
||||||
cover: layer.cover,
|
cover: layer.cover,
|
||||||
watermark: {
|
watermark: {
|
||||||
|
|
Loading…
Reference in New Issue