1extern crate est_render;
2
3use est_render::prelude::*;
4
5pub(crate) const VERTEX_DRAWING_SHADER: &str = r#"
6// Vertex Shader
7struct VertexInput {
8 @location(0) position: vec3<f32>,
9 @location(1) color: vec4<f32>,
10 @location(2) texCoord: vec2<f32>,
11};
12
13struct VertexOutput {
14 @builtin(position) position: vec4<f32>,
15 @location(0) color: vec4<f32>,
16 @location(1) texCoord: vec2<f32>,
17};
18
19@vertex
20fn main_vertex(input: VertexInput) -> VertexOutput {
21 var output: VertexOutput;
22 output.position = vec4<f32>(input.position, 1.0);
23 output.color = input.color;
24 output.texCoord = input.texCoord;
25 return output;
26}"#;
27
28pub(crate) const FRAGMENT_DRAWING_SHADER: &str = r#"
29// Fragment Shader
30@group(0) @binding(0) var myTexture: texture_2d<f32>;
31@group(0) @binding(1) var mySampler: sampler;
32
33struct FragmentInput {
34 @location(0) color: vec4<f32>,
35 @location(1) texCoord: vec2<f32>,
36};
37
38@fragment
39fn main_fragment(input: FragmentInput) -> @location(0) vec4<f32> {
40 let checkerSize = 50.0;
41 let x = floor(input.texCoord.x * checkerSize);
42 let y = floor(input.texCoord.y * checkerSize);
43 let isWhite = ((x + y) % 2.0) == 0.0;
44
45 if isWhite {
46 return input.color; // white square
47 } else {
48 return vec4<f32>(0.0, 0.0, 0.0, 1.0); // black square
49 }
50}"#;
51
52pub(crate) const COMPUTE_NOOP_SHADER: &str = r#"
53// Compute Shader
54@compute @workgroup_size(1)
55fn main() {
56 // This compute shader does nothing
57 // It can be used to test the compute pipeline setup
58}
59"#;
60
61fn main() {
62 let mut runner = est_render::runner::new().expect("Failed to create runner");
63 let mut window = runner
64 .create_window("Engine Example", Point2::new(800, 600))
65 .build()
66 .expect("Failed to create window");
67
68 let mut gpu = est_render::gpu::new(Some(&mut window))
69 .build()
70 .expect("Failed to create GPU");
71
72 let mut msaa_texture = gpu
73 .create_texture()
74 .set_render_target(Point2::new(800, 600), None)
75 .set_sample_count(SampleCount::SampleCount4)
76 .build()
77 .expect("Failed to create MSAA texture");
78
79 let blank_texture = gpu
80 .create_texture()
81 .set_raw_image(
82 &[255u8; 4],
83 Point2::new(1, 1),
84 TextureFormat::Bgra8Unorm,
85 )
86 .set_usage(TextureUsage::Sampler)
87 .build()
88 .expect("Failed to create blank texture");
89
90 let shader = gpu
91 .create_graphics_shader()
92 .set_vertex_code(VERTEX_DRAWING_SHADER)
93 .set_fragment_code(FRAGMENT_DRAWING_SHADER)
94 .build()
95 .expect("Failed to create graphics shader");
96
97 let compute_shader = gpu
98 .create_compute_shader()
99 .set_source(COMPUTE_NOOP_SHADER)
100 .build()
101 .expect("Failed to create compute shader");
102
103 let pipeline = gpu
104 .create_render_pipeline()
105 .set_shader(Some(&shader))
106 .set_blend(Some(&BlendState::ALPHA_BLEND))
107 .set_attachment_texture(0, 0, Some(&blank_texture))
108 .set_attachment_sampler(0, 1, Some(&TextureSampler::DEFAULT))
109 .build()
110 .expect("Failed to create render pipeline");
111
112 let compute_pipeline = gpu
113 .create_compute_pipeline()
114 .set_shader(Some(&compute_shader))
115 .build()
116 .expect("Failed to create compute pipeline");
117
118 let vertices = vec![
120 Vertex {
121 position: Vector3::new(-0.5, -0.5, 0.0),
122 color: Color::new(1.0, 0.0, 0.0, 1.0),
123 texcoord: Vector2::new(0.0, 1.0),
124 },
125 Vertex {
126 position: Vector3::new(0.5, -0.5, 0.0),
127 color: Color::new(0.0, 1.0, 0.0, 1.0),
128 texcoord: Vector2::new(1.0, 1.0),
129 },
130 Vertex {
131 position: Vector3::new(0.0, 0.5, 0.0),
132 color: Color::new(0.0, 0.0, 1.0, 1.0),
133 texcoord: Vector2::new(0.5, 0.0),
134 },
135 ];
136
137 let indexes = vec![0u16, 1u16, 2u16];
138
139 let vbo = gpu
140 .create_buffer()
141 .set_data_vec(vertices)
142 .set_usage(BufferUsage::VERTEX)
143 .build()
144 .expect("Failed to create vertex buffer");
145
146 let ibo = gpu
147 .create_buffer()
148 .set_data_vec(indexes)
149 .set_usage(BufferUsage::INDEX)
150 .build()
151 .expect("Failed to create index buffer");
152
153 while runner.pump_events(PumpMode::WaitDraw) {
154 for event in runner.get_events() {
155 match event {
156 Event::KeyboardInput {
157 window_id,
158 key,
159 pressed,
160 } => {
161 if *window_id == window.id() && key == "Escape" && *pressed {
162 window.quit();
163 }
164 }
165 Event::WindowResized { window_id: _, size } => {
166 if size.x <= 0 || size.y <= 0 {
167 continue; }
169
170 msaa_texture = gpu
171 .create_texture()
172 .set_render_target(Point2::new(size.x as u32, size.y as u32), None)
173 .set_sample_count(SampleCount::SampleCount4)
174 .build()
175 .expect("Failed to resize MSAA texture");
176 }
177 Event::RedrawRequested { window_id: _ } => {
178 if let Ok(mut cmd) = gpu.begin_command() {
179 if let Ok(mut cm) = cmd.begin_computepass() {
180 cm.set_pipeline(Some(&compute_pipeline));
181 cm.dispatch(1, 1, 1);
182 }
183
184 if let Ok(mut rp) = cmd.begin_renderpass() {
185 rp.set_clear_color(Color::BLACK);
186 rp.push_msaa_texture(&msaa_texture);
187
188 rp.set_pipeline(Some(&pipeline));
189 rp.set_gpu_buffer(Some(&vbo), Some(&ibo));
190 rp.draw_indexed(0..3, 0, 1);
191 }
192 }
193
194 window.request_redraw();
195 }
196 _ => {}
197 }
198 }
199 }
200}