Add a border to the UI material example (#15120)

# Objective

There aren't any examples of how to draw a ui material with borders.

## Solution

Add border rendering to the `ui_material` example's shader.

## Showcase

<img width="395" alt="bordermat"
src="https://github.com/user-attachments/assets/109c59c1-f54b-4542-96f7-acff63f5057f">

---------

Co-authored-by: charlotte <charlotte.c.mcelwain@gmail.com>
This commit is contained in:
ickshonpe 2024-09-09 17:34:24 +01:00 committed by GitHub
parent 79f6fcd1eb
commit 09d2292016
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 19 additions and 1 deletions

View file

@ -5,10 +5,21 @@
@group(1) @binding(1) var<uniform> slider: f32; @group(1) @binding(1) var<uniform> slider: f32;
@group(1) @binding(2) var material_color_texture: texture_2d<f32>; @group(1) @binding(2) var material_color_texture: texture_2d<f32>;
@group(1) @binding(3) var material_color_sampler: sampler; @group(1) @binding(3) var material_color_sampler: sampler;
@group(1) @binding(4) var<uniform> border_color: vec4<f32>;
@fragment @fragment
fn fragment(in: UiVertexOutput) -> @location(0) vec4<f32> { fn fragment(in: UiVertexOutput) -> @location(0) vec4<f32> {
let r = in.uv - 0.5;
let b = vec2(
select(in.border_widths.x, in.border_widths.y, r.x < 0.),
select(in.border_widths.z, in.border_widths.w, r.y < 0.)
);
if any(0.5 - b < abs(r)) {
return border_color;
}
if in.uv.x < slider { if in.uv.x < slider {
let output_color = textureSample(material_color_texture, material_color_sampler, in.uv) * color; let output_color = textureSample(material_color_texture, material_color_sampler, in.uv) * color;
return output_color; return output_color;

View file

@ -42,12 +42,14 @@ fn setup(
position_type: PositionType::Absolute, position_type: PositionType::Absolute,
width: Val::Px(905.0 * banner_scale_factor), width: Val::Px(905.0 * banner_scale_factor),
height: Val::Px(363.0 * banner_scale_factor), height: Val::Px(363.0 * banner_scale_factor),
border: UiRect::all(Val::Px(10.)),
..default() ..default()
}, },
material: ui_materials.add(CustomUiMaterial { material: ui_materials.add(CustomUiMaterial {
color: LinearRgba::WHITE.to_f32_array().into(), color: LinearRgba::WHITE.to_f32_array().into(),
slider: 0.5, slider: 0.5,
color_texture: asset_server.load("branding/banner.png"), color_texture: asset_server.load("branding/banner.png"),
border_color: LinearRgba::WHITE.to_f32_array().into(),
}), }),
..default() ..default()
}); });
@ -67,6 +69,9 @@ struct CustomUiMaterial {
#[texture(2)] #[texture(2)]
#[sampler(3)] #[sampler(3)]
color_texture: Handle<Image>, color_texture: Handle<Image>,
/// Color of the image's border
#[uniform(4)]
border_color: Vec4,
} }
impl UiMaterial for CustomUiMaterial { impl UiMaterial for CustomUiMaterial {
@ -87,9 +92,11 @@ fn animate(
if let Some(material) = materials.get_mut(handle) { if let Some(material) = materials.get_mut(handle) {
// rainbow color effect // rainbow color effect
let new_color = Color::hsl((time.elapsed_seconds() * 60.0) % 360.0, 1., 0.5); let new_color = Color::hsl((time.elapsed_seconds() * 60.0) % 360.0, 1., 0.5);
material.color = LinearRgba::from(new_color).to_f32_array().into(); let border_color = Color::hsl((time.elapsed_seconds() * 60.0) % 360.0, 0.75, 0.75);
material.color = new_color.to_linear().to_vec4();
material.slider = material.slider =
((time.elapsed_seconds() % (duration * 2.0)) - duration).abs() / duration; ((time.elapsed_seconds() % (duration * 2.0)) - duration).abs() / duration;
material.border_color = border_color.to_linear().to_vec4();
} }
} }
} }