1use {
6 crate::{
7 registration::{
8 relation::{
9 ParentWrapper,
10 Parent, Child
11 },
12 named::Named,
13 id::ID
14 },
15 scripting::{
16 Script,
17 executor::Spawner,
18 globals::{Global, EngineGlobals},
19 Scriptable
20 }, graphics::{
22 Drawable,
23 draw_pass_manager::DrawPassManager,
24 lighting_pass_manager::LightingPassManager,
25 graphics_system::{GraphicsSystem, GraphicsSystemTrait},
26 pass_builder::PassBuilder
27 },
28 components::{
29 triangle_mesh::TriangleMesh,
30 RGB,
31 ScreenPos
32 },
33 shaders::{
34 fs_lighting_ambient,
35 vs_lighting
36 },
37 event::UserEvent
38 },
39 vulkano::{
40 buffer::{
41 BufferUsage,
42 CpuAccessibleBuffer
43 },
44 command_buffer::{
45 AutoCommandBuffer,
46 AutoCommandBufferBuilder,
47 DynamicState
48 },
49 device::Queue,
50 descriptor::{
51 descriptor_set::PersistentDescriptorSet,
52 },
53 framebuffer::{
54 RenderPassAbstract,
55 Subpass
56 },
57 image::ImageViewAbstract,
58 pipeline::{
59 GraphicsPipeline,
60 GraphicsPipelineAbstract,
61 blend::{
62 AttachmentBlend,
63 BlendFactor,
64 BlendOp
65 },
66 viewport::Viewport
67 },
68 },
69 feo_math::{
70 linear_algebra::vector3::Vector3,
71 rotation::quaternion::Quaternion,
72 utils::space::Space
73 },
74 winit::event::Event,
75 std::{
76 sync::{
77 Arc,
78 RwLock
79 },
80 any::Any,
81 mem
82 },
83 super::{
84 super::{
85 GameObject,
86 camera::Camera,
87 },
88 Light
89 }
90};
91
92#[derive(GameObject, Drawable, Parent, Child, Named, Scriptable)]
95#[light] pub struct AmbientLight {
97 name: String,
98 id: ID,
99
100 pub subspace: Space,
101
102 intensity: f32,
103 color: RGB,
104
105 parent: ParentWrapper,
106 children: Vec<Arc<RwLock<dyn GameObject>>>,
107
108 script: Option<Box<Script<Self>>>,
109}
110
111impl std::fmt::Debug for AmbientLight {
112 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
113 f.debug_struct("AmbientLight")
114 .field("name", &self.name)
115 .field("id", &self.id)
116 .field("subspace", &self.subspace)
117 .field("intensity", &self.intensity)
118 .field("color", &self.color)
119 .field("parent", &self.parent)
120 .field("children", &self.children)
121 .field("script", &self.script).finish()
122 }
123}
124
125impl Clone for AmbientLight {
126 fn clone(&self) -> Self {
127 let id = self.id.get_system().take();
128 AmbientLight {
129 id,
130 name: self.name.clone(),
131 parent: self.parent.clone(),
132 subspace: self.subspace,
133 script: self.script.clone(),
134 children: self.children.clone().into_iter().map(|_child| {
135 todo!();
137 }).collect::<Vec<Arc<RwLock<dyn GameObject>>>>(),
138 intensity: self.intensity,
139 color: self.color,
140 }
141 }
142}
143
144impl AmbientLight {
145 #[allow(clippy::too_many_arguments)]
147 pub fn new(
148 name: Option<&str>,
149 parent: Option<Arc<RwLock<dyn GameObject>>>,
150 intensity: f32,
151 color: RGB,
152
153 position: Option<Vector3<f32>>, rotation: Option<Quaternion<f32>>,
155 scale_factor: Option<Vector3<f32>>, script: Option<Box<Script<Self>>>,
158
159 engine_globals: EngineGlobals) -> Arc<RwLock<AmbientLight>> {
160 let id = engine_globals.id_system.take();
161 Arc::new(RwLock::new(AmbientLight {
162 name: match name {
163 Some(name) => name.to_string(),
164 None => String::from("ambient_light_") + id.to_string().as_str()
165 },
166 id,
167
168 intensity,
169 color,
170 subspace: Space::new(position, rotation, scale_factor),
171
172 parent: match parent{
173 Some(game_object) => ParentWrapper::GameObject(game_object),
174 None => ParentWrapper::Scene(engine_globals.scene),
175 },
176 children: Vec::new(),
177
178 script
179 }))
180 }
181
182 fn draw<C, A, D> (
183 &self,
184 graphics_system: GraphicsSystem,
185 viewport_dimensions: [u32; 2],
186 diffuse_input: C,
187 ambient_input: A,
188 depth_input: D) -> AutoCommandBuffer
189 where
190 C: ImageViewAbstract + Send + Sync + 'static,
191 A: ImageViewAbstract + Send + Sync + 'static,
192 D: ImageViewAbstract + Send + Sync + 'static,
193 {
194 let push_constants = fs_lighting_ambient::ty::PushConstants {
195 color: [self.color.r, self.color.g, self.color.b, 1.0],
196 };
197
198 let layout = graphics_system.pipeline.descriptor_set_layout(0).unwrap();
199
200 let descriptor_set = PersistentDescriptorSet::start(layout.clone())
201 .add_image(diffuse_input).unwrap()
202 .add_image(ambient_input).unwrap()
203 .add_image(depth_input).unwrap()
204 .build().unwrap();
205
206 let dynamic_state = DynamicState {
207 viewports: Some(vec![Viewport {
208 origin: [0.0, 0.0],
209 dimensions: [viewport_dimensions[0] as f32, viewport_dimensions[1] as f32],
210 depth_range: 0.0..1.0,
211 }]),
212 ..DynamicState::none()
213 };
214
215 let mut builder = AutoCommandBufferBuilder::secondary_graphics(
216 graphics_system.gfx_queue.device().clone(),
217 graphics_system.gfx_queue.family(),
218 graphics_system.pipeline.clone().subpass().clone(),
219 ).unwrap();
220
221 builder.draw(
222 graphics_system.pipeline.clone(),
223 &dynamic_state,
224 vec![graphics_system.vertex_buffer.clone()],
225 descriptor_set,
226 push_constants,
227 vec![],
228 ).unwrap();
229
230 builder.build().unwrap()
231 }
232}
233
234impl Light for AmbientLight {
235 fn as_any(&self) -> &dyn Any { self }
236 fn as_gameobject(&self) -> &dyn GameObject { self }
237 fn cast_gameobject_arc_rwlock(&self, this: Arc<RwLock<dyn Light>>) -> Arc<RwLock<dyn GameObject>> {
238 let this= Arc::into_raw(this).cast::<RwLock<Self>>();
239 let this = unsafe { Arc::from_raw(this) };
240 this as Arc<RwLock<dyn GameObject>>
241 }
242}
243
244impl GraphicsSystemTrait for AmbientLight{
245 fn new_system<L>(gfx_queue: Arc<Queue>, subpass: Subpass<L>) -> crate::graphics::graphics_system::GraphicsSystem
246 where L: RenderPassAbstract + Sync + Send + 'static {
247 let vertex_buffer = CpuAccessibleBuffer::from_iter(
248 gfx_queue.device().clone(),
249 BufferUsage::all(),
250 false,
251 [
252 ScreenPos { position: [-1.0, -1.0] },
253 ScreenPos { position: [-1.0, 3.0] },
254 ScreenPos { position: [ 3.0, -1.0] },
255 ].iter().cloned(),
256 ).expect("failed to create buffer");
257
258 let pipeline = {
259 let vs = vs_lighting::Shader::load(gfx_queue.device().clone())
260 .expect("failed to create shader");
261 let fs = fs_lighting_ambient::Shader::load(gfx_queue.device().clone())
262 .expect("failed to create shader");
263
264 Arc::new(
265 GraphicsPipeline::start()
266 .vertex_input_single_buffer::<ScreenPos>()
267 .vertex_shader(vs.main_entry_point(), ())
268 .triangle_list()
269 .viewports_dynamic_scissors_irrelevant(1)
270 .fragment_shader(fs.main_entry_point(), ())
271 .blend_collective(AttachmentBlend {
272 enabled: true,
273 color_op: BlendOp::Add,
274 color_source: BlendFactor::One,
275 color_destination: BlendFactor::One,
276 alpha_op: BlendOp::Max,
277 alpha_source: BlendFactor::One,
278 alpha_destination: BlendFactor::One,
279 mask_red: true,
280 mask_green: true,
281 mask_blue: true,
282 mask_alpha: true,
283 })
284 .render_pass(subpass)
285 .build(gfx_queue.device().clone()).unwrap()
286 ) as Arc<_>
287 };
288
289 GraphicsSystem {
290 gfx_queue,
291 vertex_buffer,
292 pipeline,
293 }
294 }
295
296 fn get_system_num(&self) -> usize { 0 }
297
298 fn pass<'b, 'p : 'b>(&self, pass_builder: &'b mut PassBuilder<'p>, gfx_system: GraphicsSystem){
299 let dims = pass_builder.framebuffer.dimensions();
300
301 let command_buffer = self.draw(
302 gfx_system,
303 [dims[0], dims[1]],
304 pass_builder.system.diffuse_buffer.clone(),
305 pass_builder.system.ambient_buffer.clone(),
306 pass_builder.system.depth_buffer.clone(),
307 );
308
309 pass_builder.command_buffer_builder
310 .as_mut().unwrap()
311 .execute_commands(command_buffer).unwrap();
312 }
313}