1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#[macro_use]
extern crate glium;
use glium::index::PrimitiveType;
use glium::program::ShaderStage;
use glium::{Display, Surface};
use glutin::surface::WindowSurface;
use support::{ApplicationContext, State};
mod support;
#[derive(Copy, Clone)]
struct Vertex {
position: [f32; 2],
}
implement_vertex!(Vertex, position);
struct Application {
pub vertex_buffer: glium::VertexBuffer<Vertex>,
pub index_buffer: glium::IndexBuffer<u16>,
pub program: glium::Program,
pub i: i32,
}
impl ApplicationContext for Application {
const WINDOW_TITLE:&'static str = "Glium subroutines example";
fn new(display: &Display<WindowSurface>) -> Self {
// building the vertex buffer, which contains all the vertices that we will draw
let vertex_buffer = {
glium::VertexBuffer::new(
display,
&[
Vertex {
position: [-0.5, -0.5],
},
Vertex {
position: [0.0, 0.5],
},
Vertex {
position: [0.5, -0.5],
},
],
)
.unwrap()
};
// building the index buffer
let index_buffer =
glium::IndexBuffer::new(display, PrimitiveType::TrianglesList, &[0u16, 1, 2]).unwrap();
// compiling shaders and linking them together
let program = program!(display,
150 => {
vertex: "
#version 150
uniform mat4 matrix;
in vec2 position;
void main() {
gl_Position = vec4(position, 0.0, 1.0) * matrix;
}
",
fragment: "
#version 150
#extension GL_ARB_shader_subroutine : require
out vec4 fragColor;
subroutine vec4 color_t();
subroutine uniform color_t Color;
subroutine(color_t)
vec4 ColorRed()
{
return vec4(1, 0, 0, 1);
}
subroutine(color_t)
vec4 ColorBlue()
{
return vec4(0, 0.4, 1, 1);
}
subroutine(color_t)
vec4 ColorYellow()
{
return vec4(1, 1, 0, 1);
}
void main()
{
fragColor = Color();
}
"
},
)
.unwrap();
let i = 0;
Self {
vertex_buffer,
index_buffer,
program,
i,
}
}
fn draw_frame(&mut self, display: &Display<WindowSurface>) {
let mut frame = display.draw();
let subroutine = if self.i < 40 {
"ColorYellow"
} else if self.i < 80 {
"ColorBlue"
} else {
"ColorRed"
};
// building the uniforms
let uniforms = uniform! {
matrix: [
[1.0, 0.0, 0.0, 0.0],
[0.0, 1.0, 0.0, 0.0],
[0.0, 0.0, 1.0, 0.0],
[0.0, 0.0, 0.0, 1.0f32]
],
Color: (subroutine, ShaderStage::Fragment)
};
// drawing a frame
frame.clear_color(0.0, 0.0, 0.0, 0.0);
frame
.draw(
&self.vertex_buffer,
&self.index_buffer,
&self.program,
&uniforms,
&Default::default(),
)
.unwrap();
frame.finish().unwrap();
}
fn update(&mut self) {
self.i = (self.i + 1) % 120;
}
}
fn main() {
State::<Application>::run_loop();
}