From f3b6ca46e16622d027ba69a239954a8ae813c3b0 Mon Sep 17 00:00:00 2001 From: gered Date: Wed, 5 Apr 2023 12:37:26 -0400 Subject: [PATCH] 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. --- ggdt/src/graphics/bitmap/indexed/triangles.rs | 112 ++--- ggdt/src/graphics/bitmap/rgb/triangles.rs | 387 +++++++++++------- 2 files changed, 296 insertions(+), 203 deletions(-) diff --git a/ggdt/src/graphics/bitmap/indexed/triangles.rs b/ggdt/src/graphics/bitmap/indexed/triangles.rs index 2fbc98d..d0ac2d0 100644 --- a/ggdt/src/graphics/bitmap/indexed/triangles.rs +++ b/ggdt/src/graphics/bitmap/indexed/triangles.rs @@ -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) } } } diff --git a/ggdt/src/graphics/bitmap/rgb/triangles.rs b/ggdt/src/graphics/bitmap/rgb/triangles.rs index a3c55ab..981a6e8 100644 --- a/ggdt/src/graphics/bitmap/rgb/triangles.rs +++ b/ggdt/src/graphics/bitmap/rgb/triangles.rs @@ -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) } } }