diff --git a/assets/shaders/custom_material.wgsl b/assets/shaders/custom_material.wgsl index 95b1b7d26a196..37bb85d1ac9b0 100644 --- a/assets/shaders/custom_material.wgsl +++ b/assets/shaders/custom_material.wgsl @@ -1,3 +1,5 @@ +#import bevy_pbr::mesh_view_bindings + struct CustomMaterial { color: vec4, }; @@ -13,5 +15,8 @@ var base_color_sampler: sampler; fn fragment( #import bevy_pbr::mesh_vertex_output ) -> @location(0) vec4 { - return material.color * textureSample(base_color_texture, base_color_sampler, uv); + let time = sin(globals.time) * 0.5 + 0.5; + return material.color + * textureSample(base_color_texture, base_color_sampler, uv) + * vec4(time, time, time, 1.0); } diff --git a/crates/bevy_pbr/src/render/mesh.rs b/crates/bevy_pbr/src/render/mesh.rs index 082e20b733585..5f5b2a499d81d 100644 --- a/crates/bevy_pbr/src/render/mesh.rs +++ b/crates/bevy_pbr/src/render/mesh.rs @@ -13,6 +13,7 @@ use bevy_math::{Mat4, Vec2}; use bevy_reflect::TypeUuid; use bevy_render::{ extract_component::{ComponentUniforms, DynamicUniformIndex, UniformComponentPlugin}, + globals::{GlobalsBuffer, GlobalsUniform}, mesh::{ skinning::{SkinnedMesh, SkinnedMeshInverseBindposes}, GpuBufferInfo, Mesh, MeshVertexBufferLayout, @@ -377,6 +378,16 @@ impl FromWorld for MeshPipeline { }, count: None, }, + BindGroupLayoutEntry { + binding: 9, + visibility: ShaderStages::VERTEX_FRAGMENT, + ty: BindingType::Buffer { + ty: BufferBindingType::Uniform, + has_dynamic_offset: false, + min_binding_size: Some(GlobalsUniform::min_size()), + }, + count: None, + }, ], label: Some("mesh_view_layout"), }); @@ -463,6 +474,7 @@ impl FromWorld for MeshPipeline { ), } }; + MeshPipeline { view_layout, mesh_layout, @@ -757,11 +769,13 @@ pub fn queue_mesh_view_bind_groups( global_light_meta: Res, view_uniforms: Res, views: Query<(Entity, &ViewShadowBindings, &ViewClusterBindings)>, + globals_buffer: Res, ) { - if let (Some(view_binding), Some(light_binding), Some(point_light_binding)) = ( + if let (Some(view_binding), Some(light_binding), Some(point_light_binding), Some(globals)) = ( view_uniforms.uniforms.binding(), light_meta.view_gpu_lights.binding(), global_light_meta.gpu_point_lights.binding(), + globals_buffer.buffer.binding(), ) { for (entity, view_shadow_bindings, view_cluster_bindings) in &views { let view_bind_group = render_device.create_bind_group(&BindGroupDescriptor { @@ -808,6 +822,10 @@ pub fn queue_mesh_view_bind_groups( binding: 8, resource: view_cluster_bindings.offsets_and_counts_binding().unwrap(), }, + BindGroupEntry { + binding: 9, + resource: globals.clone(), + }, ], label: Some("mesh_view_bind_group"), layout: &mesh_pipeline.view_layout, diff --git a/crates/bevy_pbr/src/render/mesh_view_bindings.wgsl b/crates/bevy_pbr/src/render/mesh_view_bindings.wgsl index 04780be3f0c96..9756ff05d6501 100644 --- a/crates/bevy_pbr/src/render/mesh_view_bindings.wgsl +++ b/crates/bevy_pbr/src/render/mesh_view_bindings.wgsl @@ -40,3 +40,6 @@ var cluster_light_index_lists: ClusterLightIndexLists; @group(0) @binding(8) var cluster_offsets_and_counts: ClusterOffsetsAndCounts; #endif + +@group(0) @binding(9) +var globals: Globals; diff --git a/crates/bevy_pbr/src/render/mesh_view_types.wgsl b/crates/bevy_pbr/src/render/mesh_view_types.wgsl index ba6da2bb664f9..19e1cdf8b54fa 100644 --- a/crates/bevy_pbr/src/render/mesh_view_types.wgsl +++ b/crates/bevy_pbr/src/render/mesh_view_types.wgsl @@ -85,3 +85,10 @@ struct ClusterOffsetsAndCounts { data: array>, }; #endif + +struct Globals { + // The time since startup in seconds + time: f32, + // The delta time of the previous frame in seconds + delta_time: f32, +} diff --git a/crates/bevy_render/src/globals.rs b/crates/bevy_render/src/globals.rs new file mode 100644 index 0000000000000..4f5850ab3df46 --- /dev/null +++ b/crates/bevy_render/src/globals.rs @@ -0,0 +1,60 @@ +use crate::{ + extract_resource::ExtractResource, + render_resource::{ShaderType, UniformBuffer}, + renderer::{RenderDevice, RenderQueue}, + Extract, RenderApp, RenderStage, +}; +use bevy_app::{App, Plugin}; +use bevy_ecs::prelude::*; +use bevy_reflect::Reflect; +use bevy_time::Time; + +pub struct GlobalsPlugin; + +impl Plugin for GlobalsPlugin { + fn build(&self, app: &mut App) { + if let Ok(render_app) = app.get_sub_app_mut(RenderApp) { + render_app + .init_resource::() + .init_resource::