From 317ebb958bdca56063d56f4900e58ed80cbcc3aa Mon Sep 17 00:00:00 2001 From: Roman Pytkov Date: Wed, 25 Feb 2026 22:37:52 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A3=D0=B1=D1=80=D0=B0=D0=BD=D0=BE=20=D0=BB?= =?UTF-8?q?=D0=B8=D1=88=D0=BD=D0=B5=D0=B5=20=D1=83=D0=BC=D0=BD=D0=BE=D0=B6?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BD=D0=B0=20Alpha?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/render/cpu/pipeline.zig | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/render/cpu/pipeline.zig b/src/render/cpu/pipeline.zig index 49f3c0b..44817a4 100644 --- a/src/render/cpu/pipeline.zig +++ b/src/render/cpu/pipeline.zig @@ -112,16 +112,17 @@ pub const DrawContext = struct { }; } - /// Смешивает цвет в пикселе буфера (bx, by) с учётом opacity текущего трансформа. Bounds не проверяются. + /// Смешивает цвет в пикселе буфера (bx, by). color уже в PMA; opacity трансформа применяется к альфе и к RGB. pub fn blendPixelAtBuffer(self: *DrawContext, bx: u32, by: u32, color: Color.PMA) void { if (bx >= self.buf_width or by >= self.buf_height) return; const t = &self.transform; const idx = by * self.buf_width + bx; const dst = &self.pixels[idx]; const a = @as(f32, @floatFromInt(color.a)) / 255.0 * t.opacity; - const src_r = @as(f32, @floatFromInt(color.r)) * a; - const src_g = @as(f32, @floatFromInt(color.g)) * a; - const src_b = @as(f32, @floatFromInt(color.b)) * a; + // PMA: color.r/g/b уже помножены на color.a; при opacity только масштабируем их на t.opacity + const src_r = @as(f32, @floatFromInt(color.r)) * t.opacity; + const src_g = @as(f32, @floatFromInt(color.g)) * t.opacity; + const src_b = @as(f32, @floatFromInt(color.b)) * t.opacity; const inv_a = 1.0 - a; dst.r = @intFromFloat(std.math.clamp(src_r + inv_a * @as(f32, @floatFromInt(dst.r)), 0, 255)); dst.g = @intFromFloat(std.math.clamp(src_g + inv_a * @as(f32, @floatFromInt(dst.g)), 0, 255));