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}