1use crate::{
2 extract_resource::ExtractResource,
3 render_resource::{ShaderType, UniformBuffer},
4 renderer::{RenderDevice, RenderQueue},
5 Extract, ExtractSchedule, GpuResourceAppExt, 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.wesl");
19 if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
20 render_app
21 .init_gpu_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)]
44#[extract_app(RenderApp)]
45pub struct GlobalsUniform {
46 time: f32,
49 delta_time: f32,
51 frame_count: u32,
54 #[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
56 _webgl2_padding: f32,
57}
58
59#[derive(Resource, Default)]
61pub struct GlobalsBuffer {
62 pub buffer: UniformBuffer<GlobalsUniform>,
63}
64
65fn prepare_globals_buffer(
66 render_device: Res<RenderDevice>,
67 render_queue: Res<RenderQueue>,
68 mut globals_buffer: ResMut<GlobalsBuffer>,
69 time: Res<Time>,
70 frame_count: Res<FrameCount>,
71) {
72 let buffer = globals_buffer.buffer.get_mut();
73 buffer.time = time.elapsed_secs_wrapped();
74 buffer.delta_time = time.delta_secs();
75 buffer.frame_count = frame_count.0;
76
77 globals_buffer
78 .buffer
79 .write_buffer(&render_device, &render_queue);
80}