1use crate::{
2 extract_resource::ExtractResource,
3 render_resource::{ShaderType, UniformBuffer},
4 renderer::{RenderDevice, RenderQueue},
5 Extract, ExtractSchedule, Render, RenderApp, RenderSystems,
6};
7use bevy_app::{App, Plugin};
8use bevy_diagnostic::FrameCount;
9use bevy_ecs::prelude::*;
10use bevy_reflect::prelude::*;
11use bevy_shader::load_shader_library;
12use bevy_time::Time;
13
14pub struct GlobalsPlugin;
15
16impl Plugin for GlobalsPlugin {
17 fn build(&self, app: &mut App) {
18 load_shader_library!(app, "globals.wgsl");
19 if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
20 render_app
21 .init_resource::<GlobalsBuffer>()
22 .init_resource::<Time>()
23 .add_systems(ExtractSchedule, (extract_frame_count, extract_time))
24 .add_systems(
25 Render,
26 prepare_globals_buffer.in_set(RenderSystems::PrepareResources),
27 );
28 }
29 }
30}
31
32fn extract_frame_count(mut commands: Commands, frame_count: Extract<Res<FrameCount>>) {
33 commands.insert_resource(**frame_count);
34}
35
36fn extract_time(mut commands: Commands, time: Extract<Res<Time>>) {
37 commands.insert_resource(**time);
38}
39
40#[derive(Default, Clone, Resource, ExtractResource, Reflect, ShaderType)]
43#[reflect(Resource, Default, Clone)]
44pub struct GlobalsUniform {
45 time: f32,
48 delta_time: f32,
50 frame_count: u32,
53 #[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
55 _wasm_padding: f32,
56}
57
58#[derive(Resource, Default)]
60pub struct GlobalsBuffer {
61 pub buffer: UniformBuffer<GlobalsUniform>,
62}
63
64fn prepare_globals_buffer(
65 render_device: Res<RenderDevice>,
66 render_queue: Res<RenderQueue>,
67 mut globals_buffer: ResMut<GlobalsBuffer>,
68 time: Res<Time>,
69 frame_count: Res<FrameCount>,
70) {
71 let buffer = globals_buffer.buffer.get_mut();
72 buffer.time = time.elapsed_secs_wrapped();
73 buffer.delta_time = time.delta_secs();
74 buffer.frame_count = frame_count.0;
75
76 globals_buffer
77 .buffer
78 .write_buffer(&render_device, &render_queue);
79}