加入3.5 修复水印

This commit is contained in:
tianmo committed 2026-09-10 18:51:29 +08:00
1 parent ef01cdd6ee
commit e82a62a9ad
19 files changed
+5894 -38

No files matched your search

+18 -5
View File
@@ -45,12 +45,12 @@ function createRasterizer(context) {
const position = gl.getAttribLocation(program, 'position'), uv = gl.getAttribLocation(program, 'uv');
const resolution = gl.getUniformLocation(program, 'resolution'), opacity = gl.getUniformLocation(program, 'opacity');
const textures = new Map();
let coordinates = [], currentImage = null, currentAlpha = 1, transform;
let coordinates = [], currentImage = null, currentAlpha = 1, currentMode = 'source-over', transform;
let disposed = false, lost = false;
canvas.addEventListener('webglcontextlost', event => { event.preventDefault(); lost = true; });
function texture(image) {
if (textures.has(image)) return textures.get(image);
const t = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, t);
if (textures.has(image) && image !== context.canvas) return textures.get(image);
const t = textures.get(image) || gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, t);
// Premultiply before interpolation so translucent edges do not darken.
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
@@ -65,6 +65,12 @@ function createRasterizer(context) {
if (!coordinates.length) return;
gl.bindTexture(gl.TEXTURE_2D, texture(currentImage));
gl.uniform1f(opacity, currentAlpha);
// Premultiplied RGB factors; keep source-over alpha independently.
const factors = currentMode === 'lighter' ? [gl.ONE, gl.ONE]
: currentMode === 'multiply' ? [gl.DST_COLOR, gl.ONE_MINUS_SRC_ALPHA]
: currentMode === 'screen' ? [gl.ONE, gl.ONE_MINUS_SRC_COLOR]
: [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
gl.blendFuncSeparate(factors[0], factors[1], gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(coordinates), gl.STREAM_DRAW);
gl.drawArrays(gl.TRIANGLES, 0, coordinates.length / 4);
coordinates.length = 0;
@@ -84,11 +90,18 @@ function createRasterizer(context) {
gl.uniform2f(resolution, canvas.width, canvas.height);
gl.activeTexture(gl.TEXTURE0); gl.uniform1i(gl.getUniformLocation(program, 'image'), 0);
gl.enable(gl.BLEND); gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
// Seed the same framebuffer with the actual Canvas pixels (solid or
// checkerboard background). CSS backgrounds cannot participate in blending.
currentImage = target; currentAlpha = 1; currentMode = 'source-over';
const w = canvas.width, h = canvas.height;
coordinates.push(0,0,0,0, w,0,1,0, w,h,1,1, 0,0,0,0, w,h,1,1, 0,h,0,1);
flush(); currentImage = null;
return true;
},
triangle(image, x0, y0, u0, v0, x1, y1, u1, v1, x2, y2, u2, v2) {
const alpha = context.globalAlpha;
if (image !== currentImage || alpha !== currentAlpha) { flush(); currentImage = image; currentAlpha = alpha; }
const mode = context.globalCompositeOperation || 'source-over';
if (image !== currentImage || alpha !== currentAlpha || mode !== currentMode) { flush(); currentImage = image; currentAlpha = alpha; currentMode = mode; }
const t = transform;
coordinates.push(
t.a * x0 + t.c * y0 + t.e, t.b * x0 + t.d * y0 + t.f, u0, v0,
@@ -98,7 +111,7 @@ function createRasterizer(context) {
end() {
flush();
context.save();
try { context.setTransform(1, 0, 0, 1, 0, 0); context.globalAlpha = 1; context.drawImage(canvas, 0, 0); }
try { context.setTransform(1, 0, 0, 1, 0, 0); context.globalAlpha = 1; context.globalCompositeOperation = 'copy'; context.drawImage(canvas, 0, 0); }
finally { context.restore(); }
},
dispose() {