graphics/
graphics.rs

1use crate::{
2    types::{self, Matrix2d, Scalar},
3    CircleArc, DrawState, Ellipse, Image, ImageSize, Line, Polygon, Rectangle,
4};
5
6/// Implemented by all graphics back-ends.
7///
8/// [An example back-end using raw OpenGL](https://github.com/PistonDevelopers/opengl_graphics)
9///
10/// By default, this design uses triangles as graphics primitives.
11/// This is supported by all GPUs and easy to implement in shader languages.
12///
13/// Default trait methods can be overridden for better performance or higher
14/// quality.
15///
16/// When drawing, use this trait as generic constraint:
17///
18/// ```
19/// use graphics::{Context, Graphics};
20///
21/// fn draw<G: Graphics>(c: &Context, g: &mut G) {
22///     //...
23/// }
24/// ```
25///
26/// Color space is sRGB.
27///
28/// ### Notice for back-end authors
29///
30/// When sRGB is enabled for a back-end shader, the gamma must be converted
31/// to linear space when used as vertex color or uniform parameter.
32/// To convert gamma, use `color::gamma_srgb_to_linear`.
33///
34/// For more information, see
35/// https://github.com/PistonDevelopers/piston/issues/1014.
36pub trait Graphics: Sized {
37    /// The texture type associated with the back-end.
38    ///
39    /// In generic code, this type is often unknown.
40    /// This might lead to more boilerplate code:
41    ///
42    /// ```
43    /// use graphics::{Context, Graphics, ImageSize};
44    ///
45    /// fn draw_texture<G, T>(c: &Context, g: &mut G)
46    /// where
47    ///     G: Graphics<Texture = T>,
48    ///     T: ImageSize,
49    /// {
50    ///     //...
51    /// }
52    /// ```
53    ///
54    /// Code written specifically for one back-end can be easier to write.
55    /// Later, when the code is done, it can be refactored into generic code.
56    type Texture: ImageSize;
57
58    /// Clears background with a color.
59    ///
60    /// The color should replace the values in the buffer.
61    ///
62    /// Color space is sRGB.
63    fn clear_color(&mut self, color: types::Color);
64
65    /// Clears stencil buffer with a value, usually 0.
66    ///
67    /// A stencil buffer contains values that are not visible on the screen.
68    /// These values are used to test against the pixel to paint.
69    ///
70    /// If you are drawing a shape for clipping and forgot to clear the
71    /// stencil buffer, then the clipping shape will carry over in next frame
72    /// and cause artifacts.
73    fn clear_stencil(&mut self, value: u8);
74
75    /// Renders list of 2d triangles using a solid color.
76    ///
77    /// All vertices share the same color.
78    ///
79    /// The back-end calls the closure with a closure to receive vertices.
80    /// First, the back-end sets up shaders and such to prepare.
81    /// Then it calls the closure, which calls back with chunks of vertices.
82    /// The number of vertices per chunk never exceeds
83    /// `BACK_END_MAX_VERTEX_COUNT`.
84    /// Vertex positions are encoded `[[x0, y0], [x1, y1], ...]`.
85    ///
86    /// Color space is sRGB.
87    fn tri_list<F>(&mut self, draw_state: &DrawState, color: &[f32; 4], f: F)
88    where
89        F: FnMut(&mut dyn FnMut(&[[f32; 2]]));
90
91    /// Same as `tri_list`, but with individual vertex colors.
92    ///
93    /// Argument are `|vertices: &[[f32; 2], colors: &[[f32; 4]]]|`.
94    fn tri_list_c<F>(&mut self, draw_state: &DrawState, f: F)
95    where
96        F: FnMut(&mut dyn FnMut(&[[f32; 2]], &[[f32; 4]]));
97
98    /// Renders list of 2d triangles using a color and a texture.
99    ///
100    /// All vertices share the same color.
101    ///
102    /// Tip: For objects of different colors, use grayscale textures.
103    /// The texture color gets multiplied with the color.
104    ///
105    /// A texture coordinate is assigned per vertex (from [0, 0] to [1, 1]).
106    ///
107    /// The back-end calls the closure with a closure to receive vertices.
108    /// First, the back-end sets up shaders and such to prepare.
109    /// Then it calls the closure, which calls back with chunks of vertices.
110    /// The number of vertices per chunk never exceeds
111    /// `BACK_END_MAX_VERTEX_COUNT`.
112    /// Vertex positions are encoded `[[x0, y0], [x1, y1], ...]`.
113    /// Texture coordinates are encoded `[[u0, v0], [u1, v1], ...]`.
114    ///
115    /// Chunks uses separate buffer for vertex positions and texture coordinates.
116    /// Arguments are `|vertices: &[[f32; 2]], texture_coords: &[[f32; 2]]|`.
117    ///
118    /// Color space is sRGB.
119    fn tri_list_uv<F>(
120        &mut self,
121        draw_state: &DrawState,
122        color: &[f32; 4],
123        texture: &<Self as Graphics>::Texture,
124        f: F,
125    ) where
126        F: FnMut(&mut dyn FnMut(&[[f32; 2]], &[[f32; 2]]));
127
128    /// Same as `tri_list_uv`, but with individual vertex colors.
129    ///
130    /// Argument are `|vertices: &[[f32; 2], texture_coors: &[[f32; 2]], colors: &[[f32; 4]]]|`.
131    fn tri_list_uv_c<F>(
132        &mut self,
133        draw_state: &DrawState,
134        texture: &<Self as Graphics>::Texture,
135        f: F,
136    ) where
137        F: FnMut(&mut dyn FnMut(&[[f32; 2]], &[[f32; 2]], &[[f32; 4]]));
138
139    /// Draws a rectangle.
140    ///
141    /// Can be overriden in the back-end for higher performance.
142    ///
143    /// Instead of calling this directly, use `Rectangle::draw`.
144    #[inline(always)]
145    fn rectangle<R: Into<types::Rectangle>>(
146        &mut self,
147        r: &Rectangle,
148        rectangle: R,
149        draw_state: &DrawState,
150        transform: Matrix2d,
151    ) {
152        r.draw_tri(rectangle, draw_state, transform, self);
153    }
154
155    /// Draws a polygon.
156    ///
157    /// Can be overridden in the back-end for higher performance.
158    ///
159    /// Instead of calling this directly, use `Polygon::draw`.
160    #[inline(always)]
161    fn polygon(
162        &mut self,
163        p: &Polygon,
164        polygon: types::Polygon<'_>,
165        draw_state: &DrawState,
166        transform: Matrix2d,
167    ) {
168        p.draw_tri(polygon, draw_state, transform, self);
169    }
170
171    /// Draws a tweened polygon using linear interpolation.
172    ///
173    /// Can be overridden in the back-end for higher performance.
174    ///
175    /// Instead of calling this directly, use `Polygon::draw_tween_lerp`.
176    #[inline(always)]
177    fn polygon_tween_lerp(
178        &mut self,
179        p: &Polygon,
180        polygons: types::Polygons<'_>,
181        tween_factor: Scalar,
182        draw_state: &DrawState,
183        transform: Matrix2d,
184    ) {
185        p.draw_tween_lerp_tri(polygons, tween_factor, draw_state, transform, self);
186    }
187
188    /// Draws image.
189    ///
190    /// Can be overridden in the back-end for higher performance.
191    ///
192    /// Instead of calling this directly, use `Image::draw`.
193    #[inline(always)]
194    fn image(
195        &mut self,
196        image: &Image,
197        texture: &Self::Texture,
198        draw_state: &DrawState,
199        transform: Matrix2d,
200    ) {
201        image.draw_tri(texture, draw_state, transform, self);
202    }
203
204    /// Draws ellipse.
205    ///
206    /// Can be overridden in the back-end for higher performance.
207    ///
208    /// Instead of calling this directly, use `Ellipse::draw`.
209    #[inline(always)]
210    fn ellipse<R: Into<types::Rectangle>>(
211        &mut self,
212        e: &Ellipse,
213        rectangle: R,
214        draw_state: &DrawState,
215        transform: Matrix2d,
216    ) {
217        e.draw_tri(rectangle, draw_state, transform, self);
218    }
219
220    /// Draws line.
221    ///
222    /// Can be overridden in the back-end for higher performance.
223    ///
224    /// Instead of calling this directly, use `Line::draw`.
225    #[inline(always)]
226    fn line<L: Into<types::Line>>(
227        &mut self,
228        l: &Line,
229        line: L,
230        draw_state: &DrawState,
231        transform: Matrix2d,
232    ) {
233        l.draw_tri(line, draw_state, transform, self);
234    }
235
236    /// Draws circle arc.
237    ///
238    /// Can be overriden in the back-end for higher performance.
239    ///
240    /// Instead of calling this directly, use `CircleArc::draw`.
241    #[inline(always)]
242    fn circle_arc<R: Into<types::Rectangle>>(
243        &mut self,
244        c: &CircleArc,
245        rectangle: R,
246        draw_state: &DrawState,
247        transform: Matrix2d,
248    ) {
249        c.draw_tri(rectangle, draw_state, transform, self);
250    }
251}