2个版本
0.1.1 | 2024年7月26日 |
---|---|
0.1.0 | 2024年7月26日 |
#41 in 渲染
每月下载 257次
415KB
50 行
softbuffer-rgb
softbuffer-rgb
是 softbuffer
的包装器,它使修改原始像素缓冲区变得更容易。
而不是这样做
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