我正在尝试创建一个稍微有效的函数来渲染圆。我尝试使用中点算法逐像素绘制像素,但这太慢了。因此,经过一些研究,我选择创建纹理,锁定它并操纵它的像素。问题是我似乎无法获得正确的颜色。这是我想到的:
pub fn fill_circle(&mut self, center: impl Into<Vector2>, radius: impl ToF32) {
let center = center.into();
let r = radius.to_f32();
let d = r * 2.0;
let color = self.canvas.draw_color();
let mut texture = unsafe {
TEXTURE_CREATOR
.get()
.unwrap()
.create_texture_streaming(PixelFormatEnum::RGBA8888, d as u32, d as u32)
.unwrap()
};
texture.set_blend_mode(sdl2::render::BlendMode::Blend);
texture
.with_lock(None, |buffer, pitch| {
for x in 0..d as usize {
for y in 0..d as usize {
let circle_v = (x as f32 - r) * (x as f32 - r)
+ (y as f32 - r) * (y as f32 - r)
- r * r;
let i = y * pitch + x * 4;
if circle_v <= 0.0 {
buffer[i] = color.r;
buffer[i + 1] = color.g;
buffer[i + 2] = color.b;
buffer[i + 3] = color.a;
}
}
}
})
.expect("Failed to lock texture");
let target_rect = FRect::new(center.x - r, center.y - r, d, d);
self.canvas
.copy_f(&texture, None, Some(target_rect))
.unwrap();
unsafe { texture.destroy() };
}
忽略
unsafe
块,我只是在制作原型。但是当在缓冲区数组中设置颜色时,颜色就不正确。例如,如果我将绘制颜色设置为青色(r:0,g:255,b:255,a:255),则圆圈为白色,如果我设置洋红色,则为黄色。
问题是我没有检查字节序。由于我的系统使用little endian字节顺序,所以如果little -> abgr,big -> rgba。
这是纹理锁定回调:
texture
.with_lock(None, |buffer, pitch| {
for x in 0..d as usize {
for y in 0..d as usize {
let circle_v = (x as f32 - r) * (x as f32 - r)
+ (y as f32 - r) * (y as f32 - r)
- r * r;
let i = y * pitch + x * 4;
if circle_v <= 0.0 {
#[cfg(target_endian = "little")]
{
buffer[i] = color.a;
buffer[i + 1] = color.b;
buffer[i + 2] = color.g;
buffer[i + 3] = color.r;
}
#[cfg(target_endian = "big")]
{
buffer[i] = color.r;
buffer[i + 1] = color.g;
buffer[i + 2] = color.b;
buffer[i + 3] = color.a;
}
}
}
}
})
.expect("Failed to lock texture");