Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- use std::cmp::{max, min};
- use std::mem::swap;
- use super::Target;
- use super::FragmentShader;
- use super::Varying;
- use super::VertexShader;
- pub struct Triangle;
- impl Triangle {
- /// Rasterizes a triangle with the given parameters. Results are written to the given TTarget.
- pub fn triangle<TVertexShader, TFragmentShader, TUniform, TVertex, TVarying, TTarget>(
- vs: &TVertexShader,
- fs: &TFragmentShader,
- uniform: &TUniform,
- vertex0: &TVertex,
- vertex1: &TVertex,
- vertex2: &TVertex,
- target: &TTarget,
- ) where
- TVertexShader: VertexShader<Uniform = TUniform, Vertex = TVertex, Varying = TVarying>,
- TFragmentShader: FragmentShader<Uniform = TUniform, Varying = TVarying>,
- TVarying: Varying,
- TTarget: Target,
- {
- // compute half width and height.
- let width = target.width() as f32;
- let height = target.height() as f32;
- let half_width = width * 0.5;
- let half_height = height * 0.5;
- // setup vrs for this primitive.
- let mut vr0 = Varying::new();
- let mut vr1 = Varying::new();
- let mut vr2 = Varying::new();
- // execute vertex shader, store position for interpolation.
- let t0 = vs.main(&uniform, &vertex0, &mut vr0);
- let t1 = vs.main(&uniform, &vertex1, &mut vr1);
- let t2 = vs.main(&uniform, &vertex2, &mut vr2);
- // calculate positions in clip space.
- let cs0 = Vector2::new(
- ((t0.x / t0.z) * width) + half_width,
- ((t0.y / t0.z) * height) + half_height,
- );
- let cs1 = Vector2::new(
- ((t1.x / t1.z) * width) + half_width,
- ((t1.y / t1.z) * height) + half_height,
- );
- let cs2 = Vector2::new(
- ((t2.x / t2.z) * width) + half_width,
- ((t2.y / t2.z) * height) + half_height,
- );
- // run fragment processor
- Self::run_fragment(
- fs,
- uniform,
- &vr0,
- &vr1,
- &vr2,
- &cs0,
- &cs1,
- &cs2,
- target,
- );
- }
- /// Runs a fragment shader rasterization pass for this triangle.
- fn run_fragment<TTarget, TFragmentShader, TVarying, TUniform>(
- fs: &TFragmentShader,
- uniform: &TUniform,
- vr0: &TVarying,
- vr1: &TVarying,
- vr2: &TVarying,
- cs0: &Vector2,
- cs1: &Vector2,
- cs2: &Vector2,
- target: &TTarget,
- ) where
- TFragmentShader: FragmentShader<Uniform = TUniform, Varying = TVarying>,
- TVarying: Varying,
- TTarget: Target,
- {
- let mut x0 = cs0.x;
- let mut y0 = cs0.y;
- let mut x1 = cs1.x;
- let mut y1 = cs1.y;
- let mut x2 = cs2.x;
- let mut y2 = cs2.y;
- let width = target.width();
- let height = target.height();
- // sort top to bottom
- if y0 > y1 {
- swap(&mut x0, &mut x1);
- swap(&mut y0, &mut y1);
- }
- if y1 > y2 {
- swap(&mut x1, &mut x2);
- swap(&mut y1, &mut y2);
- }
- if y0 > y1 {
- swap(&mut x0, &mut x1);
- swap(&mut y0, &mut y1);
- }
- // full height
- let h0 = y2 - y0;
- // top triangle
- {
- let h1 = y1 - y0;
- if h1 > 0_f32 {
- let xmin = max(y0 as i32, 0);
- let ymax = min(y1 as i32, (height - 1) as i32);
- for y in xmin..ymax + 1 {
- let sx = (y as f32 - y0) / h0;
- let sy = (y as f32 - y0) / h1;
- let m0 = (x0 + (x2 - x0) * sx) as i32;
- let m1 = (x0 + (x1 - x0) * sy) as i32;
- let xmin = max(min(m0, m1), 0);
- let xmax = min(max(m0, m1), (width - 1) as i32);
- for x in xmin..xmax + 1 {
- // let c = p.pixel(&w, &h, &x, &y);
- // buf.set(x as usize, y as usize, c);
- }
- }
- }
- }
- // bottom triangle
- {
- let h1 = y2 - y1;
- if h1 > 0_f32 {
- let xmin = max(y1 as i32, 0);
- let ymax = min(y2 as i32, (height - 1) as i32);
- for y in xmin..ymax + 1 {
- let sx = (y as f32 - y0) / h0;
- let sy = (y as f32 - y1) / h1;
- let m0 = (x0 + (x2 - x0) * sx) as i32;
- let m1 = (x1 + (x2 - x1) * sy) as i32;
- let xmin = max(min(m0, m1), 0);
- let xmax = min(max(m0, m1), (width - 1) as i32);
- for x in xmin..xmax + 1 {
- // let c = p.pixel(&w, &h, &x, &y);
- // buf.set(x as usize, y as usize, c);
- }
- }
- }
- }
- }
- fn visible(&self, v0: &Vector2, v1: &Vector2, v2: &Vector2) -> bool {
- return ((v1.x - v0.x) * (v2.y - v0.y)) - ((v1.y - v0.y) * (v2.x - v0.x)) >= 0.0;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement