Дополнительный буфер для отрисовки broken line

This commit is contained in:
2026-02-26 13:48:42 +03:00
parent 0eee436150
commit 05f5481a42
4 changed files with 59 additions and 11 deletions

View File

@@ -45,6 +45,8 @@ pub const DrawContext = struct {
scale_x: f32,
scale_y: f32,
transform: Transform = .{},
/// Если true, blendPixelAtBuffer перезаписывает пиксель без бленда
replace_mode: bool = false,
pub fn setTransform(self: *DrawContext, t: Transform) void {
self.transform = t;
@@ -111,12 +113,16 @@ pub const DrawContext = struct {
};
}
/// Смешивает цвет в пикселе буфера с учётом opacity трансформа.
/// Смешивает цвет в пикселе буфера с учётом opacity трансформа. В replace_mode просто перезаписывает пиксель.
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];
if (self.replace_mode) {
dst.* = color;
return;
}
const t = &self.transform;
const a = @as(f32, @floatFromInt(color.a)) / 255.0 * t.opacity;
const src_r = @as(f32, @floatFromInt(color.r)) * t.opacity;
const src_g = @as(f32, @floatFromInt(color.g)) * t.opacity;
@@ -128,6 +134,26 @@ pub const DrawContext = struct {
dst.a = @intFromFloat(std.math.clamp(a * 255 + inv_a * @as(f32, @floatFromInt(dst.a)), 0, 255));
}
/// Накладывает буфер другого контекста на этот с заданной прозрачностью (один бленд на пиксель). Размеры буферов должны совпадать.
pub fn compositeDrawerContext(self: *DrawContext, other: *const DrawContext, opacity: f32) void {
if (self.buf_width != other.buf_width or self.buf_height != other.buf_height) return;
const n = self.buf_width * self.buf_height;
for (0..n) |i| {
const src = other.pixels[i];
if (src.a == 0) continue;
const dst = &self.pixels[i];
const a = @as(f32, @floatFromInt(src.a)) / 255.0 * opacity;
const src_r = @as(f32, @floatFromInt(src.r)) * opacity;
const src_g = @as(f32, @floatFromInt(src.g)) * opacity;
const src_b = @as(f32, @floatFromInt(src.b)) * 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));
dst.b = @intFromFloat(std.math.clamp(src_b + inv_a * @as(f32, @floatFromInt(dst.b)), 0, 255));
dst.a = @intFromFloat(std.math.clamp(a * 255 + inv_a * @as(f32, @floatFromInt(dst.a)), 0, 255));
}
}
/// Пиксель в локальных координатах (трансформ + PMA).
pub fn blendPixelLocal(self: *DrawContext, local_x: f32, local_y: f32, color: Color.PMA) void {
const w = self.localToWorld(local_x, local_y);