Skip to content

Commit 09290ba

Browse files
committed
[add] multiple triangles demo.
1 parent c95abd4 commit 09290ba

6 files changed

Lines changed: 314 additions & 1 deletion

File tree

Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ members = [
55
"lambda",
66
"crates/lambda-platform",
77
"tools/lambda_rs_demo",
8-
"tools/minimal"
8+
"tools/minimal",
9+
"tools/triangles_demo",
910
]
1011

1112
default-members = [

tools/triangles_demo/Cargo.toml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[package]
2+
name = "lambda_rs_triangles"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[[bin]]
7+
name = "triangles"
8+
path = "src/main.rs"
9+
10+
[dependencies]
11+
lambda = { path = "../../lambda" }
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#version 450
2+
#extension GL_ARB_separate_shader_objects : enable
3+
4+
layout(location = 0) in vec4 vertex_color;
5+
6+
layout(location = 0) out vec4 fragment_color;
7+
8+
void main() {
9+
fragment_color = vertex_color;
10+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#version 450
2+
#extension GL_ARB_separate_shader_objects : enable
3+
4+
5+
layout(location = 0) out vec4 vertex_color;
6+
7+
layout( push_constant ) uniform Block {
8+
vec4 color;
9+
vec2 position;
10+
vec2 scale;
11+
} PushConstants;
12+
13+
vec2 positions[3] = vec2[](
14+
vec2(0.0, -0.5),
15+
vec2(-0.5, 0.5),
16+
vec2(0.5, 0.5)
17+
);
18+
19+
void main() {
20+
vec2 position = positions[gl_VertexIndex] * PushConstants.scale;
21+
vertex_color = PushConstants.color;
22+
gl_Position = vec4((position + PushConstants.position), 0.0, 1.0);
23+
}

tools/triangles_demo/src/main.rs

Lines changed: 261 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,261 @@
1+
use std::rc::Rc;
2+
3+
use lambda::{
4+
core::{
5+
component::{
6+
Component,
7+
RenderableComponent,
8+
},
9+
events::{
10+
Events,
11+
WindowEvent,
12+
},
13+
render::{
14+
command::RenderCommand,
15+
pipeline::{
16+
self,
17+
PipelineStage,
18+
RenderPipeline,
19+
},
20+
render_pass::{
21+
self,
22+
RenderPass,
23+
},
24+
shader::{
25+
Shader,
26+
ShaderBuilder,
27+
ShaderKind,
28+
VirtualShader,
29+
},
30+
viewport,
31+
},
32+
runtime::start_runtime,
33+
},
34+
runtimes::GenericRuntimeBuilder,
35+
};
36+
37+
pub struct TrianglesComponent {
38+
triangle_vertex: Shader,
39+
vertex_shader: Shader,
40+
render_pass: Option<Rc<RenderPass>>,
41+
render_pipeline: Option<Rc<RenderPipeline>>,
42+
width: u32,
43+
height: u32,
44+
}
45+
46+
impl Component<Events> for TrianglesComponent {
47+
fn on_attach(&mut self) {
48+
println!("Attached the DemoComponent.");
49+
}
50+
51+
fn on_detach(&mut self) {}
52+
53+
fn on_event(&mut self, event: &lambda::core::events::Events) {
54+
match event {
55+
Events::Runtime { event, issued_at } => match event {
56+
lambda::core::events::RuntimeEvent::Shutdown => {
57+
println!("Shutting down the runtime");
58+
}
59+
_ => {}
60+
},
61+
Events::Window { event, issued_at } => match event {
62+
WindowEvent::Resize { width, height } => {
63+
println!("Window resized to {}x{}", width, height);
64+
self.width = *width;
65+
self.height = *height;
66+
}
67+
WindowEvent::Close => {
68+
println!("Window closed");
69+
}
70+
},
71+
_ => {}
72+
}
73+
}
74+
75+
fn on_update(&mut self, last_frame: &std::time::Duration) {
76+
match last_frame.as_millis() > 20 {
77+
true => {
78+
println!("[WARN] Last frame took {}ms", last_frame.as_millis());
79+
}
80+
false => {}
81+
}
82+
}
83+
}
84+
85+
#[repr(C)]
86+
#[derive(Debug, Copy, Clone)]
87+
pub struct PushConstant {
88+
color: [f32; 4],
89+
position: [f32; 2],
90+
scale: [f32; 2],
91+
}
92+
93+
pub fn push_constants_to_bytes(push_constants: &PushConstant) -> &[u32] {
94+
let bytes = unsafe {
95+
let size_in_bytes = std::mem::size_of::<PushConstant>();
96+
let size_in_u32 = size_in_bytes / std::mem::size_of::<u32>();
97+
let ptr = push_constants as *const PushConstant as *const u32;
98+
std::slice::from_raw_parts(ptr, size_in_u32)
99+
};
100+
101+
return bytes;
102+
}
103+
104+
/// Implement rendering for the component.
105+
impl RenderableComponent<Events> for TrianglesComponent {
106+
fn on_renderer_attached(
107+
&mut self,
108+
render_context: &mut lambda::core::render::RenderContext,
109+
) {
110+
println!("Attached the demo component to the renderer");
111+
let render_pass =
112+
Rc::new(render_pass::RenderPassBuilder::new().build(&render_context));
113+
114+
self.render_pass = Some(render_pass.clone());
115+
116+
let push_constants_size = std::mem::size_of::<PushConstant>() as u32;
117+
println!("Push constant size: {}", push_constants_size);
118+
let pipeline = Rc::new(
119+
pipeline::RenderPipelineBuilder::new()
120+
.with_push_constant(PipelineStage::VERTEX, push_constants_size)
121+
.build(
122+
render_context,
123+
&self.render_pass.as_ref().unwrap(),
124+
&self.vertex_shader,
125+
&self.triangle_vertex,
126+
),
127+
);
128+
129+
self.render_pipeline = Some(pipeline.clone());
130+
}
131+
132+
fn on_render(
133+
&mut self,
134+
_render_context: &mut lambda::core::render::RenderContext,
135+
) -> Vec<RenderCommand> {
136+
let viewport =
137+
viewport::ViewportBuilder::new().build(self.width, self.height);
138+
139+
let triangle_data = &[
140+
PushConstant {
141+
color: [1.0, 0.0, 0.0, 1.0],
142+
position: [0.0, 0.0],
143+
scale: [0.3, 0.3],
144+
},
145+
PushConstant {
146+
color: [0.0, 1.0, 0.0, 1.0],
147+
position: [0.5, 0.0],
148+
scale: [0.4, 0.4],
149+
},
150+
PushConstant {
151+
color: [0.0, 0.0, 1.0, 1.0],
152+
position: [0.25, 0.5],
153+
scale: [0.5, 0.5],
154+
},
155+
PushConstant {
156+
color: [1.0, 1.0, 1.0, 1.0],
157+
position: [0.0, 0.0],
158+
scale: [0.5, 0.5],
159+
},
160+
];
161+
162+
let render_pipeline = self
163+
.render_pipeline
164+
.as_ref()
165+
.expect("No render pipeline actively set for rendering.");
166+
167+
let mut commands = vec![
168+
RenderCommand::SetViewports {
169+
start_at: 0,
170+
viewports: vec![viewport.clone()],
171+
},
172+
RenderCommand::SetScissors {
173+
start_at: 0,
174+
viewports: vec![viewport.clone()],
175+
},
176+
RenderCommand::SetPipeline {
177+
pipeline: render_pipeline.clone(),
178+
},
179+
RenderCommand::BeginRenderPass {
180+
render_pass: self
181+
.render_pass
182+
.as_ref()
183+
.expect("Cannot begin the render pass when it doesn't exist.")
184+
.clone(),
185+
viewport: viewport.clone(),
186+
},
187+
];
188+
189+
for triangle in triangle_data {
190+
commands.push(RenderCommand::PushConstants {
191+
pipeline: render_pipeline.clone(),
192+
stage: PipelineStage::VERTEX,
193+
offset: 0,
194+
bytes: push_constants_to_bytes(triangle),
195+
});
196+
commands.push(RenderCommand::Draw { vertices: 0..3 });
197+
}
198+
199+
return commands;
200+
}
201+
202+
fn on_renderer_detached(
203+
&mut self,
204+
_render_context: &mut lambda::core::render::RenderContext,
205+
) {
206+
println!("Detached the demo component from the renderer");
207+
}
208+
}
209+
210+
impl Default for TrianglesComponent {
211+
/// Load in shaders upon creation.
212+
213+
fn default() -> Self {
214+
// Specify virtual shaders to use for rendering
215+
let triangle_vertex = VirtualShader::Source {
216+
source: include_str!("../assets/triangles.vert").to_string(),
217+
kind: ShaderKind::Vertex,
218+
name: String::from("triangles"),
219+
entry_point: String::from("main"),
220+
};
221+
222+
let triangle_fragment = VirtualShader::Source {
223+
source: include_str!("../assets/triangles.frag").to_string(),
224+
kind: ShaderKind::Fragment,
225+
name: String::from("triangles"),
226+
entry_point: String::from("main"),
227+
};
228+
229+
// Create a shader builder to compile the shaders.
230+
let mut builder = ShaderBuilder::new();
231+
let vs = builder.build(triangle_vertex);
232+
let fs = builder.build(triangle_fragment);
233+
234+
return TrianglesComponent {
235+
vertex_shader: vs,
236+
triangle_vertex: fs,
237+
render_pass: None,
238+
render_pipeline: None,
239+
width: 800,
240+
height: 600,
241+
};
242+
}
243+
}
244+
245+
fn main() {
246+
let runtime = GenericRuntimeBuilder::new("Multiple Triangles Demo")
247+
.with_renderer_configured_as(move |render_context_builder| {
248+
return render_context_builder.with_render_timeout(1_000_000_000);
249+
})
250+
.with_window_configured_as(move |window_builder| {
251+
return window_builder
252+
.with_dimensions(800, 600)
253+
.with_name("Triangles");
254+
})
255+
.with_component(move |runtime, triangles: TrianglesComponent| {
256+
return (runtime, triangles);
257+
})
258+
.build();
259+
260+
start_runtime(runtime);
261+
}

0 commit comments

Comments
 (0)