Skip to content

Commit 2c1c247

Browse files
committed
[add] triangle and triangles demo.
1 parent f264299 commit 2c1c247

3 files changed

Lines changed: 520 additions & 0 deletions

File tree

demos/render/src/bin/.gitkeep

Whitespace-only changes.

demos/render/src/bin/triangle.rs

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
#![allow(clippy::needless_return)]
2+
use lambda::{
3+
component::Component,
4+
events::{
5+
EventMask,
6+
Key,
7+
WindowEvent,
8+
},
9+
render::{
10+
command::RenderCommand,
11+
pipeline,
12+
render_pass,
13+
shader::{
14+
Shader,
15+
ShaderBuilder,
16+
ShaderKind,
17+
VirtualShader,
18+
},
19+
viewport,
20+
RenderContext,
21+
},
22+
runtime::start_runtime,
23+
runtimes::{
24+
application::ComponentResult,
25+
ApplicationRuntimeBuilder,
26+
},
27+
};
28+
29+
pub struct DemoComponent {
30+
fragment_shader: Shader,
31+
vertex_shader: Shader,
32+
render_pass_id: Option<lambda::render::ResourceId>,
33+
render_pipeline_id: Option<lambda::render::ResourceId>,
34+
width: u32,
35+
height: u32,
36+
}
37+
38+
impl Component<ComponentResult, String> for DemoComponent {
39+
fn on_attach(
40+
&mut self,
41+
render_context: &mut RenderContext,
42+
) -> Result<ComponentResult, String> {
43+
logging::info!("Attached the demo component to the renderer");
44+
let render_pass = render_pass::RenderPassBuilder::new().build(
45+
render_context.gpu(),
46+
render_context.surface_format(),
47+
render_context.depth_format(),
48+
);
49+
50+
let pipeline = pipeline::RenderPipelineBuilder::new()
51+
.with_culling(pipeline::CullingMode::None)
52+
.build(
53+
render_context.gpu(),
54+
render_context.surface_format(),
55+
render_context.depth_format(),
56+
&render_pass,
57+
&self.vertex_shader,
58+
Some(&self.fragment_shader),
59+
);
60+
61+
// Attach the render pass and pipeline to the render context
62+
self.render_pass_id = Some(render_context.attach_render_pass(render_pass));
63+
self.render_pipeline_id = Some(render_context.attach_pipeline(pipeline));
64+
65+
logging::info!("Attached the DemoComponent.");
66+
return Ok(ComponentResult::Success);
67+
}
68+
69+
fn on_detach(
70+
self: &mut DemoComponent,
71+
_render_context: &mut RenderContext,
72+
) -> Result<ComponentResult, String> {
73+
return Ok(ComponentResult::Success);
74+
}
75+
76+
fn event_mask(&self) -> EventMask {
77+
return EventMask::WINDOW | EventMask::KEYBOARD;
78+
}
79+
80+
fn on_window_event(&mut self, event: &WindowEvent) -> Result<(), String> {
81+
match event {
82+
WindowEvent::Resize { width, height } => {
83+
logging::info!("Window resized to {}x{}", width, height);
84+
self.width = *width;
85+
self.height = *height;
86+
}
87+
WindowEvent::Close => {
88+
logging::info!("Window closed");
89+
}
90+
}
91+
return Ok(());
92+
}
93+
94+
fn on_keyboard_event(&mut self, event: &Key) -> Result<(), String> {
95+
match event {
96+
Key::Pressed {
97+
scan_code: _,
98+
virtual_key,
99+
} => {
100+
logging::debug!("Key pressed: {:?}", virtual_key);
101+
}
102+
Key::Released {
103+
scan_code: _,
104+
virtual_key,
105+
} => {
106+
logging::debug!("Key released: {:?}", virtual_key);
107+
}
108+
Key::ModifierPressed {
109+
modifier: _,
110+
virtual_key,
111+
} => {
112+
logging::debug!("Modifier pressed: {:?}", virtual_key);
113+
}
114+
}
115+
return Ok(());
116+
}
117+
118+
fn on_update(
119+
self: &mut DemoComponent,
120+
last_frame: &std::time::Duration,
121+
) -> Result<ComponentResult, String> {
122+
if last_frame.as_millis() > 20 {
123+
logging::warn!("Last frame took {}ms", last_frame.as_millis());
124+
}
125+
return Ok(ComponentResult::Success);
126+
}
127+
fn on_render(
128+
self: &mut DemoComponent,
129+
_render_context: &mut lambda::render::RenderContext,
130+
) -> Vec<RenderCommand> {
131+
let viewport =
132+
viewport::ViewportBuilder::new().build(self.width, self.height);
133+
134+
// Begin the pass first, then set pipeline/state inside
135+
return vec![
136+
RenderCommand::BeginRenderPass {
137+
render_pass: self
138+
.render_pass_id
139+
.expect("No render pass attached to the component"),
140+
viewport: viewport.clone(),
141+
},
142+
RenderCommand::SetPipeline {
143+
pipeline: self
144+
.render_pipeline_id
145+
.expect("No pipeline attached to the component"),
146+
},
147+
RenderCommand::SetViewports {
148+
start_at: 0,
149+
viewports: vec![viewport.clone()],
150+
},
151+
RenderCommand::SetScissors {
152+
start_at: 0,
153+
viewports: vec![viewport.clone()],
154+
},
155+
RenderCommand::Draw {
156+
vertices: 0..3,
157+
instances: 0..1,
158+
},
159+
RenderCommand::EndRenderPass,
160+
];
161+
}
162+
}
163+
164+
impl DemoComponent {}
165+
166+
impl Default for DemoComponent {
167+
/// Load in shaders upon creation.
168+
fn default() -> Self {
169+
// Specify virtual shaders to use for rendering
170+
let triangle_vertex = VirtualShader::Source {
171+
source: include_str!(concat!(
172+
env!("CARGO_MANIFEST_DIR"),
173+
"/../../crates/lambda-rs/assets/shaders/triangle.vert"
174+
))
175+
.to_string(),
176+
kind: ShaderKind::Vertex,
177+
name: String::from("triangle"),
178+
entry_point: String::from("main"),
179+
};
180+
181+
let triangle_fragment = VirtualShader::Source {
182+
source: include_str!(concat!(
183+
env!("CARGO_MANIFEST_DIR"),
184+
"/../../crates/lambda-rs/assets/shaders/triangle.frag"
185+
))
186+
.to_string(),
187+
kind: ShaderKind::Fragment,
188+
name: String::from("triangle"),
189+
entry_point: String::from("main"),
190+
};
191+
192+
// Create a shader builder to compile the shaders.
193+
let mut builder = ShaderBuilder::new();
194+
let vs = builder.build(triangle_vertex);
195+
let fs = builder.build(triangle_fragment);
196+
197+
return DemoComponent {
198+
vertex_shader: vs,
199+
fragment_shader: fs,
200+
render_pass_id: None,
201+
render_pipeline_id: None,
202+
width: 800,
203+
height: 600,
204+
};
205+
}
206+
}
207+
208+
fn main() {
209+
let runtime = ApplicationRuntimeBuilder::new("2D Triangle Demo")
210+
.with_renderer_configured_as(move |render_context_builder| {
211+
return render_context_builder.with_render_timeout(1_000_000_000);
212+
})
213+
.with_window_configured_as(move |window_builder| {
214+
return window_builder
215+
.with_dimensions(1200, 600)
216+
.with_name("2D Triangle Window");
217+
})
218+
.with_component(move |runtime, demo: DemoComponent| {
219+
return (runtime, demo);
220+
})
221+
.build();
222+
223+
start_runtime(runtime);
224+
}

0 commit comments

Comments
 (0)