diff --git a/Cargo.toml b/Cargo.toml index ab6f381..5a6b45b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,6 @@ name = "graphics" path = "./src/lib.rs" [dependencies] -draw_state = "0.3.0" interpolation = "0.1.0" piston-texture = "0.3.0" piston-viewport = "0.2.0" diff --git a/src/clip_draw_state.rs b/src/clip_draw_state.rs deleted file mode 100644 index 335a591..0000000 --- a/src/clip_draw_state.rs +++ /dev/null @@ -1,53 +0,0 @@ -use draw_state_lib::state::*; -use DrawState; - -static CLIP_DRAW_STATE: &'static DrawState = - &DrawState { - rasterizer: Rasterizer { - front_face: FrontFace::CounterClockwise, - method: RasterMethod::Fill( - CullFace::Nothing - ), - offset: None, - samples: None - }, - multi_sample: None, - scissor: None, - stencil: Some(Stencil { - front: StencilSide { - fun: Comparison::Never, - mask_read: 255, - mask_write: 255, - op_fail: StencilOp::Replace, - op_depth_fail: StencilOp::Keep, - op_pass: StencilOp::Keep, - }, - back: StencilSide { - fun: Comparison::Never, - mask_read: 255, - mask_write: 255, - op_fail: StencilOp::Replace, - op_depth_fail: StencilOp::Keep, - op_pass: StencilOp::Keep, - }, - }), - depth: None, - blend: Some(Blend { - color: BlendChannel { - equation: Equation::Add, - source: Factor::ZeroPlus(BlendValue::SourceAlpha), - destination: Factor::OneMinus(BlendValue::SourceAlpha), - }, - alpha: BlendChannel { - equation: Equation::Add, - source: Factor::One, - destination: Factor::One, - }, - }), - color_mask: MASK_NONE, - }; - -/// Returns a default draw state that does additive blending and no culling. -pub fn clip_draw_state() -> &'static DrawState { - CLIP_DRAW_STATE -} diff --git a/src/context.rs b/src/context.rs index 873e6d0..ffae182 100644 --- a/src/context.rs +++ b/src/context.rs @@ -1,7 +1,6 @@ //! Transformation context use DrawState; -use default_draw_state; use math::{ abs_transform, identity, @@ -33,7 +32,7 @@ impl Context { Context { view: identity(), transform: identity(), - draw_state: *default_draw_state(), + draw_state: Default::default(), viewport: None, } } @@ -54,7 +53,7 @@ impl Context { Context { view: mat, transform: mat, - draw_state: *default_draw_state(), + draw_state: Default::default(), viewport: Some(viewport), } } @@ -75,7 +74,7 @@ impl Context { Context { view: mat, transform: mat, - draw_state: *default_draw_state(), + draw_state: Default::default(), viewport: None, } } diff --git a/src/default_draw_state.rs b/src/default_draw_state.rs deleted file mode 100644 index 49bbe74..0000000 --- a/src/default_draw_state.rs +++ /dev/null @@ -1,36 +0,0 @@ -use draw_state::state::*; -use DrawState; - -static DEFAULT_DRAW_STATE: &'static DrawState = - &DrawState { - rasterizer: Rasterizer { - front_face: FrontFace::CounterClockwise, - method: RasterMethod::Fill( - CullFace::Nothing - ), - offset: None, - samples: None - }, - multi_sample: None, - scissor: None, - stencil: None, - depth: None, - blend: Some(Blend { - color: BlendChannel { - equation: Equation::Add, - source: Factor::ZeroPlus(BlendValue::SourceAlpha), - destination: Factor::OneMinus(BlendValue::SourceAlpha), - }, - alpha: BlendChannel { - equation: Equation::Add, - source: Factor::One, - destination: Factor::One, - }, - }), - color_mask: MASK_ALL, - }; - -/// Returns a default draw state that does additive blending and no culling. -pub fn default_draw_state() -> &'static DrawState { - DEFAULT_DRAW_STATE -} diff --git a/src/draw_state.rs b/src/draw_state.rs new file mode 100644 index 0000000..8df25f7 --- /dev/null +++ b/src/draw_state.rs @@ -0,0 +1,125 @@ +//! Graphics draw state. + +/// Graphics draw state used for blending, clipping and stencil rendering. +#[derive(Copy, Clone, PartialEq, Debug, PartialOrd)] +pub struct DrawState { + /// Scissor mask to use. If set, no pixel outside of this + /// rectangle (in screen space) will be written to as a result of rendering. + pub scissor: Option<[u32; 4]>, + /// Stencil test to use. If None, no stencil testing is done. + pub stencil: Option, + /// Blend function to use. If None, blending is disabled. + pub blend: Option, +} + +impl Default for DrawState { + fn default() -> Self { + DrawState::new_alpha() + } +} + +impl DrawState { + /// Uses alpha blending. + pub fn new_alpha() -> DrawState { + DrawState { + blend: Some(Blend::Alpha), + stencil: None, + scissor: None, + } + } + + /// Draws to stencil buffer with value 255. + /// This can be used for clipping. + pub fn new_clip() -> DrawState { + DrawState { + blend: Some(Blend::Alpha), + stencil: Some(Stencil::Clip(255)), + scissor: None, + } + } + + /// Tests against stencil buffer with value 255. + /// Draws inside the shape defined by stencil buffer. + pub fn new_inside() -> DrawState { + DrawState { + blend: Some(Blend::Alpha), + stencil: Some(Stencil::Inside(255)), + scissor: None, + } + } + + /// Tests against stencil buffer with value 255. + /// Draws outside the shape defined by stencil buffer. + pub fn new_outside() -> DrawState { + DrawState { + blend: Some(Blend::Alpha), + stencil: Some(Stencil::Outside(255)), + scissor: None, + } + } + + /// Sets blending. + pub fn blend(mut self, blend: Blend) -> DrawState { + self.blend = Some(blend); + self + } + + /// Sets scissor `[x, y, w, h]`. + pub fn scissor(mut self, scissor: [u32; 4]) -> DrawState { + self.scissor = Some(scissor); + self + } +} + +/// The blend setting to use when drawing. +/// +/// Using presets since some backends need one pipeline state object instance +/// per blending technique. +#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)] +pub enum Blend { + /// Alpha blending (allows semi-transparent pixels). + /// + /// ```ignore + /// dest_color' = src_color * src_alpha + dest_color * (1 - src_alpha) + /// dest_alpha' = src_alpha + dest_alpha + /// ``` + Alpha, + /// Additive blending. + /// + /// ```ignore + /// dest_color' = src_color + dest_color + /// dest_alpha' = src_alpha + dest_alpha + /// ``` + Add, + /// Multiply color components. + /// + /// ```ignore + /// dest_color' = src_color * dest_color + /// dest_alpha' = src_alpha * dest_alpha + /// ``` + Multiply, + /// Invert colors when rendering a white shape. + /// + /// ```ignore + /// dest_color' = ref_color - src_color + /// dest_alpha' = dest_alpha + /// ``` + /// + /// When combining two fragments, subtract the destination color from a constant color + /// using the source color as weight. Has an invert effect with the constant color + /// as base and source color controlling displacement from the base color. + /// A white source color and a white value results in plain invert. + /// The output alpha is same as destination alpha. + Invert, +} + +/// Stencil buffer settings. +#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)] +pub enum Stencil { + /// Draw to stencil buffer. + Clip(u8), + /// Draw pixels that have stencil value. + Inside(u8), + /// Draw pixels that does not have stencil value. + Outside(u8), +} diff --git a/src/graphics_draw_state.rs b/src/graphics_draw_state.rs deleted file mode 100644 index 2aa55f4..0000000 --- a/src/graphics_draw_state.rs +++ /dev/null @@ -1,30 +0,0 @@ -use draw_state_lib::state::{ - Blend, - ColorMask, - Depth, - MultiSample, - Rasterizer, - Stencil -}; -use draw_state_lib::target::Rect; - -/// Graphics draw state used for blending, clipping and stencil rendering. -#[derive(Copy, Clone, PartialEq, Debug, PartialOrd)] -pub struct DrawState { - /// How to rasterize geometric primitives. - pub rasterizer: Rasterizer, - /// Multi-sampling mode - pub multi_sample: Option, - /// Scissor mask to use. If set, no pixel outside of this rectangle (in screen space) will be - /// written to as a result of rendering. - pub scissor: Option, - /// Stencil test to use. If None, no stencil testing is done. - pub stencil: Option, - /// Depth test to use. If None, no depth testing is done. - pub depth: Option, - /// Blend function to use. If None, no blending is done. - pub blend: Option, - /// Color mask to use. Each flag indicates that the given color channel can be written to, and - /// they can be OR'd together. - pub color_mask: ColorMask, -} diff --git a/src/inside_draw_state.rs b/src/inside_draw_state.rs deleted file mode 100644 index 62f97a3..0000000 --- a/src/inside_draw_state.rs +++ /dev/null @@ -1,53 +0,0 @@ -use draw_state_lib::state::*; -use DrawState; - -static INSIDE_DRAW_STATE: &'static DrawState = - &DrawState { - rasterizer: Rasterizer { - front_face: FrontFace::CounterClockwise, - method: RasterMethod::Fill( - CullFace::Nothing - ), - offset: None, - samples: None - }, - multi_sample: None, - scissor: None, - stencil: Some(Stencil { - front: StencilSide { - fun: Comparison::Equal, - mask_read: 255, - mask_write: 0, - op_fail: StencilOp::Keep, - op_depth_fail: StencilOp::Keep, - op_pass: StencilOp::Keep, - }, - back: StencilSide { - fun: Comparison::Equal, - mask_read: 255, - mask_write: 0, - op_fail: StencilOp::Keep, - op_depth_fail: StencilOp::Keep, - op_pass: StencilOp::Keep, - }, - }), - depth: None, - blend: Some(Blend { - color: BlendChannel { - equation: Equation::Add, - source: Factor::ZeroPlus(BlendValue::SourceAlpha), - destination: Factor::OneMinus(BlendValue::SourceAlpha), - }, - alpha: BlendChannel { - equation: Equation::Add, - source: Factor::One, - destination: Factor::One, - }, - }), - color_mask: MASK_ALL, - }; - -/// Returns a default draw state that does additive blending and no culling. -pub fn inside_draw_state() -> &'static DrawState { - INSIDE_DRAW_STATE -} diff --git a/src/lib.rs b/src/lib.rs index 7944ce1..6ced85b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,11 +8,9 @@ extern crate vecmath; extern crate texture; extern crate read_color; extern crate interpolation; -extern crate draw_state as draw_state_lib; extern crate viewport; pub use texture::ImageSize; -pub use draw_state_lib as draw_state; pub use viewport::Viewport; pub use graphics::Graphics; @@ -27,12 +25,8 @@ pub use circle_arc::CircleArc; pub use image::Image; pub use polygon::Polygon; pub use text::Text; -pub use default_draw_state::default_draw_state; -pub use clip_draw_state::clip_draw_state; -pub use inside_draw_state::inside_draw_state; -pub use outside_draw_state::outside_draw_state; pub use context::Context; -pub use graphics_draw_state::DrawState; +pub use draw_state::DrawState; /// Any triangulation method called on the back-end /// never exceeds this number of vertices. @@ -44,12 +38,8 @@ mod source_rectangled; mod rectangled; mod transformed; mod colored; -mod default_draw_state; -mod clip_draw_state; -mod inside_draw_state; -mod outside_draw_state; -mod graphics_draw_state; +pub mod draw_state; pub mod character; pub mod context; pub mod color; @@ -91,7 +81,7 @@ pub fn image( ) where G: Graphics { - Image::new().draw(image, default_draw_state(), transform, g); + Image::new().draw(image, &Default::default(), transform, g); } /// Draws ellipse. @@ -103,7 +93,7 @@ pub fn ellipse, G>( ) where G: Graphics { - Ellipse::new(color).draw(rect, default_draw_state(), transform, g); + Ellipse::new(color).draw(rect, &Default::default(), transform, g); } /// Draws arc @@ -118,7 +108,8 @@ pub fn circle_arc, G>( ) where G: Graphics { - CircleArc::new(color, radius, start, end).draw(rect, default_draw_state(), transform, g); + CircleArc::new(color, radius, start, end) + .draw(rect, &Default::default(), transform, g); } /// Draws rectangle. @@ -130,7 +121,7 @@ pub fn rectangle, G>( ) where G: Graphics { - Rectangle::new(color).draw(rect, default_draw_state(), transform, g); + Rectangle::new(color).draw(rect, &Default::default(), transform, g); } /// Draws polygon. @@ -142,7 +133,7 @@ pub fn polygon( ) where G: Graphics { - Polygon::new(color).draw(polygon, default_draw_state(), transform, g); + Polygon::new(color).draw(polygon, &Default::default(), transform, g); } /// Draws line. @@ -155,7 +146,7 @@ pub fn line, G>( ) where G: Graphics { - Line::new(color, radius).draw(line, default_draw_state(), transform, g) + Line::new(color, radius).draw(line, &Default::default(), transform, g) } /// Draws text. @@ -171,5 +162,6 @@ pub fn text( C: character::CharacterCache, G: Graphics::Texture> { - Text::new_color(color, font_size).draw(text, cache, default_draw_state(), transform, g) + Text::new_color(color, font_size) + .draw(text, cache, &Default::default(), transform, g) } diff --git a/src/math.rs b/src/math.rs index 8b7d314..2204b8d 100644 --- a/src/math.rs +++ b/src/math.rs @@ -41,7 +41,7 @@ pub type Vec3d = vecmath::Vector3; /// Creates a perpendicular vector. #[inline(always)] -pub fn perp(v: [T; 2]) -> [T; 2] +pub fn perp(v: [T; 2]) -> [T; 2] where T: Float { [-v[1], v[0]] @@ -53,7 +53,7 @@ pub fn perp(v: [T; 2]) -> [T; 2] /// In absolute coordinates, the x axis points to the right, /// and the y axis points down on the screen. #[inline(always)] -pub fn abs_transform(w: T, h: T) -> Matrix2d +pub fn abs_transform(w: T, h: T) -> Matrix2d where T: Float { use vecmath::traits::{ One, FromPrimitive, Zero }; @@ -69,7 +69,7 @@ pub fn abs_transform(w: T, h: T) -> Matrix2d /// Creates a translation matrix. #[inline(always)] -pub fn translate(v: Vec2d) -> Matrix2d +pub fn translate(v: Vec2d) -> Matrix2d where T: Float { use vecmath::traits::{ One, Zero }; @@ -82,7 +82,7 @@ pub fn translate(v: Vec2d) -> Matrix2d /// Creates a rotation matrix. #[inline(always)] -pub fn rotate_radians(angle: T) -> Matrix2d +pub fn rotate_radians(angle: T) -> Matrix2d where T: Float { use vecmath::traits::Zero; @@ -99,7 +99,7 @@ pub fn rotate_radians(angle: T) -> Matrix2d /// Leaves x axis unchanged if the /// point to look at is the origin. #[inline(always)] -pub fn orient(x: T, y: T) -> Matrix2d +pub fn orient(x: T, y: T) -> Matrix2d where T: Float { use vecmath::traits::Zero; @@ -119,7 +119,7 @@ pub fn orient(x: T, y: T) -> Matrix2d /// Create a scale matrix. #[inline(always)] -pub fn scale(sx: T, sy: T) -> Matrix2d +pub fn scale(sx: T, sy: T) -> Matrix2d where T: Float { use vecmath::traits::Zero; @@ -131,7 +131,7 @@ pub fn scale(sx: T, sy: T) -> Matrix2d /// Create a shear matrix. #[inline(always)] -pub fn shear(v: Vec2d) -> Matrix2d +pub fn shear(v: Vec2d) -> Matrix2d where T: Float { use vecmath::traits::{ Zero, One }; @@ -144,7 +144,7 @@ pub fn shear(v: Vec2d) -> Matrix2d /// Create an identity matrix. #[inline(always)] -pub fn identity() -> Matrix2d +pub fn identity() -> Matrix2d where T: Float { use vecmath::traits::{ Zero, One }; @@ -157,7 +157,7 @@ pub fn identity() -> Matrix2d /// Extract scale information from matrix. #[inline(always)] -pub fn get_scale(m: Matrix2d) -> Vec2d +pub fn get_scale(m: Matrix2d) -> Vec2d where T: Float { [ @@ -169,7 +169,7 @@ pub fn get_scale(m: Matrix2d) -> Vec2d /// Compute the shortest vector from point to ray. /// A ray stores starting point and directional vector. #[inline(always)] -pub fn separation(ray: Ray, v: Vec2d) -> Vec2d +pub fn separation(ray: Ray, v: Vec2d) -> Vec2d where T: Float { // Get the directional vector. @@ -191,7 +191,7 @@ pub fn separation(ray: Ray, v: Vec2d) -> Vec2d /// The separation returned can be used /// to solve collision of rectangles. #[inline(always)] -pub fn least_separation_4( +pub fn least_separation_4( sep1: Vec2d, sep2: Vec2d, sep3: Vec2d, @@ -221,7 +221,7 @@ pub fn least_separation_4( /// Shrinks a rectangle by a factor on all sides. #[inline(always)] -pub fn margin_rectangle(rect: Rectangle, m: T) -> Rectangle +pub fn margin_rectangle(rect: Rectangle, m: T) -> Rectangle where T: Float { use vecmath::traits::{ Zero, FromPrimitive }; @@ -248,7 +248,7 @@ pub fn margin_rectangle(rect: Rectangle, m: T) -> Rectangle /// Computes a relative rectangle using the rectangle as a tile. #[inline(always)] -pub fn relative_rectangle( +pub fn relative_rectangle( rect: Rectangle, v: Vec2d ) -> Rectangle @@ -266,7 +266,7 @@ pub fn relative_rectangle( /// The area of the overlapping rectangle is positive. /// A shared edge or corner is not considered overlap. #[inline(always)] -pub fn overlap_rectangle( +pub fn overlap_rectangle( a: Rectangle, b: Rectangle ) -> Option> @@ -362,7 +362,7 @@ mod test_modular_offset { /// /// A simple polygon is one that does not intersect itself. /// Source: http://en.wikipedia.org/wiki/Polygon_area#Simple_polygons -pub fn area_centroid(polygon: Polygon) -> (Area, Vec2d) +pub fn area_centroid(polygon: Polygon) -> (Area, Vec2d) where T: Float { use vecmath::traits::{ Zero, FromPrimitive }; @@ -395,7 +395,7 @@ pub fn area_centroid(polygon: Polygon) -> (Area, Vec2d) /// /// A simple polygon is one that does not intersect itself. #[inline(always)] -pub fn area(polygon: Polygon) -> T +pub fn area(polygon: Polygon) -> T where T: Float { let (res, _) = area_centroid(polygon); @@ -406,7 +406,7 @@ pub fn area(polygon: Polygon) -> T /// /// A simple polygon is one that does not intersect itself. #[inline(always)] -pub fn centroid(polygon: Polygon) -> Vec2d +pub fn centroid(polygon: Polygon) -> Vec2d where T: Float { let (_, res) = area_centroid(polygon); @@ -419,7 +419,7 @@ pub fn centroid(polygon: Polygon) -> Vec2d /// with the vector between point and starting point of line. /// One side of the line has opposite sign of the other. #[inline(always)] -pub fn line_side(line: Line, v: Vec2d) -> T +pub fn line_side(line: Line, v: Vec2d) -> T where T: Float { let (ax, ay) = (line[0], line[1]); @@ -432,7 +432,7 @@ pub fn line_side(line: Line, v: Vec2d) -> T /// This is done by computing a `side` number for each edge. /// If the number is inside if it is on the same side for all edges. /// Might break for very small triangles. -pub fn inside_triangle(triangle: Triangle, v: Vec2d) -> bool +pub fn inside_triangle(triangle: Triangle, v: Vec2d) -> bool where T: Float { use vecmath::traits::Zero; @@ -466,7 +466,7 @@ pub fn inside_triangle(triangle: Triangle, v: Vec2d) -> bool /// The triangle is considered clockwise if the third vertex is on the line /// between the two first vertices. #[inline(always)] -pub fn triangle_face(triangle: Triangle) -> bool +pub fn triangle_face(triangle: Triangle) -> bool where T: Float { use vecmath::traits::Zero; @@ -505,7 +505,7 @@ mod test_triangle { /// Transforms from cartesian coordinates to barycentric. #[inline(always)] -pub fn to_barycentric( +pub fn to_barycentric( triangle: Triangle, pos: Vec2d ) -> Vec3d @@ -531,7 +531,7 @@ pub fn to_barycentric( /// Transforms from barycentric coordinates to cartesian. #[inline(always)] -pub fn from_barycentric( +pub fn from_barycentric( triangle: Triangle, lambda: Vec3d ) -> Vec2d diff --git a/src/outside_draw_state.rs b/src/outside_draw_state.rs deleted file mode 100644 index fe74aa6..0000000 --- a/src/outside_draw_state.rs +++ /dev/null @@ -1,53 +0,0 @@ -use draw_state_lib::state::*; -use DrawState; - -static OUTSIDE_DRAW_STATE: &'static DrawState = - &DrawState { - rasterizer: Rasterizer { - front_face: FrontFace::CounterClockwise, - method: RasterMethod::Fill( - CullFace::Nothing - ), - offset: None, - samples: None, - }, - multi_sample: None, - scissor: None, - stencil: Some(Stencil { - front: StencilSide { - fun: Comparison::NotEqual, - mask_read: 255, - mask_write: 0, - op_fail: StencilOp::Keep, - op_depth_fail: StencilOp::Keep, - op_pass: StencilOp::Keep, - }, - back: StencilSide { - fun: Comparison::NotEqual, - mask_read: 255, - mask_write: 0, - op_fail: StencilOp::Keep, - op_depth_fail: StencilOp::Keep, - op_pass: StencilOp::Keep, - }, - }), - depth: None, - blend: Some(Blend { - color: BlendChannel { - equation: Equation::Add, - source: Factor::ZeroPlus(BlendValue::SourceAlpha), - destination: Factor::OneMinus(BlendValue::SourceAlpha), - }, - alpha: BlendChannel { - equation: Equation::Add, - source: Factor::One, - destination: Factor::One, - }, - }), - color_mask: MASK_ALL, - }; - -/// Returns a default draw state that does additive blending and no culling. -pub fn outside_draw_state() -> &'static DrawState { - OUTSIDE_DRAW_STATE -}