#framebuffer #windowing #softbuffer

softbuffer-rgb

softbuffer的包装器,使修改原始像素缓冲区更容易

2个版本

0.1.1 2024年7月26日
0.1.0 2024年7月26日

#41 in 渲染

Download history 105/week @ 2024-07-20 152/week @ 2024-07-27

每月下载 257次

MIT 许可证

415KB
50

softbuffer-rgb

softbuffer-rgbsoftbuffer 的包装器,它使修改原始像素缓冲区变得更容易。

而不是这样做

buffer.buffer_mut()[y * width + x] = u32::from_le_bytes([0, 200, 70, 10]);

...现在你可以这样做

buffer.pixels[y][x] = [0, 200, 70, 10];

问题

softbuffer 将像素数据存储在一个 u32 缓冲区中,其中每个 u32 是一个 "0RGB" 颜色。第一个字节始终为零,第二个字节是红色,第三个字节是绿色,第四个字节是蓝色。

将颜色存储为数组,如这样

let color = [0, 200, 70, 10];

softbuffer 中,颜色需要是 u32

let color = u32::from_le_bytes([0, 200, 70, 10]);

此外,softbuffer 缓冲区是一维的。通常,你会在二维(x,y)坐标系中编程,这意味着你必须将二维(x,y)坐标转换为索引。这是一个廉价的操作,但如果每个帧你必须为许多像素这样做,性能成本可能会增加!

解决方案

softbuffer-rgb 使用一点不安全的代码来重新排列原始缓冲区数据,形成一个三维数组:(width, height, 0RGB)。修改此 pixels 数组将修改底层 u32 缓冲区数组,反之亦然。

因此

  • softbuffer-rgb 比使用 softbuffer 更容易使用。
  • softbuffer-rgb 可以稍微快一些,因为您不需要将它们转换为 u32,也不需要将(x,y)坐标转换为索引。

注意

softbuffer-rgb 依赖于泛型常量来定义 pixels 的大小,这意味着缓冲区大小必须在编译时已知。

示例

use softbuffer::{Context, Surface};
use std::num::NonZeroU32;
use winit::application::ApplicationHandler;
use winit::dpi::LogicalSize;
use winit::event::{StartCause, WindowEvent};
use winit::event_loop::{ActiveEventLoop, EventLoop};
use winit::window::{Window, WindowAttributes, WindowId};

use softbuffer_rgb::RgbBuffer;

const X: usize = 400;
const Y: usize = 300;

fn main() {
   let mut app = App::default();
   let event_loop = EventLoop::new().unwrap();
   event_loop.run_app(&mut app).unwrap();
}

#[derive(Default)]
struct App {
   window: Option<Window>,
}

impl ApplicationHandler for App {
   fn resumed(&mut self, _: &ActiveEventLoop) {}

   fn new_events(&mut self, event_loop: &ActiveEventLoop, cause: StartCause) {
       if let StartCause::Init = cause {
           let window_attributes =
               WindowAttributes::default().with_inner_size(LogicalSize::new(X as u32, Y as u32));
           // Create the window.
           self.window = Some(event_loop.create_window(window_attributes).unwrap());
           // Get the window.
           let window = self.window.as_ref().unwrap();
           let context = Context::new(window).unwrap();
           let mut surface = Surface::new(&context, &window).unwrap();
           surface
               .resize(
                   NonZeroU32::new(X as u32).unwrap(),
                   NonZeroU32::new(Y as u32).unwrap(),
               )
               .unwrap();
           let mut rgb_buffer =
               RgbBuffer::<X, Y, _, _>::from_softbuffer(surface.buffer_mut().unwrap()).unwrap();
           let x = 12;
           let y = 23;
           rgb_buffer.pixels[y][x] = [0, 200, 100, 70];
           event_loop.exit();
       }
   }

   fn window_event(&mut self, _: &ActiveEventLoop, _: WindowId, _: WindowEvent) {}
}

依赖项

~0.3–9.5MB
~87K SLoC