Skip to content

UI Node Gradients #18139

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 138 commits into
base: main
Choose a base branch
from
Open

UI Node Gradients #18139

wants to merge 138 commits into from

Conversation

ickshonpe
Copy link
Contributor

@ickshonpe ickshonpe commented Mar 3, 2025

Objective

Allowing drawing of UI nodes with a gradient instead of a flat color.

Solution

The are three gradient structs corresponding to the three types of gradients supported: LinearGradient, ConicGradient and RadialGradient. These are then wrapped in a Gradient enum discriminator which has Linear, Conic and Radial variants.

Each gradient type consists of the geometric properties for that gradient and a list of color stops.
Color stops consist of a color, a position or angle and an optional hint. If no position is specified for a stop, it's evenly spaced between the previous and following stops. Color stop postions are absolute, if you specify a list of stops:
vec![vec![ColorStop::new(RED, Val::Percent(90.), ColorStop::new(Color::GREEN, Val::Percent(10.))
the colors will be reordered and the gradient will transition from green at 10% to red at 90%.

Colors are interpolated between the stops in SRGB space. The hint is a normalized value that can be used to shift the mid-point where the colors are mixed 50-50. between the stop with the hint and the following stop.

For sharp stops with no interpolated transition, place two stops at the same position.

ConicGradients and RadialGradients have a center which is set using the new Positiontype.Position` consists of normalized (relative to the UI node) Vec2 anchor point and a responsive x, y offset.

To draw a UI node with a gradient you insert the components BackgroundGradient and BorderGradient, which both newtype a vector of Gradients. If you set a background color, the background color is drawn first and the gradient(s) are drawn on top.

The implementation is deliberately simple and self contained. The shader draws the gradient in multiple passes which is quite inefficient for gradients with a very large number of color stops. It's simple though and there won't be any compatibility issues. We could make gradients a specialization for UiPipeline but I used a separate pipeline plugin for now to ensure that these changes don't break anything.

Not supported in this PR

  • Interpolation in other color spaces besides SRGB.
  • Images and text: This would need some breaking changes like a UiColor enum type with Color and Gradient variants, to enable BorderColor, TextColor, BackgroundColor and ImageNode::color to take either a Color or a gradient.
  • Repeating gradients

Testing

Includes three examples that can be used for testing:

cargo run --example linear_gradients
cargo run --example stacked_gradients
cargo run --example radial_gradients

Most of the code except the components API is contained within the bevy_ui/src/render/linear_gradients module.
There are no changes to any existing systems or plugins except for the addition of the gradients rendering systems to the render world schedule and the Val changes from #18164 .

Showcase

gradients
stacked
rad

Conic gradients can be used to draw simple pie charts like in CSS:
PIE

@ickshonpe ickshonpe changed the title UI Linear Gradients UI Node Gradients Mar 3, 2025
@alice-i-cecile alice-i-cecile added C-Feature A new feature, making something new possible A-Rendering Drawing game state to the screen A-UI Graphical user interfaces, styles, layouts, and widgets labels Mar 3, 2025
Copy link
Contributor

@atlv24 atlv24 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great, thanks!

@extrawurst
Copy link
Contributor

@alice-i-cecile is there any chance to get this still in for 0.16? Would love to see that - what can I do to help?

@alice-i-cecile alice-i-cecile added S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it and removed S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Mar 22, 2025
@alice-i-cecile
Copy link
Member

This has two approvals so it's ready to merge but I'm reluctant to ship a feature after the initial release candidate has been cut.

@extrawurst
Copy link
Contributor

FWIW I tested the examples, works great for me.

@alice-i-cecile alice-i-cecile added this to the 0.17 milestone Mar 23, 2025
@ickshonpe
Copy link
Contributor Author

ickshonpe commented Mar 24, 2025

@alice-i-cecile is there any chance to get this still in for 0.16? Would love to see that - what can I do to help?

This has missed the deadline for 0.16 features but the changes here are only very loosely coupled to the rest of bevy_ui, it should (hopefully) be really simple to copy the gradients plugin module, the components, and the shader into your own project with minimal changes. The only sources of friction should be from this change: #18164 and maybe the shader imports. If you want to try that and have any problems, feel free to message me with any questions.

I plan to release a third-party crate but got a couple of other things I'm working on I want to get finished first this week.

Copy link
Contributor

@NthTensor NthTensor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR was created before we implemented the new release notes process, and so hasn't gotten the right pings by the bot. I'm re-adding the tags so that you'll get the new instructions.

@NthTensor NthTensor added M-Needs-Release-Note Work that should be called out in the blog due to impact and removed M-Needs-Release-Note Work that should be called out in the blog due to impact labels Apr 25, 2025
Copy link
Contributor

It looks like your PR has been selected for a highlight in the next release blog post, but you didn't provide a release note.

Please review the instructions for writing release notes, then expand or revise the content in the release notes directory to showcase your changes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Rendering Drawing game state to the screen A-UI Graphical user interfaces, styles, layouts, and widgets C-Feature A new feature, making something new possible D-Shaders This code uses GPU shader languages M-Needs-Release-Note Work that should be called out in the blog due to impact S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it
Projects
Status: No status
Development

Successfully merging this pull request may close these issues.

8 participants