diff --git a/ggdt/src/graphics/bitmap/primitives.rs b/ggdt/src/graphics/bitmap/primitives.rs index 507c863..ddd2118 100644 --- a/ggdt/src/graphics/bitmap/primitives.rs +++ b/ggdt/src/graphics/bitmap/primitives.rs @@ -3,6 +3,7 @@ use std::mem::swap; use crate::graphics::bitmap::Bitmap; use crate::graphics::font::{Character, Font, FontRenderOpts}; use crate::graphics::Pixel; +use crate::math::lerp; use crate::math::rect::Rect; impl Bitmap { @@ -68,8 +69,14 @@ impl Bitmap { #[inline] pub fn sample_at(&self, u: f32, v: f32) -> PixelType { - let x = (u * self.width as f32) as i32 % self.width as i32; - let y = (v * self.height as f32) as i32 % self.height as i32; + // HACK: the 0.00001 shit. there is some weird and classic "off-by-1" issue happening SOMEWHERE in the + // textured 2d triangle rendering and i cannot find it. every other article i've read on the subject + // doesn't seem to do anything special here so either i'm doing something wrong or no one else tests + // their shit either. i just don't know which it is! but this hack fix definitely is all kinds of shit. + // i have no doubt that this "Fix" will probably be the source of OTHER issues too that i've just not + // seen yet in my testing. ugh. + let x = lerp(0.0, self.width as f32 - 0.00001, u) as i32 % self.width as i32; + let y = lerp(0.0, self.height as f32 - 0.00001, v) as i32 % self.height as i32; unsafe { self.get_pixel_unchecked(x, y) } } diff --git a/ggdt/src/graphics/bitmap/triangles.rs b/ggdt/src/graphics/bitmap/triangles.rs index acda50f..4fc8887 100644 --- a/ggdt/src/graphics/bitmap/triangles.rs +++ b/ggdt/src/graphics/bitmap/triangles.rs @@ -60,15 +60,15 @@ impl Bitmap { // ordering but the math presented seems to only work as-is with clockwise ordering ... *grumble* // TODO: implement fill rules, probably using top-left ordering as most 3d APIs do i guess - let min_x = a.x.min(b.x).min(c.x); - let min_y = a.y.min(b.y).min(c.y); - let max_x = a.x.max(b.x).max(c.x); - let max_y = a.y.max(b.y).max(c.y); + let min_x = a.x.min(b.x).min(c.x).floor() as i32; + let min_y = a.y.min(b.y).min(c.y).floor() as i32; + let max_x = a.x.max(b.x).max(c.x).ceil() as i32; + let max_y = a.y.max(b.y).max(c.y).ceil() as i32; - let min_x = std::cmp::max(self.clip_region().x, min_x as i32); - let min_y = std::cmp::max(self.clip_region().y, min_y as i32); - let max_x = std::cmp::min(self.clip_region().right(), max_x as i32); - let max_y = std::cmp::min(self.clip_region().bottom(), max_y as i32); + let min_x = std::cmp::max(self.clip_region().x, min_x); + let min_y = std::cmp::max(self.clip_region().y, min_y); + let max_x = std::cmp::min(self.clip_region().right(), max_x); + let max_y = std::cmp::min(self.clip_region().bottom(), max_y); let draw_width = (max_x - min_x + 1) as usize; let next_row_inc = self.width() as usize; @@ -79,7 +79,7 @@ impl Bitmap { for (idx, pixel) in row_pixels.iter_mut().enumerate() { let x = min_x + idx as i32; - let p = Vector2::new(x as f32 + 0.5, y as f32 + 0.5); + let p = Vector2::new(x as f32, y as f32); let w0 = cross(b, c, p); let w1 = cross(c, a, p); let w2 = cross(a, b, p);