use bevy_asset::{load_embedded_asset, AssetServer, Handle}; use bevy_ecs::prelude::*; use bevy_image::BevyDefault as _; use bevy_render::{ render_resource::{ binding_types::{sampler, texture_2d, uniform_buffer}, *, }, renderer::RenderDevice, view::{ViewTarget, ViewUniform}, }; use bevy_utils::default; #[derive(Resource)] pub struct UiPipeline { pub view_layout: BindGroupLayout, pub image_layout: BindGroupLayout, pub shader: Handle, } pub fn init_ui_pipeline( mut commands: Commands, render_device: Res, asset_server: Res, ) { let view_layout = render_device.create_bind_group_layout( "ui_view_layout", &BindGroupLayoutEntries::single( ShaderStages::VERTEX_FRAGMENT, uniform_buffer::(true), ), ); let image_layout = render_device.create_bind_group_layout( "ui_image_layout", &BindGroupLayoutEntries::sequential( ShaderStages::FRAGMENT, ( texture_2d(TextureSampleType::Float { filterable: true }), sampler(SamplerBindingType::Filtering), ), ), ); commands.insert_resource(UiPipeline { view_layout, image_layout, shader: load_embedded_asset!(asset_server.as_ref(), "ui.wgsl"), }); } #[derive(Clone, Copy, Hash, PartialEq, Eq)] pub struct UiPipelineKey { pub hdr: bool, pub anti_alias: bool, } impl SpecializedRenderPipeline for UiPipeline { type Key = UiPipelineKey; fn specialize(&self, key: Self::Key) -> RenderPipelineDescriptor { let vertex_layout = VertexBufferLayout::from_vertex_formats( VertexStepMode::Vertex, vec![ // position VertexFormat::Float32x3, // uv VertexFormat::Float32x2, // color VertexFormat::Float32x4, // mode VertexFormat::Uint32, // border radius VertexFormat::Float32x4, // border thickness VertexFormat::Float32x4, // border size VertexFormat::Float32x2, // position relative to the center VertexFormat::Float32x2, ], ); let shader_defs = if key.anti_alias { vec!["ANTI_ALIAS".into()] } else { Vec::new() }; RenderPipelineDescriptor { vertex: VertexState { shader: self.shader.clone(), shader_defs: shader_defs.clone(), buffers: vec![vertex_layout], ..default() }, fragment: Some(FragmentState { shader: self.shader.clone(), shader_defs, targets: vec![Some(ColorTargetState { format: if key.hdr { ViewTarget::TEXTURE_FORMAT_HDR } else { TextureFormat::bevy_default() }, blend: Some(BlendState::ALPHA_BLENDING), write_mask: ColorWrites::ALL, })], ..default() }), layout: vec![self.view_layout.clone(), self.image_layout.clone()], label: Some("ui_pipeline".into()), ..default() } } }