pub fn triangle(
    canvas: &mut Image,
    zbuffer: &mut Vec<f64>,
    shader: &mut dyn Shader,
    v0: Vec3f,
    v1: Vec3f,
    v2: Vec3f,
) {
    // figure out the bounding box
    let (mut xmin, mut ymin) = (f64::MAX, f64::MAX);
    let (mut xmax, mut ymax) = (f64::MIN, f64::MIN);
    for v in [v0, v1, v2].iter() {
        xmin = xmin.min(v.x);
        xmax = xmax.max(v.x);
        ymin = ymin.min(v.y);
        ymax = ymax.max(v.y);
    }

    let xmin = (xmin as usize).max(0);
    let xmax = (xmax as usize).min(canvas.width);
    let ymin = (ymin as usize).max(0);
    let ymax = (ymax as usize).min(canvas.height);

    // for every pixel p inside the box ...
    let mut p = Vec3f::zero();
    for x in xmin..=xmax {
        p.x = x as f64;
        for y in ymin..=ymax {
            p.y = y as f64;

            // ... calculate the barycentric coordinates for p
            let bc_screen = barycentric(v0, v1, v2, p);
            // if any part of the coordinate is negative, p is outside the triangle
            if bc_screen.x < 0. || bc_screen.y < 0. || bc_screen.z < 0. {
                continue;
            };
            p.z = v0.z * bc_screen.x;
            p.z += v1.z * bc_screen.y;
            p.z += v2.z * bc_screen.z;

            // don't draw fragments behind something we have already drawn
            let fragment_index = (p.x as usize) + (p.y as usize) * canvas.width;
            if zbuffer[fragment_index] < p.z {
                zbuffer[fragment_index] = p.z;

                // apply fragment shader
                let mut color = [0, 0, 0];
                let keep_fragment = shader.fragment(bc_screen, &mut color);
                // does this really play right with the z-index check before?
                if keep_fragment {
                    canvas.put(p.x as usize, p.y as usize, color);
                }
            }
        }
    }
}
/// Render a triangle v0,v1,v2 to the given canvas.
Render a triangle v0,v1,v2 to the given canvas.
Render a triangle v0 v1 v2 to the given canvas .
pub fn triangle(
    canvas: &mut Image,
    zbuffer: &mut Vec<f64>,
    shader: &mut dyn Shader,
    v0: Vec3f,
    v1: Vec3f,
    v2: Vec3f,
) {
    // figure out the bounding box
    let (mut xmin, mut ymin) = (f64::MAX, f64::MAX);
    let (mut xmax, mut ymax) = (f64::MIN, f64::MIN);
    for v in [v0, v1, v2].iter() {
        xmin = xmin.min(v.x);
        xmax = xmax.max(v.x);
        ymin = ymin.min(v.y);
        ymax = ymax.max(v.y);
    }
    let xmin = (xmin as usize).max(0);
    let xmax = (xmax as usize).min(canvas.width);
    let ymin = (ymin as usize).max(0);
    let ymax = (ymax as usize).min(canvas.height);
    // for every pixel p inside the box ...
    let mut p = Vec3f::zero();
    for x in xmin..=xmax {
        p.x = x as f64;
        for y in ymin..=ymax {
            p.y = y as f64;
            // ... calculate the barycentric coordinates for p
            let bc_screen = barycentric(v0, v1, v2, p);
            // if any part of the coordinate is negative, p is outside the triangle
            if bc_screen.x < 0. || bc_screen.y < 0. || bc_screen.z < 0. {
                continue;
            };
            p.z = v0.z * bc_screen.x;
            p.z += v1.z * bc_screen.y;
            p.z += v2.z * bc_screen.z;
            // don't draw fragments behind something we have already drawn
            let fragment_index = (p.x as usize) + (p.y as usize) * canvas.width;
            if zbuffer[fragment_index] < p.z {
                zbuffer[fragment_index] = p.z;
                // apply fragment shader
                let mut color = [0, 0, 0];
                let keep_fragment = shader.fragment(bc_screen, &mut color);
                // does this really play right with the z-index check before?
                if keep_fragment {
                    canvas.put(p.x as usize, p.y as usize, color);
                }
            }
        }
    }
}
pub fn triangle ( canvas : & mut Image , zbuffer : & mut Vec < f64 > , shader : & mut dyn Shader , v0 : Vec3f , v1 : Vec3f , v2 : Vec3f , ) { // figure out the bounding box let ( mut xmin , mut ymin ) = ( f64 :: MAX , f64 :: MAX ) ; let ( mut xmax , mut ymax ) = ( f64 :: MIN , f64 :: MIN ) ; for v in [ v0 , v1 , v2 ] . iter ( ) { xmin = xmin . min ( v . x ) ; xmax = xmax . max ( v . x ) ; ymin = ymin . min ( v . y ) ; ymax = ymax . max ( v . y ) ; } let xmin = ( xmin as usize ) . max ( 0 ) ; let xmax = ( xmax as usize ) . min ( canvas . width ) ; let ymin = ( ymin as usize ) . max ( 0 ) ; let ymax = ( ymax as usize ) . min ( canvas . height ) ; // for every pixel p inside the box ... let mut p = Vec3f :: zero ( ) ; for x in xmin ..= xmax { p . x = x as f64 ; for y in ymin ..= ymax { p . y = y as f64 ; // ... calculate the barycentric coordinates for p let bc_screen = barycentric ( v0 , v1 , v2 , p ) ; // if any part of the coordinate is negative, p is outside the triangle if bc_screen . x < 0. || bc_screen . y < 0. || bc_screen . z < 0. { continue ; } ; p . z = v0 . z * bc_screen . x ; p . z += v1 . z * bc_screen . y ; p . z += v2 . z * bc_screen . z ; // don't draw fragments behind something we have already drawn let fragment_index = ( p . x as usize ) + ( p . y as usize ) * canvas . width ; if zbuffer [ fragment_index ] < p . z { zbuffer [ fragment_index ] = p . z ; // apply fragment shader let mut color = [ 0 , 0 , 0 ] ; let keep_fragment = shader . fragment ( bc_screen , & mut color ) ; // does this really play right with the z-index check before? if keep_fragment { canvas . put ( p . x as usize , p . y as usize , color ) ; } } } } }
Render a triangle v0,v1,v2 to the given canvas.
Render a triangle v0 v1 v2 to the given canvas .
canvas
&mut Image
zbuffer
&mut Vec<f64>
shader
&mut dyn Shader
v0
Vec3f
v1
Vec3f
v2
Vec3f