bevy_color: Added Color Conversion Mermaid Diagram (#12147)

Shows relationships between color spaces and explains what files should
contain which conversions.

# Objective

- Provide documentation for maintainers and users on how color space
conversion is implemented.

## Solution

- Created a mermaid diagram documenting the relationships between
various color spaces. This diagram also includes links to defining
articles, and edges include links to conversion formulae.
- Added a `conversion.md` document which is included in the
documentation of each of the color spaces. This ensures it is readily
visible in all relevant contexts.


## Notes

The diagram is in the Mermaid (`.mmd`) format, and must be converted
into an SVG file (or other image format) prior to use in Rust
documentation. I've included a link to
[mermaid.live](https://mermaid.live) as an option for doing such
conversion in an appropriate README.

Below is a screenshot of the documentation added.


![Capture](https://github.com/bevyengine/bevy/assets/2217286/370a65f2-6dd4-4af7-a99b-3763832d1b8a)
This commit is contained in:
Zachary Harrold 2024-02-27 17:03:34 +11:00 committed by GitHub
parent 00b6545fe4
commit bbcdf6815d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 86 additions and 5 deletions

View file

@ -0,0 +1,16 @@
# Conversion
Conversion between the various color spaces is achieved using Rust's native [From] trait. Because certain color spaces are defined by their transformation to and from another space, these [From] implementations reflect that set of definitions.
```rust
# use bevy_color::{Srgba, LinearRgba};
let color = Srgba::rgb(0.5, 0.5, 0.5);
// Using From explicitly
let linear_color = LinearRgba::from(color);
// Using Into
let linear_color: LinearRgba = color.into();
```
For example, the [sRGB](crate::Srgba) space is defined by its relationship with [Linear RGB](crate::LinearRgba), and [HWB](crate::Hwba) by its with [sRGB](crate::Srgba). As such, it is the responsibility of [sRGB](crate::Srgba) to provide [From] implementations for [Linear RGB](crate::LinearRgba), and [HWB](crate::Hwba) for [sRGB](crate::Srgba). To then provide conversion between [Linear RGB](crate::LinearRgba) and [HWB](crate::Hwba) directly, [HWB](crate::Hwba) is responsible for implementing these conversions, delegating to [sRGB](crate::Srgba) as an intermediatory. This ensures that all conversions take the shortest path between any two spaces, and limit the proliferation of domain specific knowledge for each color space to their respective definitions.

View file

@ -0,0 +1,3 @@
# Creating Mermaid Diagrams
Mermaid diagrams (`.mmd` files) can be converted to SVG using various tools. The simplest to work with is [mermaid.live](https://mermaid.live/), which is a HTML web app. When editing `.mmd` files, make sure to regenerate the associated SVGs.

View file

@ -0,0 +1,22 @@
%%{ init: { 'theme': 'dark', 'flowchart': { 'curve': 'stepAfter', 'padding': 30 }, 'themeCSS': '.label foreignObject { overflow: visible; }' } }%%
flowchart LR
lRGB(<a href='https://en.wikipedia.org/wiki/Rgb'>Linear<br/>sRGB</a>)
Oklab(<a href='https://oklch.com/'>Oklab</a>)
Oklch(<a href='https://oklch.com/'>Oklch</a>)
XYZ(<a href='https://en.wikipedia.org/wiki/XYZ_color'>XYZ</a>)
Lab(<a href='https://en.wikipedia.org/wiki/Lab_color'>Lab</a>)
Lch(<a href='https://en.wikipedia.org/wiki/CIELAB_color_space#Cylindrical_model'>Lch</a>)
sRGB(<a href='https://en.wikipedia.org/wiki/Srgb'>sRGB</a>)
HWB(<a href='https://en.wikipedia.org/wiki/HWB_color_model'>HWB</a>)
HSV(<a href='https://en.wikipedia.org/wiki/HSL_and_HSV'>HSV</a>)
HSL(<a href='https://en.wikipedia.org/wiki/HSL_and_HSV'>HSL</a>)
GPU <--> lRGB
lRGB <--<a href='https://bottosson.github.io/posts/oklab/#converting-from-linear-srgb-to-oklab'>Conversion</a>--> Oklab
Oklab <--<a href='https://bottosson.github.io/posts/oklab/#the-oklab-color-space'>Conversion</a>--> Oklch
lRGB <--<a href='http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html'>Conversion</a>--> XYZ
XYZ <--<a href='http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_Lab.html'>Conversion</a>--> Lab
Lab <--<a href='http://www.brucelindbloom.com/index.html?Eqn_Lab_to_LCH.html'>Conversion</a>--> Lch
lRGB <--<a href='https://en.wikipedia.org/wiki/SRGB#From_sRGB_to_CIE_XYZ'>Conversion</a>--> sRGB
sRGB <--<a href='http://alvyray.com/Papers/CG/HWB_JGTv208.pdf'>Conversion</a>--> HWB
HWB <--<a href='http://alvyray.com/Papers/CG/HWB_JGTv208.pdf'>Conversion</a>--> HSV
HSV <--<a href='https://en.wikipedia.org/wiki/HSL_and_HSV#Interconversion'>Conversion</a>--> HSL

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 19 KiB

View file

@ -6,6 +6,10 @@ use serde::{Deserialize, Serialize};
///
/// This is useful when you need to store a color in a data structure that can't be generic over
/// the color type.
#[doc = include_str!("../docs/conversion.md")]
/// <div>
#[doc = include_str!("../docs/diagrams/model_graph.svg")]
/// </div>
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, Reflect)]
#[reflect(PartialEq, Serialize, Deserialize)]
pub enum Color {

View file

@ -4,6 +4,10 @@ use serde::{Deserialize, Serialize};
/// Color in Hue-Saturation-Lightness (HSL) color space with alpha.
/// Further information on this color model can be found on [Wikipedia](https://en.wikipedia.org/wiki/HSL_and_HSV).
#[doc = include_str!("../docs/conversion.md")]
/// <div>
#[doc = include_str!("../docs/diagrams/model_graph.svg")]
/// </div>
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, Reflect)]
#[reflect(PartialEq, Serialize, Deserialize)]
pub struct Hsla {

View file

@ -4,6 +4,10 @@ use serde::{Deserialize, Serialize};
/// Color in Hue-Saturation-Value (HSV) color space with alpha.
/// Further information on this color model can be found on [Wikipedia](https://en.wikipedia.org/wiki/HSL_and_HSV).
#[doc = include_str!("../docs/conversion.md")]
/// <div>
#[doc = include_str!("../docs/diagrams/model_graph.svg")]
/// </div>
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, Reflect)]
#[reflect(PartialEq, Serialize, Deserialize)]
pub struct Hsva {

View file

@ -8,6 +8,10 @@ use serde::{Deserialize, Serialize};
/// Color in Hue-Whiteness-Blackness (HWB) color space with alpha.
/// Further information on this color model can be found on [Wikipedia](https://en.wikipedia.org/wiki/HWB_color_model).
#[doc = include_str!("../docs/conversion.md")]
/// <div>
#[doc = include_str!("../docs/diagrams/model_graph.svg")]
/// </div>
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, Reflect)]
#[reflect(PartialEq, Serialize, Deserialize)]
pub struct Hwba {

View file

@ -5,6 +5,10 @@ use bevy_reflect::{Reflect, ReflectDeserialize, ReflectSerialize};
use serde::{Deserialize, Serialize};
/// Color in LAB color space, with alpha
#[doc = include_str!("../docs/conversion.md")]
/// <div>
#[doc = include_str!("../docs/diagrams/model_graph.svg")]
/// </div>
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, Reflect)]
#[reflect(PartialEq, Serialize, Deserialize)]
pub struct Laba {

View file

@ -3,6 +3,10 @@ use bevy_reflect::{Reflect, ReflectDeserialize, ReflectSerialize};
use serde::{Deserialize, Serialize};
/// Color in LCH color space, with alpha
#[doc = include_str!("../docs/conversion.md")]
/// <div>
#[doc = include_str!("../docs/diagrams/model_graph.svg")]
/// </div>
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, Reflect)]
#[reflect(PartialEq, Serialize, Deserialize)]
pub struct Lcha {

View file

@ -50,11 +50,10 @@
//!
//! See also the [Wikipedia article on color spaces](https://en.wikipedia.org/wiki/Color_space).
//!
//! # Conversions
//!
//! Each color space can be converted to and from the others using the [`From`] trait. Not all
//! possible combinations of conversions are provided, but every color space has a conversion to
//! and from [`Srgba`] and [`LinearRgba`].
#![doc = include_str!("../docs/conversion.md")]
//! <div>
#![doc = include_str!("../docs/diagrams/model_graph.svg")]
//! </div>
//!
//! # Other Utilities
//!

View file

@ -5,6 +5,10 @@ use bytemuck::{Pod, Zeroable};
use serde::{Deserialize, Serialize};
/// Linear RGB color with alpha.
#[doc = include_str!("../docs/conversion.md")]
/// <div>
#[doc = include_str!("../docs/diagrams/model_graph.svg")]
/// </div>
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, Reflect)]
#[reflect(PartialEq, Serialize, Deserialize)]
#[repr(C)]

View file

@ -6,6 +6,10 @@ use bevy_reflect::{Reflect, ReflectDeserialize, ReflectSerialize};
use serde::{Deserialize, Serialize};
/// Color in Oklaba color space, with alpha
#[doc = include_str!("../docs/conversion.md")]
/// <div>
#[doc = include_str!("../docs/diagrams/model_graph.svg")]
/// </div>
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, Reflect)]
#[reflect(PartialEq, Serialize, Deserialize)]
pub struct Oklaba {

View file

@ -6,6 +6,10 @@ use serde::{Deserialize, Serialize};
use thiserror::Error;
/// Non-linear standard RGB with alpha.
#[doc = include_str!("../docs/conversion.md")]
/// <div>
#[doc = include_str!("../docs/diagrams/model_graph.svg")]
/// </div>
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, Reflect)]
#[reflect(PartialEq, Serialize, Deserialize)]
pub struct Srgba {

View file

@ -3,6 +3,10 @@ use bevy_reflect::{Reflect, ReflectDeserialize, ReflectSerialize};
use serde::{Deserialize, Serialize};
/// [CIE 1931](https://en.wikipedia.org/wiki/CIE_1931_color_space) color space, also known as XYZ, with an alpha channel.
#[doc = include_str!("../docs/conversion.md")]
/// <div>
#[doc = include_str!("../docs/diagrams/model_graph.svg")]
/// </div>
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, Reflect)]
#[reflect(PartialEq, Serialize, Deserialize)]
pub struct Xyza {