11use lambda:: {
22 core:: {
33 component:: Component ,
4- render:: shader,
4+ render:: {
5+ command:: RenderCommand ,
6+ pipeline:: {
7+ RenderPipeline ,
8+ RenderPipelineBuilder ,
9+ } ,
10+ render_pass:: {
11+ RenderPass ,
12+ RenderPassBuilder ,
13+ } ,
14+ shader:: {
15+ Shader ,
16+ ShaderBuilder ,
17+ } ,
18+ viewport,
19+ ResourceId ,
20+ } ,
521 runtime:: start_runtime,
622 } ,
7- math,
23+ math:: {
24+ matrix:: {
25+ self ,
26+ Matrix ,
27+ } ,
28+ vector:: Vector ,
29+ } ,
830 runtimes:: GenericRuntimeBuilder ,
931} ;
32+ use lambda_platform:: {
33+ gfx:: pipeline:: PipelineStage ,
34+ shaderc:: {
35+ ShaderKind ,
36+ VirtualShader ,
37+ } ,
38+ } ;
1039
1140const VERTEX_SHADER_SOURCE : & str = r#"
1241#version 450
@@ -29,14 +58,44 @@ void main() {
2958
3059"# ;
3160
32- struct PushConstantsExample { }
61+ #[ repr( C ) ]
62+ #[ derive( Debug , Clone , Copy ) ]
63+ pub struct PushConstant {
64+ data : [ f32 ; 4 ] ,
65+ render_matrix : [ [ f32 ; 4 ] ; 4 ] ,
66+ }
67+
68+ pub struct PushConstantsExample {
69+ frame_number : u64 ,
70+ shader : Shader ,
71+ render_pipeline : Option < ResourceId > ,
72+ render_pass : Option < ResourceId > ,
73+ }
74+
75+ pub fn push_constants_to_bytes ( push_constants : & PushConstant ) -> & [ u32 ] {
76+ let bytes = unsafe {
77+ let size_in_bytes = std:: mem:: size_of :: < PushConstant > ( ) ;
78+ let size_in_u32 = size_in_bytes / std:: mem:: size_of :: < u32 > ( ) ;
79+ let ptr = push_constants as * const PushConstant as * const u32 ;
80+ std:: slice:: from_raw_parts ( ptr, size_in_u32)
81+ } ;
82+
83+ return bytes;
84+ }
3385
3486impl Component for PushConstantsExample {
3587 fn on_attach (
3688 & mut self ,
3789 render_context : & mut lambda:: core:: render:: RenderContext ,
3890 ) {
39- todo ! ( )
91+ let render_pass = RenderPassBuilder :: new ( ) . build ( & render_context) ;
92+ let push_constant_size = std:: mem:: size_of :: < PushConstant > ( ) as u32 ;
93+ let pipeline = RenderPipelineBuilder :: new ( )
94+ . with_push_constant ( PipelineStage :: VERTEX , push_constant_size)
95+ . build ( render_context, & render_pass, & self . shader , None ) ;
96+
97+ self . render_pass = Some ( render_context. attach_render_pass ( render_pass) ) ;
98+ self . render_pipeline = Some ( render_context. attach_pipeline ( pipeline) ) ;
4099 }
41100
42101 fn on_detach (
@@ -50,28 +109,94 @@ impl Component for PushConstantsExample {
50109 todo ! ( )
51110 }
52111
112+ /// Update the frame number every frame.
53113 fn on_update ( & mut self , last_frame : & std:: time:: Duration ) {
54- todo ! ( )
114+ self . frame_number += 1 ;
55115 }
56116
57117 fn on_render (
58118 & mut self ,
59119 render_context : & mut lambda:: core:: render:: RenderContext ,
60120 ) -> Vec < lambda:: core:: render:: command:: RenderCommand > {
61- use math:: vector:: Vector ;
62121 let mut camera = [ 0.0 , 0.0 , -2.0 ] ;
63- let view: [ [ f32 ; 4 ] ; 4 ] = math:: matrix:: translation_matrix ( camera) ;
122+ let view: [ [ f32 ; 4 ] ; 4 ] = matrix:: translation_matrix ( camera) ;
123+
124+ // Create a projection matrix.
64125 let mut projection: [ [ f32 ; 4 ] ; 4 ] =
65- math :: matrix:: perspective_matrix ( 1.0 / 2.0 , 1700.0 / 900.0 , 0.1 , 200.0 ) ;
126+ matrix:: perspective_matrix ( 1.0 / 2.0 , 1700.0 / 900.0 , 0.1 , 200.0 ) ;
66127 projection. as_mut ( ) [ 1 ] . as_mut ( ) [ 1 ] *= -1.0 ;
67128
68- todo ! ( )
129+ // Rotate model.
130+ let model: [ [ f32 ; 4 ] ; 4 ] = matrix:: rotate_matrix (
131+ matrix:: filled_matrix ( 4 , 4 , 1.0 ) ,
132+ [ 0.0 , 1.0 , 0.0 ] ,
133+ 0.4 * self . frame_number as f32 ,
134+ ) ;
135+
136+ // Create render matrix.
137+ let mesh_matrix = projection. multiply ( & view) . multiply ( & model) ;
138+
139+ // Create viewport.
140+ let viewport = viewport:: ViewportBuilder :: new ( ) . build ( 800 , 600 ) ;
141+
142+ let render_pipeline = self
143+ . render_pipeline
144+ . expect ( "No render pipeline actively set for rendering." ) ;
145+
146+ let mut commands = vec ! [
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 :: SetPipeline {
156+ pipeline: render_pipeline. clone( ) ,
157+ } ,
158+ RenderCommand :: BeginRenderPass {
159+ render_pass: self
160+ . render_pass
161+ . expect( "Cannot begin the render pass when it doesn't exist." )
162+ . clone( ) ,
163+ viewport: viewport. clone( ) ,
164+ } ,
165+ RenderCommand :: PushConstants {
166+ pipeline: render_pipeline. clone( ) ,
167+ stage: PipelineStage :: VERTEX ,
168+ offset: 0 ,
169+ bytes: Vec :: from( push_constants_to_bytes( & PushConstant {
170+ data: [ 0.0 , 0.0 , 0.0 , 0.0 ] ,
171+ render_matrix: mesh_matrix,
172+ } ) ) ,
173+ } ,
174+ RenderCommand :: Draw { vertices: 0 ..3 } ,
175+ ] ;
176+ commands. push ( RenderCommand :: EndRenderPass ) ;
177+
178+ return commands;
69179 }
70180}
71181
72182impl Default for PushConstantsExample {
73183 fn default ( ) -> Self {
74- return Self { } ;
184+ let triangle_in_3d = VirtualShader :: Source {
185+ source : VERTEX_SHADER_SOURCE . to_string ( ) ,
186+ kind : ShaderKind :: Vertex ,
187+ entry_point : "main" . to_string ( ) ,
188+ name : "push_constants" . to_string ( ) ,
189+ } ;
190+
191+ let mut builder = ShaderBuilder :: new ( ) ;
192+ let shader = builder. build ( triangle_in_3d) ;
193+
194+ return Self {
195+ frame_number : 0 ,
196+ shader,
197+ render_pipeline : None ,
198+ render_pass : None ,
199+ } ;
75200 }
76201}
77202
0 commit comments