-
Notifications
You must be signed in to change notification settings - Fork 59
/
Copy pathdynamic_uniform_interface.rs
151 lines (132 loc) · 3.97 KB
/
dynamic_uniform_interface.rs
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
//! This example shows you how to lookup dynamically uniforms into shaders to implement various kind
//! of situations. This feature is very likely to be interesting for anyone who would like to
//! implement a GUI, where the interface of the shader programs are not known statically, for
//! instance.
//!
//! This example looks up the time and the triangle position on the fly, without using the uniform
//! interface.
//!
//! Press the <left>, <right>, <up>, <down> actions to move the triangle on the screen.
//!
//! <https://docs.rs/luminance>
use crate::{
shared::{FragSlot, Vertex},
Example, InputAction, LoopFeedback, PlatformServices,
};
use luminance::{
backend::Backend,
context::Context,
dim::{Dim2, Size2},
framebuffer::{Back, Framebuffer},
pipeline::PipelineState,
primitive::Triangle,
render_state::RenderState,
shader::{Program, ProgramBuilder},
vertex_entity::{VertexEntity, VertexEntityBuilder, View},
vertex_storage::{Interleaved, Interleaving},
};
const VS: &'static str = include_str!("displacement-vs.glsl");
const FS: &'static str = include_str!("displacement-fs.glsl");
// Only one triangle this time.
const TRI_VERTICES: [Vertex; 3] = [
// triangle – an RGB one
//
Vertex::new(
mint::Vector2 { x: 0.5, y: -0.5 },
mint::Vector3 {
x: 0.,
y: 1.,
z: 0.,
},
),
Vertex::new(
mint::Vector2 { x: 0., y: 0.5 },
mint::Vector3 {
x: 0.,
y: 0.,
z: 1.,
},
),
Vertex::new(
mint::Vector2 { x: -0.5, y: -0.5 },
mint::Vector3 {
x: 1.,
y: 0.,
z: 0.,
},
),
];
pub struct LocalExample {
program: Program<Vertex, (), Triangle, FragSlot, ()>, // no uniform environment; we want dynamic lookups
triangle: VertexEntity<Vertex, Triangle, Interleaving>,
triangle_pos: mint::Vector2<f32>,
back_buffer: Framebuffer<Dim2, Back<FragSlot>, Back<()>>,
}
impl Example for LocalExample {
type Err = luminance::backend::Error;
const TITLE: &'static str = "Dynamic uniform lookup";
fn bootstrap(
[width, height]: [u32; 2],
_: &mut impl PlatformServices,
ctx: &mut Context<impl Backend>,
) -> Result<Self, Self::Err> {
// notice that we don’t set a uniform interface here: we’re going to look it up on the fly
let program = ctx.new_program(
ProgramBuilder::new()
.add_vertex_stage(VS)
.no_primitive_stage()
.add_shading_stage(FS),
)?;
let triangle = ctx.new_vertex_entity(
VertexEntityBuilder::new().add_vertices(Interleaved::new().set_vertices(TRI_VERTICES)),
)?;
let triangle_pos = mint::Vector2 { x: 0., y: 0. };
let back_buffer = ctx.back_buffer(Size2::new(width, height))?;
Ok(Self {
program,
triangle,
triangle_pos,
back_buffer,
})
}
fn render_frame(
mut self,
t: f32,
actions: impl Iterator<Item = InputAction>,
ctx: &mut Context<impl Backend>,
) -> Result<LoopFeedback<Self>, Self::Err> {
for action in actions {
match action {
InputAction::Quit => return Ok(LoopFeedback::Exit),
InputAction::Left => {
self.triangle_pos.x -= 0.1;
}
InputAction::Right => {
self.triangle_pos.x += 0.1;
}
InputAction::Forward => {
self.triangle_pos.y += 0.1;
}
InputAction::Backward => {
self.triangle_pos.y -= 0.1;
}
_ => (),
}
}
let program = &self.program;
let triangle = &self.triangle;
let triangle_pos = &self.triangle_pos;
ctx.with_framebuffer(&self.back_buffer, &PipelineState::default(), |mut frame| {
frame.with_program(program, |mut frame| {
frame.update(|mut update, _| {
update.query_set::<f32>("t", &t)?;
update.query_set::<mint::Vector2<f32>>("triangle_pos", triangle_pos)
})?;
frame.with_render_state(&RenderState::default(), |mut frame| {
frame.render_vertex_entity(triangle.view(..))
})
})
})?;
Ok(LoopFeedback::Continue(self))
}
}