Skip to content
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

Implement filmic color grading. #13121

Merged
merged 5 commits into from May 2, 2024
Merged

Conversation

pcwalton
Copy link
Contributor

This commit expands Bevy's existing tonemapping feature to a complete set of filmic color grading tools, matching those of engines like Unity, Unreal, and Godot. The following features are supported:

  • White point adjustment. This is inspired by Unity's implementation of the feature, but simplified and optimized. Temperature and tint control the adjustments to the x and y chromaticity values of CIE 1931. Following Unity, the adjustments are made relative to the D65 standard illuminant in the LMS color space.

  • Hue rotation. This simply converts the RGB value to HSV, alters the hue, and converts back.

  • Color correction. This allows the gamma, gain, and lift values to be adjusted according to the standard ASC CDL combined function.

  • Separate color correction for shadows, midtones, and highlights. Blender's source code was used as a reference for the implementation of this. The midtone ranges can be adjusted by the user. To avoid abrupt color changes, a small crossfade is used between the different sections of the image, again following Blender's formulas.

A new example, color_grading, has been added, offering a GUI to change all the color grading settings. It uses the same test scene as the existing tonemapping example, which has been factored out into a shared glTF scene.

Changelog

Added

  • Many new filmic color grading options have been added to the ColorGrading component.

Migration Guide

  • ColorGrading::gamma and ColorGrading::pre_saturation are now set separately for the shadows, midtones, and highlights sections. You can migrate code with the ColorGrading::all_sections and ColorGrading::all_sections_mut functions, which access and/or update all sections at once.
  • ColorGrading::post_saturation and ColorGrading::exposure are now fields of ColorGrading::global.

Screenshots

Screenshot 2024-04-27 143144

Screenshot 2024-04-27 143216

@pcwalton pcwalton added A-Rendering Drawing game state to the screen C-Enhancement A new feature labels Apr 27, 2024
@pcwalton pcwalton added this to the 0.14 milestone Apr 27, 2024
Copy link
Contributor

The generated examples/README.md is out of sync with the example metadata in Cargo.toml or the example readme template. Please run cargo run -p build-templated-pages -- update examples to update it, and commit the file change.

@pcwalton pcwalton force-pushed the color-grading branch 2 times, most recently from 01d6ecf to d87aa2d Compare April 28, 2024 00:13
This commit expands Bevy's existing tonemapping feature to a complete
set of filmic color grading tools, matching those of engines like Unity,
Unreal, and Godot. The following features are supported:

* White point adjustment. This is inspired by Unity's implementation of
  the feature, but simplified and optimized. *Temperature* and *tint*
  control the adjustments to the *x* and *y* chromaticity values of [CIE
  1931]. Following Unity, the adjustments are made relative to the [D65
  standard illuminant] in the [LMS color space].

* Hue rotation. This simply converts the RGB value to [HSV], alters the
  hue, and converts back.

* Color correction. This allows the *gamma*, *gain*, and *lift* values
  to be adjusted according to the standard [ASC CDL combined function].

* Separate color correction for shadows, midtones, and highlights.
  Blender's source code was used as a reference for the implementation
  of this. The midtone ranges can be adjusted by the user. To avoid
  abrupt color changes, a small crossfade is used between the different
  sections of the image, again following Blender's formulas.

A new example, `color_grading`, has been added, offering a GUI to change
all the color grading settings. It uses the same test scene as the
existing `tonemapping` example, which has been factored out into a
shared glTF scene.

[CIE 1931]: https://en.wikipedia.org/wiki/CIE_1931_color_space

[D65 standard illuminant]: https://en.wikipedia.org/wiki/Standard_illuminant#Illuminant_series_D

[LMS color space]: https://en.wikipedia.org/wiki/LMS_color_space

[HSV]: https://en.wikipedia.org/wiki/HSL_and_HSV

[ASC CDL combined function]: https://en.wikipedia.org/wiki/ASC_CDL#Combined_Function
}

impl Default for ColorGrading {
/// The [`ColorGrading`] structure, packed into the most efficient form for the
/// GPU.
Copy link
Contributor

Choose a reason for hiding this comment

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

Out of interest and learning, how/why is this most efficient?
I'm thinking it has to do with the fact that the fields of the struct are of decreasing size?

Copy link
Contributor Author

@pcwalton pcwalton Apr 30, 2024

Choose a reason for hiding this comment

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

Because:

(1) Shadows, midtones, and highlights are split out into struct-of-vectors instead of array-of-structs, turning the math into a series of dot products;

(2) White balance is baked into a 3x3 matrix ahead of time so the work doesn't have to be redone for every pixel.

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 is some of the highest quality and best documented code I've had the pleasure of reviewing. Color math looks right, the method seems solid.

I really appreciate the technical precision in the comments. Would that the entire engine was this exact with its color terminology.

I haven't played with this locally, but I plan to later today. Will report back if I find anything.

@alice-i-cecile
Copy link
Member

@Kurble @fintelia if either of you have the time, I'd be interested in a review from you based on your work with auto-exposure.

Copy link
Member

@alice-i-cecile alice-i-cecile left a comment

Choose a reason for hiding this comment

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

I'm actually quite comfortable with this PR's contents! I've had a solid chance to get acquainted with the color math and basic concepts of color manipulation in the past, and the shaders are straightforward enough.

I'm very pleased with the end user API as well: clearly documented, intuitive parameters.

As expected, the code quality and documentation are both top notch.

@alice-i-cecile alice-i-cecile added the S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it label May 2, 2024
@alice-i-cecile alice-i-cecile added this pull request to the merge queue May 2, 2024
Merged via the queue into bevyengine:main with commit 961b24d May 2, 2024
32 checks passed
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 C-Enhancement A new feature S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants