move all of the triangle_2d draw implementations to their own functions

keeping the original single triangle_2d function taking the enum, but
also allowing separate functions to be called without the need for an
enum, which might be useful.

plus this also feels a bit better organized and easier to read when you
just need to look at one or two different triangle drawing
implementations.
This commit is contained in:
Gered 2023-04-05 12:37:26 -04:00
parent 097147c568
commit f3b6ca46e1
2 changed files with 296 additions and 203 deletions

View file

@ -28,59 +28,73 @@ pub enum IndexedTriangle2d<'a> {
}
impl IndexedBitmap {
pub fn solid_triangle_2d(&mut self, positions: &[Vector2; 3], color: u8) {
per_pixel_triangle_2d(
self, //
positions[0],
positions[1],
positions[2],
|dest_pixels, _w0, _w1, _w2| *dest_pixels = color,
)
}
pub fn solid_blended_triangle_2d(&mut self, positions: &[Vector2; 3], color: u8, blendmap: &BlendMap) {
per_pixel_triangle_2d(
self, //
positions[0],
positions[1],
positions[2],
|dest_pixels, _w0, _w1, _w2| {
*dest_pixels = if let Some(blended) = blendmap.blend(color, *dest_pixels) { blended } else { color };
},
)
}
pub fn solid_textured_triangle_2d(&mut self, positions: &[Vector2; 3], texcoords: &[Vector2; 3], bitmap: &Self) {
let area = edge_function(positions[0], positions[1], positions[2]);
per_pixel_triangle_2d(
self, //
positions[0],
positions[1],
positions[2],
|dest_pixels, w0, w1, w2| {
let u = (w0 * texcoords[0].x + w1 * texcoords[1].x + w2 * texcoords[2].x) / area;
let v = (w0 * texcoords[0].y + w1 * texcoords[1].y + w2 * texcoords[2].y) / area;
*dest_pixels = bitmap.sample_at(u, v);
},
)
}
pub fn solid_textured_blended_triangle_2d(
&mut self,
positions: &[Vector2; 3],
texcoords: &[Vector2; 3],
bitmap: &Self,
blendmap: &BlendMap,
) {
let area = edge_function(positions[0], positions[1], positions[2]);
per_pixel_triangle_2d(
self, //
positions[0],
positions[1],
positions[2],
|dest_pixels, w0, w1, w2| {
let u = (w0 * texcoords[0].x + w1 * texcoords[1].x + w2 * texcoords[2].x) / area;
let v = (w0 * texcoords[0].y + w1 * texcoords[1].y + w2 * texcoords[2].y) / area;
let texel = bitmap.sample_at(u, v);
*dest_pixels = if let Some(blended) = blendmap.blend(texel, *dest_pixels) { blended } else { texel };
},
)
}
pub fn triangle_2d(&mut self, triangle: &IndexedTriangle2d) {
use IndexedTriangle2d::*;
match triangle {
Solid { position, color } => {
per_pixel_triangle_2d(
self, //
position[0],
position[1],
position[2],
|dest_pixels, _w0, _w1, _w2| *dest_pixels = *color,
)
}
SolidBlended { position, color, blendmap } => {
per_pixel_triangle_2d(
self, //
position[0],
position[1],
position[2],
|dest_pixels, _w0, _w1, _w2| {
*dest_pixels =
if let Some(blended) = blendmap.blend(*color, *dest_pixels) { blended } else { *color };
},
)
}
SolidTextured { position, texcoord, bitmap } => {
let area = edge_function(position[0], position[1], position[2]);
per_pixel_triangle_2d(
self, //
position[0],
position[1],
position[2],
|dest_pixels, w0, w1, w2| {
let u = (w0 * texcoord[0].x + w1 * texcoord[1].x + w2 * texcoord[2].x) / area;
let v = (w0 * texcoord[0].y + w1 * texcoord[1].y + w2 * texcoord[2].y) / area;
*dest_pixels = bitmap.sample_at(u, v);
},
)
}
Solid { position, color } => self.solid_triangle_2d(position, *color),
SolidBlended { position, color, blendmap } => self.solid_blended_triangle_2d(position, *color, *blendmap),
SolidTextured { position, texcoord, bitmap } => self.solid_textured_triangle_2d(position, texcoord, bitmap),
SolidTexturedBlended { position, texcoord, bitmap, blendmap } => {
let area = edge_function(position[0], position[1], position[2]);
per_pixel_triangle_2d(
self, //
position[0],
position[1],
position[2],
|dest_pixels, w0, w1, w2| {
let u = (w0 * texcoord[0].x + w1 * texcoord[1].x + w2 * texcoord[2].x) / area;
let v = (w0 * texcoord[0].y + w1 * texcoord[1].y + w2 * texcoord[2].y) / area;
let texel = bitmap.sample_at(u, v);
*dest_pixels =
if let Some(blended) = blendmap.blend(texel, *dest_pixels) { blended } else { texel };
},
)
self.solid_textured_blended_triangle_2d(position, texcoord, bitmap, blendmap)
}
}
}

View file

@ -71,176 +71,255 @@ pub enum RgbaTriangle2d<'a> {
}
impl RgbaBitmap {
pub fn solid_triangle_2d(&mut self, positions: &[Vector2; 3], color: u32) {
per_pixel_triangle_2d(
self, //
positions[0],
positions[1],
positions[2],
|dest_pixels, _w0, _w1, _w2| *dest_pixels = color,
)
}
pub fn solid_blended_triangle_2d(&mut self, positions: &[Vector2; 3], color: u32, blend: BlendFunction) {
per_pixel_triangle_2d(
self, //
positions[0],
positions[1],
positions[2],
|dest_pixels, _w0, _w1, _w2| *dest_pixels = blend.blend(color, *dest_pixels),
)
}
pub fn solid_multicolor_triangle_2d(&mut self, positions: &[Vector2; 3], colors: &[u32; 3]) {
let area = edge_function(positions[0], positions[1], positions[2]);
let (r1, g1, b1) = from_rgb32(colors[0]);
let (r2, g2, b2) = from_rgb32(colors[1]);
let (r3, g3, b3) = from_rgb32(colors[2]);
per_pixel_triangle_2d(
self, //
positions[0],
positions[1],
positions[2],
|dest_pixels, w0, w1, w2| {
let r = ((w0 * r1 as f32 + w1 * r2 as f32 + w2 * r3 as f32) / area) as u8;
let g = ((w0 * g1 as f32 + w1 * g2 as f32 + w2 * g3 as f32) / area) as u8;
let b = ((w0 * b1 as f32 + w1 * b2 as f32 + w2 * b3 as f32) / area) as u8;
*dest_pixels = to_rgb32(r, g, b)
},
)
}
pub fn solid_multicolor_blended_triangle_2d(
&mut self,
positions: &[Vector2; 3],
colors: &[u32; 3],
blend: BlendFunction,
) {
let area = edge_function(positions[0], positions[1], positions[2]);
let (a1, r1, g1, b1) = from_argb32(colors[0]);
let (a2, r2, g2, b2) = from_argb32(colors[1]);
let (a3, r3, g3, b3) = from_argb32(colors[2]);
per_pixel_triangle_2d(
self, //
positions[0],
positions[1],
positions[2],
|dest_pixels, w0, w1, w2| {
let a = ((w0 * a1 as f32 + w1 * a2 as f32 + w2 * a3 as f32) / area) as u8;
let r = ((w0 * r1 as f32 + w1 * r2 as f32 + w2 * r3 as f32) / area) as u8;
let g = ((w0 * g1 as f32 + w1 * g2 as f32 + w2 * g3 as f32) / area) as u8;
let b = ((w0 * b1 as f32 + w1 * b2 as f32 + w2 * b3 as f32) / area) as u8;
*dest_pixels = blend.blend(to_argb32(a, r, g, b), *dest_pixels)
},
)
}
pub fn solid_textured_triangle_2d(&mut self, positions: &[Vector2; 3], texcoords: &[Vector2; 3], bitmap: &Self) {
let area = edge_function(positions[0], positions[1], positions[2]);
per_pixel_triangle_2d(
self, //
positions[0],
positions[1],
positions[2],
|dest_pixels, w0, w1, w2| {
let u = (w0 * texcoords[0].x + w1 * texcoords[1].x + w2 * texcoords[2].x) / area;
let v = (w0 * texcoords[0].y + w1 * texcoords[1].y + w2 * texcoords[2].y) / area;
*dest_pixels = bitmap.sample_at(u, v);
},
)
}
pub fn solid_textured_colored_triangle_2d(
&mut self,
positions: &[Vector2; 3],
texcoords: &[Vector2; 3],
color: u32,
bitmap: &Self,
) {
let area = edge_function(positions[0], positions[1], positions[2]);
per_pixel_triangle_2d(
self, //
positions[0],
positions[1],
positions[2],
|dest_pixels, w0, w1, w2| {
let u = (w0 * texcoords[0].x + w1 * texcoords[1].x + w2 * texcoords[2].x) / area;
let v = (w0 * texcoords[0].y + w1 * texcoords[1].y + w2 * texcoords[2].y) / area;
*dest_pixels = multiply_argb32(bitmap.sample_at(u, v), color)
},
)
}
pub fn solid_textured_colored_blended_triangle_2d(
&mut self,
positions: &[Vector2; 3],
texcoords: &[Vector2; 3],
color: u32,
bitmap: &Self,
blend: BlendFunction,
) {
let area = edge_function(positions[0], positions[1], positions[2]);
per_pixel_triangle_2d(
self, //
positions[0],
positions[1],
positions[2],
|dest_pixels, w0, w1, w2| {
let u = (w0 * texcoords[0].x + w1 * texcoords[1].x + w2 * texcoords[2].x) / area;
let v = (w0 * texcoords[0].y + w1 * texcoords[1].y + w2 * texcoords[2].y) / area;
let src = multiply_argb32(bitmap.sample_at(u, v), color);
*dest_pixels = blend.blend(src, *dest_pixels)
},
)
}
pub fn solid_textured_multicolor_triangle_2d(
&mut self,
positions: &[Vector2; 3],
texcoords: &[Vector2; 3],
colors: &[u32; 3],
bitmap: &Self,
) {
let area = edge_function(positions[0], positions[1], positions[2]);
let (r1, g1, b1) = from_rgb32(colors[0]);
let (r2, g2, b2) = from_rgb32(colors[1]);
let (r3, g3, b3) = from_rgb32(colors[2]);
per_pixel_triangle_2d(
self, //
positions[0],
positions[1],
positions[2],
|dest_pixels, w0, w1, w2| {
let r = ((w0 * r1 as f32 + w1 * r2 as f32 + w2 * r3 as f32) / area) as u8;
let g = ((w0 * g1 as f32 + w1 * g2 as f32 + w2 * g3 as f32) / area) as u8;
let b = ((w0 * b1 as f32 + w1 * b2 as f32 + w2 * b3 as f32) / area) as u8;
let u = (w0 * texcoords[0].x + w1 * texcoords[1].x + w2 * texcoords[2].x) / area;
let v = (w0 * texcoords[0].y + w1 * texcoords[1].y + w2 * texcoords[2].y) / area;
*dest_pixels = multiply_argb32(bitmap.sample_at(u, v), to_rgb32(r, g, b))
},
)
}
pub fn solid_textured_multicolor_blended_triangle_2d(
&mut self,
positions: &[Vector2; 3],
texcoords: &[Vector2; 3],
colors: &[u32; 3],
bitmap: &Self,
blend: BlendFunction,
) {
let area = edge_function(positions[0], positions[1], positions[2]);
let (a1, r1, g1, b1) = from_argb32(colors[0]);
let (a2, r2, g2, b2) = from_argb32(colors[1]);
let (a3, r3, g3, b3) = from_argb32(colors[2]);
per_pixel_triangle_2d(
self, //
positions[0],
positions[1],
positions[2],
|dest_pixels, w0, w1, w2| {
let a = ((w0 * a1 as f32 + w1 * a2 as f32 + w2 * a3 as f32) / area) as u8;
let r = ((w0 * r1 as f32 + w1 * r2 as f32 + w2 * r3 as f32) / area) as u8;
let g = ((w0 * g1 as f32 + w1 * g2 as f32 + w2 * g3 as f32) / area) as u8;
let b = ((w0 * b1 as f32 + w1 * b2 as f32 + w2 * b3 as f32) / area) as u8;
let u = (w0 * texcoords[0].x + w1 * texcoords[1].x + w2 * texcoords[2].x) / area;
let v = (w0 * texcoords[0].y + w1 * texcoords[1].y + w2 * texcoords[2].y) / area;
let src = multiply_argb32(bitmap.sample_at(u, v), to_argb32(a, r, g, b));
*dest_pixels = blend.blend(src, *dest_pixels)
},
)
}
pub fn solid_textured_tinted_triangle_2d(
&mut self,
positions: &[Vector2; 3],
texcoords: &[Vector2; 3],
bitmap: &Self,
tint: u32,
) {
let area = edge_function(positions[0], positions[1], positions[2]);
per_pixel_triangle_2d(
self, //
positions[0],
positions[1],
positions[2],
|dest_pixels, w0, w1, w2| {
let u = (w0 * texcoords[0].x + w1 * texcoords[1].x + w2 * texcoords[2].x) / area;
let v = (w0 * texcoords[0].y + w1 * texcoords[1].y + w2 * texcoords[2].y) / area;
*dest_pixels = tint_argb32(bitmap.sample_at(u, v), tint);
},
)
}
pub fn solid_textured_blended_triangle_2d(
&mut self,
positions: &[Vector2; 3],
texcoords: &[Vector2; 3],
bitmap: &Self,
blend: BlendFunction,
) {
let area = edge_function(positions[0], positions[1], positions[2]);
per_pixel_triangle_2d(
self, //
positions[0],
positions[1],
positions[2],
|dest_pixels, w0, w1, w2| {
let u = (w0 * texcoords[0].x + w1 * texcoords[1].x + w2 * texcoords[2].x) / area;
let v = (w0 * texcoords[0].y + w1 * texcoords[1].y + w2 * texcoords[2].y) / area;
*dest_pixels = blend.blend(bitmap.sample_at(u, v), *dest_pixels);
},
)
}
pub fn triangle_2d(&mut self, triangle: &RgbaTriangle2d) {
use RgbaTriangle2d::*;
match triangle {
Solid { position, color } => {
per_pixel_triangle_2d(
self, //
position[0],
position[1],
position[2],
|dest_pixels, _w0, _w1, _w2| *dest_pixels = *color,
)
}
SolidBlended { position, color, blend } => {
per_pixel_triangle_2d(
self, //
position[0],
position[1],
position[2],
|dest_pixels, _w0, _w1, _w2| *dest_pixels = blend.blend(*color, *dest_pixels),
)
}
SolidMultiColor { position, color } => {
let area = edge_function(position[0], position[1], position[2]);
let (r1, g1, b1) = from_rgb32(color[0]);
let (r2, g2, b2) = from_rgb32(color[1]);
let (r3, g3, b3) = from_rgb32(color[2]);
per_pixel_triangle_2d(
self, //
position[0],
position[1],
position[2],
|dest_pixels, w0, w1, w2| {
let r = ((w0 * r1 as f32 + w1 * r2 as f32 + w2 * r3 as f32) / area) as u8;
let g = ((w0 * g1 as f32 + w1 * g2 as f32 + w2 * g3 as f32) / area) as u8;
let b = ((w0 * b1 as f32 + w1 * b2 as f32 + w2 * b3 as f32) / area) as u8;
*dest_pixels = to_rgb32(r, g, b)
},
)
}
Solid { position, color } => self.solid_triangle_2d(position, *color),
SolidBlended { position, color, blend } => self.solid_blended_triangle_2d(position, *color, *blend),
SolidMultiColor { position, color } => self.solid_multicolor_triangle_2d(position, color),
SolidMultiColorBlended { position, color, blend } => {
let area = edge_function(position[0], position[1], position[2]);
let (a1, r1, g1, b1) = from_argb32(color[0]);
let (a2, r2, g2, b2) = from_argb32(color[1]);
let (a3, r3, g3, b3) = from_argb32(color[2]);
per_pixel_triangle_2d(
self, //
position[0],
position[1],
position[2],
|dest_pixels, w0, w1, w2| {
let a = ((w0 * a1 as f32 + w1 * a2 as f32 + w2 * a3 as f32) / area) as u8;
let r = ((w0 * r1 as f32 + w1 * r2 as f32 + w2 * r3 as f32) / area) as u8;
let g = ((w0 * g1 as f32 + w1 * g2 as f32 + w2 * g3 as f32) / area) as u8;
let b = ((w0 * b1 as f32 + w1 * b2 as f32 + w2 * b3 as f32) / area) as u8;
*dest_pixels = blend.blend(to_argb32(a, r, g, b), *dest_pixels)
},
)
}
SolidTextured { position, texcoord, bitmap } => {
let area = edge_function(position[0], position[1], position[2]);
per_pixel_triangle_2d(
self, //
position[0],
position[1],
position[2],
|dest_pixels, w0, w1, w2| {
let u = (w0 * texcoord[0].x + w1 * texcoord[1].x + w2 * texcoord[2].x) / area;
let v = (w0 * texcoord[0].y + w1 * texcoord[1].y + w2 * texcoord[2].y) / area;
*dest_pixels = bitmap.sample_at(u, v);
},
)
self.solid_multicolor_blended_triangle_2d(position, color, *blend)
}
SolidTextured { position, texcoord, bitmap } => self.solid_textured_triangle_2d(position, texcoord, bitmap),
SolidTexturedColored { position, texcoord, color, bitmap } => {
let area = edge_function(position[0], position[1], position[2]);
per_pixel_triangle_2d(
self, //
position[0],
position[1],
position[2],
|dest_pixels, w0, w1, w2| {
let u = (w0 * texcoord[0].x + w1 * texcoord[1].x + w2 * texcoord[2].x) / area;
let v = (w0 * texcoord[0].y + w1 * texcoord[1].y + w2 * texcoord[2].y) / area;
*dest_pixels = multiply_argb32(bitmap.sample_at(u, v), *color)
},
)
self.solid_textured_colored_triangle_2d(position, texcoord, *color, bitmap)
}
SolidTexturedColoredBlended { position, texcoord, color, bitmap, blend } => {
let area = edge_function(position[0], position[1], position[2]);
per_pixel_triangle_2d(
self, //
position[0],
position[1],
position[2],
|dest_pixels, w0, w1, w2| {
let u = (w0 * texcoord[0].x + w1 * texcoord[1].x + w2 * texcoord[2].x) / area;
let v = (w0 * texcoord[0].y + w1 * texcoord[1].y + w2 * texcoord[2].y) / area;
let src = multiply_argb32(bitmap.sample_at(u, v), *color);
*dest_pixels = blend.blend(src, *dest_pixels)
},
)
self.solid_textured_colored_blended_triangle_2d(position, texcoord, *color, bitmap, *blend)
}
SolidTexturedMultiColored { position, texcoord, color, bitmap } => {
let area = edge_function(position[0], position[1], position[2]);
let (r1, g1, b1) = from_rgb32(color[0]);
let (r2, g2, b2) = from_rgb32(color[1]);
let (r3, g3, b3) = from_rgb32(color[2]);
per_pixel_triangle_2d(
self, //
position[0],
position[1],
position[2],
|dest_pixels, w0, w1, w2| {
let r = ((w0 * r1 as f32 + w1 * r2 as f32 + w2 * r3 as f32) / area) as u8;
let g = ((w0 * g1 as f32 + w1 * g2 as f32 + w2 * g3 as f32) / area) as u8;
let b = ((w0 * b1 as f32 + w1 * b2 as f32 + w2 * b3 as f32) / area) as u8;
let u = (w0 * texcoord[0].x + w1 * texcoord[1].x + w2 * texcoord[2].x) / area;
let v = (w0 * texcoord[0].y + w1 * texcoord[1].y + w2 * texcoord[2].y) / area;
*dest_pixels = multiply_argb32(bitmap.sample_at(u, v), to_rgb32(r, g, b))
},
)
self.solid_textured_multicolor_triangle_2d(position, texcoord, color, bitmap)
}
SolidTexturedMultiColoredBlended { position, texcoord, color, bitmap, blend } => {
let area = edge_function(position[0], position[1], position[2]);
let (a1, r1, g1, b1) = from_argb32(color[0]);
let (a2, r2, g2, b2) = from_argb32(color[1]);
let (a3, r3, g3, b3) = from_argb32(color[2]);
per_pixel_triangle_2d(
self, //
position[0],
position[1],
position[2],
|dest_pixels, w0, w1, w2| {
let a = ((w0 * a1 as f32 + w1 * a2 as f32 + w2 * a3 as f32) / area) as u8;
let r = ((w0 * r1 as f32 + w1 * r2 as f32 + w2 * r3 as f32) / area) as u8;
let g = ((w0 * g1 as f32 + w1 * g2 as f32 + w2 * g3 as f32) / area) as u8;
let b = ((w0 * b1 as f32 + w1 * b2 as f32 + w2 * b3 as f32) / area) as u8;
let u = (w0 * texcoord[0].x + w1 * texcoord[1].x + w2 * texcoord[2].x) / area;
let v = (w0 * texcoord[0].y + w1 * texcoord[1].y + w2 * texcoord[2].y) / area;
let src = multiply_argb32(bitmap.sample_at(u, v), to_argb32(a, r, g, b));
*dest_pixels = blend.blend(src, *dest_pixels)
},
)
self.solid_textured_multicolor_blended_triangle_2d(position, texcoord, color, bitmap, *blend)
}
SolidTexturedTinted { position, texcoord, bitmap, tint } => {
let area = edge_function(position[0], position[1], position[2]);
per_pixel_triangle_2d(
self, //
position[0],
position[1],
position[2],
|dest_pixels, w0, w1, w2| {
let u = (w0 * texcoord[0].x + w1 * texcoord[1].x + w2 * texcoord[2].x) / area;
let v = (w0 * texcoord[0].y + w1 * texcoord[1].y + w2 * texcoord[2].y) / area;
*dest_pixels = tint_argb32(bitmap.sample_at(u, v), *tint);
},
)
self.solid_textured_tinted_triangle_2d(position, texcoord, bitmap, *tint)
}
SolidTexturedBlended { position, texcoord, bitmap, blend } => {
let area = edge_function(position[0], position[1], position[2]);
per_pixel_triangle_2d(
self, //
position[0],
position[1],
position[2],
|dest_pixels, w0, w1, w2| {
let u = (w0 * texcoord[0].x + w1 * texcoord[1].x + w2 * texcoord[2].x) / area;
let v = (w0 * texcoord[0].y + w1 * texcoord[1].y + w2 * texcoord[2].y) / area;
*dest_pixels = blend.blend(bitmap.sample_at(u, v), *dest_pixels);
},
)
self.solid_textured_blended_triangle_2d(position, texcoord, bitmap, *blend)
}
}
}