I am trying to make a somewhat efficient function to render a circle. I tried drawing pixel per pixel with the midpoint algorithm, but that’s too slow. So after some research i opted for creating a texture, locking it and manipulating its pixels. The problem is that i cannot seem to get the right colors. Here is what I came up:
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() };
}
Ignore the unsafe
blocks, i am just prototyping. But when setting the colors in the buffer array, the colors just aren’t right. If i set the draw color to cyan as an example (r: 0, g: 255, b: 255, a: 255) the circle is white, if i set magenta, its yellow.
1
The problem was that I was not checking for endianness. Since my system uses little endian byte order, so if little -> abgr, big -> rgba.
here is the texture lock callback:
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");
thanks to @AlexanderFadeev !