Provide GlobalsUniform in UiMaterial shaders (#10739)

# Objective

`GlobalsUniform` provides the current time to shaders, which is useful
for animations. `UiMaterial` is an abstraction that makes it easier to
write custom shaders for UI elements.
This PR makes it possible to use the `GlobalsUniform` in `UiMaterial`
shaders.

## Solution

The `GlobalsUniform` is bound to `@group(0) @binding(1)`. It is
accessible in shaders with:
```wgsl
#import bevy_render::globals::Globals

@group(0) @binding(1)
var<uniform> globals: Globals;
```

---

## Changelog

Added `GlobalsUniform` in `UiMaterial` shaders

## Discussion

Should I modify the existing ui_material example to showcase this?
This commit is contained in:
davier 2023-11-28 13:08:28 +01:00 committed by GitHub
parent 0e9f6e92ea
commit e44b74fb6a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 21 additions and 6 deletions

View File

@ -1,8 +1,13 @@
#import bevy_render::view::View
#import bevy_render::{
view::View,
globals::Globals,
}
#import bevy_ui::ui_vertex_output::UiVertexOutput
@group(0) @binding(0)
var<uniform> view: View;
@group(0) @binding(1)
var<uniform> globals: Globals;
@vertex
fn vertex(

View File

@ -15,6 +15,7 @@ use bevy_ecs::{
use bevy_math::{Mat4, Rect, Vec2, Vec4Swizzles};
use bevy_render::{
extract_component::ExtractComponentPlugin,
globals::{GlobalsBuffer, GlobalsUniform},
render_asset::RenderAssets,
render_phase::*,
render_resource::{binding_types::uniform_buffer, *},
@ -225,11 +226,15 @@ impl<M: UiMaterial> FromWorld for UiMaterialPipeline<M> {
let view_layout = render_device.create_bind_group_layout(
"ui_view_layout",
&BindGroupLayoutEntries::single(
&BindGroupLayoutEntries::sequential(
ShaderStages::VERTEX_FRAGMENT,
(
uniform_buffer::<ViewUniform>(true),
uniform_buffer::<GlobalsUniform>(false),
),
),
);
UiMaterialPipeline {
ui_layout,
view_layout,
@ -430,18 +435,22 @@ pub fn prepare_uimaterial_nodes<M: UiMaterial>(
mut ui_meta: ResMut<UiMaterialMeta<M>>,
mut extracted_uinodes: ResMut<ExtractedUiMaterialNodes<M>>,
view_uniforms: Res<ViewUniforms>,
globals_buffer: Res<GlobalsBuffer>,
ui_material_pipeline: Res<UiMaterialPipeline<M>>,
mut phases: Query<&mut RenderPhase<TransparentUi>>,
mut previous_len: Local<usize>,
) {
if let Some(view_binding) = view_uniforms.uniforms.binding() {
if let (Some(view_binding), Some(globals_binding)) = (
view_uniforms.uniforms.binding(),
globals_buffer.buffer.binding(),
) {
let mut batches: Vec<(Entity, UiMaterialBatch<M>)> = Vec::with_capacity(*previous_len);
ui_meta.vertices.clear();
ui_meta.view_bind_group = Some(render_device.create_bind_group(
"ui_material_view_bind_group",
&ui_material_pipeline.view_layout,
&BindGroupEntries::single(view_binding),
&BindGroupEntries::sequential((view_binding, globals_binding)),
));
let mut index = 0;

View File

@ -67,7 +67,8 @@ use bevy_render::render_resource::{AsBindGroup, RenderPipelineDescriptor, Shader
///
/// If you only use the fragment shader make sure to import `UiVertexOutput` from
/// `bevy_ui::ui_vertex_output` in your wgsl shader.
/// Also note that bind group 0 is always bound to the [`View Uniform`](bevy_render::view::ViewUniform).
/// Also note that bind group 0 is always bound to the [`View Uniform`](bevy_render::view::ViewUniform)
/// and the [`Globals Uniform`](bevy_render::globals::GlobalsUniform).
///
/// ```wgsl
/// #import bevy_ui::ui_vertex_output UiVertexOutput