glowygraph/render2/
mod.rs

1use glium::{self, Surface};
2use cgmath;
3
4/// Node is used to pass nodes into the renderer.
5#[derive(Copy, Clone, Debug)]
6pub struct Node {
7    pub position: [f32; 2],
8    pub inner_color: [f32; 4],
9    /// Decreasing falloff makes the nodes brightness more centered at the middle and increasing it makes it consistent.
10    pub falloff: f32,
11    pub falloff_color: [f32; 4],
12    pub falloff_radius: f32,
13    pub inner_radius: f32,
14}
15
16impl From<cgmath::Point2<f32>> for Node {
17    fn from(point: cgmath::Point2<f32>) -> Node {
18        Node {
19            position: point.into(),
20            inner_color: [1.0, 1.0, 1.0, 1.0],
21            falloff: 0.5,
22            falloff_color: [1.0, 1.0, 1.0, 1.0],
23            // These radii will only work in certian scenarios, but can be modified.
24            falloff_radius: 0.01,
25            inner_radius: 0.002,
26        }
27    }
28}
29
30implement_vertex!(
31    Node,
32    position,
33    inner_color,
34    falloff,
35    falloff_color,
36    falloff_radius,
37    inner_radius
38);
39
40/// QBezier is used to pass a quadratic bezier curve into the shader with interpolating values.
41#[derive(Copy, Clone, Debug)]
42pub struct QBezier {
43    pub position0: [f32; 2],
44    pub position1: [f32; 2],
45    pub position2: [f32; 2],
46    pub inner_color0: [f32; 4],
47    pub inner_color1: [f32; 4],
48    pub falloff_color0: [f32; 4],
49    pub falloff_color1: [f32; 4],
50    /// Decreasing falloff makes the nodes brightness more centered at the middle and increasing it makes it consistent.
51    pub falloff0: f32,
52    pub falloff1: f32,
53    pub falloff_radius0: f32,
54    pub falloff_radius1: f32,
55    pub inner_radius0: f32,
56    pub inner_radius1: f32,
57}
58
59implement_vertex!(
60    QBezier,
61    position0,
62    position1,
63    position2,
64    inner_color0,
65    inner_color1,
66    falloff0,
67    falloff1,
68    falloff_color0,
69    falloff_color1,
70    falloff_radius0,
71    falloff_radius1,
72    inner_radius0,
73    inner_radius1
74);
75
76/// A Renderer is tied to the lifetime of the glium Display and making one builds a GLSL program internally.
77pub struct Renderer<'a, D>
78where
79    D: 'a,
80{
81    display: &'a D,
82    node_program: glium::Program,
83    round_edge_program: glium::Program,
84    flat_edge_program: glium::Program,
85    round_qbezier_program: glium::Program,
86    flat_qbezier_program: glium::Program,
87    params: glium::DrawParameters<'a>,
88}
89
90impl<'a, D> Renderer<'a, D>
91where
92    D: glium::backend::Facade,
93{
94    /// Make a new Renderer from a Facade.
95    pub fn new(display: &'a D) -> Self {
96        Renderer {
97            display: display,
98            node_program: glium::Program::from_source(
99                display,
100                include_str!("node.vert"),
101                include_str!("node.frag"),
102                Some(include_str!("node.geom")),
103            ).unwrap(),
104            round_edge_program: glium::Program::from_source(
105                display,
106                include_str!("node.vert"),
107                include_str!("node.frag"),
108                Some(include_str!("round_edge.geom")),
109            ).unwrap(),
110            flat_edge_program: glium::Program::from_source(
111                display,
112                include_str!("node.vert"),
113                include_str!("node.frag"),
114                Some(include_str!("flat_edge.geom")),
115            ).unwrap(),
116            round_qbezier_program: glium::Program::from_source(
117                display,
118                include_str!("qbezier.vert"),
119                include_str!("qbezier.frag"),
120                Some(include_str!("round_qbezier.geom")),
121            ).unwrap(),
122            flat_qbezier_program: glium::Program::from_source(
123                display,
124                include_str!("qbezier.vert"),
125                include_str!("qbezier.frag"),
126                Some(include_str!("flat_qbezier.geom")),
127            ).unwrap(),
128            params: glium::DrawParameters {
129                blend: glium::Blend::alpha_blending(),
130                ..Default::default()
131            },
132        }
133    }
134
135    /// Take a series of nodes and draw them in parallel on the GPU.
136    pub fn render_nodes<S>(
137        &self,
138        target: &mut S,
139        modelview: [[f32; 3]; 3],
140        projection: [[f32; 3]; 3],
141        nodes: &[Node],
142    ) where
143        S: Surface,
144    {
145        let vertex_buffer = glium::VertexBuffer::new(self.display, nodes).unwrap();
146        let indices = glium::index::NoIndices(glium::index::PrimitiveType::Points);
147
148        let uniforms = uniform! {
149            modelview: modelview,
150            projection: projection,
151        };
152
153        target
154            .draw(
155                &vertex_buffer,
156                &indices,
157                &self.node_program,
158                &uniforms,
159                &self.params,
160            )
161            .unwrap();
162    }
163
164    /// Take a series of lines (edges) and draw them in parallel on the GPU.
165    ///
166    /// These will have round ends.
167    pub fn render_edges_round<S>(
168        &self,
169        target: &mut S,
170        modelview: [[f32; 3]; 3],
171        projection: [[f32; 3]; 3],
172        edges: &[Node],
173    ) where
174        S: Surface,
175    {
176        let vertex_buffer = glium::VertexBuffer::new(self.display, edges).unwrap();
177        let indices = glium::index::NoIndices(glium::index::PrimitiveType::LinesList);
178
179        let uniforms = uniform! {
180            modelview: modelview,
181            projection: projection,
182        };
183
184        target
185            .draw(
186                &vertex_buffer,
187                &indices,
188                &self.round_edge_program,
189                &uniforms,
190                &self.params,
191            )
192            .unwrap();
193    }
194
195    /// Take a series of lines (edges) and draw them in parallel on the GPU.
196    ///
197    /// These will have flat ends.
198    pub fn render_edges_flat<S>(
199        &self,
200        target: &mut S,
201        modelview: [[f32; 3]; 3],
202        projection: [[f32; 3]; 3],
203        edges: &[Node],
204    ) where
205        S: Surface,
206    {
207        let vertex_buffer = glium::VertexBuffer::new(self.display, edges).unwrap();
208        let indices = glium::index::NoIndices(glium::index::PrimitiveType::LinesList);
209
210        let uniforms = uniform! {
211            modelview: modelview,
212            projection: projection,
213        };
214
215        target
216            .draw(
217                &vertex_buffer,
218                &indices,
219                &self.flat_edge_program,
220                &uniforms,
221                &self.params,
222            )
223            .unwrap();
224    }
225
226    /// Take a series of triangles (quadratic bezier curves) and draw them in parallel on the GPU.
227    ///
228    /// These will have round ends.
229    pub fn render_qbeziers_round<S>(
230        &self,
231        target: &mut S,
232        modelview: [[f32; 3]; 3],
233        projection: [[f32; 3]; 3],
234        qbeziers: &[QBezier],
235    ) where
236        S: Surface,
237    {
238        let vertex_buffer = glium::VertexBuffer::new(self.display, qbeziers).unwrap();
239        let indices = glium::index::NoIndices(glium::index::PrimitiveType::Points);
240
241        let uniforms = uniform! {
242            modelview: modelview,
243            projection: projection,
244        };
245
246        target
247            .draw(
248                &vertex_buffer,
249                &indices,
250                &self.round_qbezier_program,
251                &uniforms,
252                &self.params,
253            )
254            .unwrap();
255    }
256
257    /// Take a series of triangles (quadratic bezier curves) and draw them in parallel on the GPU.
258    ///
259    /// These will have flat ends.
260    pub fn render_qbeziers_flat<S>(
261        &self,
262        target: &mut S,
263        modelview: [[f32; 3]; 3],
264        projection: [[f32; 3]; 3],
265        qbeziers: &[QBezier],
266    ) where
267        S: Surface,
268    {
269        let vertex_buffer = glium::VertexBuffer::new(self.display, qbeziers).unwrap();
270        let indices = glium::index::NoIndices(glium::index::PrimitiveType::Points);
271
272        let uniforms = uniform! {
273            modelview: modelview,
274            projection: projection,
275        };
276
277        target
278            .draw(
279                &vertex_buffer,
280                &indices,
281                &self.flat_qbezier_program,
282                &uniforms,
283                &self.params,
284            )
285            .unwrap();
286    }
287}