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

Use bitbybit to encode the MeshPipelineKey #10246

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions crates/bevy_core_pipeline/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ bevy_transform = { path = "../bevy_transform", version = "0.12.0-dev" }
bevy_math = { path = "../bevy_math", version = "0.12.0-dev" }
bevy_utils = { path = "../bevy_utils", version = "0.12.0-dev" }

arbitrary-int = "1.2.6"
bitbybit = "1.2.2"
serde = { version = "1", features = ["derive"] }
bitflags = "2.3"
radsort = "0.1"
86 changes: 37 additions & 49 deletions crates/bevy_core_pipeline/src/tonemapping/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,37 +114,36 @@ pub struct TonemappingPipeline {
}

/// Optionally enables a tonemapping shader that attempts to map linear input stimulus into a perceptually uniform image for a given [`Camera`] entity.
#[derive(
Component, Debug, Hash, Clone, Copy, Reflect, Default, ExtractComponent, PartialEq, Eq,
)]
#[derive(Component, Debug, Hash, Reflect, Default, ExtractComponent, PartialEq, Eq)]
#[extract_component_filter(With<Camera>)]
#[reflect(Component)]
#[bitbybit::bitenum(u3, exhaustive: true)]
pub enum Tonemapping {
/// Bypass tonemapping.
None,
None = 0,
/// Suffers from lots hue shifting, brights don't desaturate naturally.
/// Bright primaries and secondaries don't desaturate at all.
Reinhard,
Reinhard = 1,
/// Suffers from hue shifting. Brights don't desaturate much at all across the spectrum.
ReinhardLuminance,
ReinhardLuminance = 2,
/// Same base implementation that Godot 4.0 uses for Tonemap ACES.
/// <https://github.com/TheRealMJP/BakingLab/blob/master/BakingLab/ACES.hlsl>
/// Not neutral, has a very specific aesthetic, intentional and dramatic hue shifting.
/// Bright greens and reds turn orange. Bright blues turn magenta.
/// Significantly increased contrast. Brights desaturate across the spectrum.
AcesFitted,
AcesFitted = 3,
/// By Troy Sobotka
/// <https://github.com/sobotka/AgX>
/// Very neutral. Image is somewhat desaturated when compared to other tonemappers.
/// Little to no hue shifting. Subtle [Abney shifting](https://en.wikipedia.org/wiki/Abney_effect).
/// NOTE: Requires the `tonemapping_luts` cargo feature.
AgX,
AgX = 4,
/// By Tomasz Stachowiak
/// Has little hue shifting in the darks and mids, but lots in the brights. Brights desaturate across the spectrum.
/// Is sort of between Reinhard and ReinhardLuminance. Conceptually similar to reinhard-jodie.
/// Designed as a compromise if you want e.g. decent skin tones in low light, but can't afford to re-do your
/// VFX to look good without hue shifting.
SomewhatBoringDisplayTransform,
SomewhatBoringDisplayTransform = 5,
/// Current Bevy default.
/// By Tomasz Stachowiak
/// <https://github.com/h3r2tic/tony-mc-mapface>
Expand All @@ -158,17 +157,42 @@ pub enum Tonemapping {
/// To avoid posterization, selective desaturation is employed, with care to avoid the [Abney effect](https://en.wikipedia.org/wiki/Abney_effect).
/// NOTE: Requires the `tonemapping_luts` cargo feature.
#[default]
TonyMcMapface,
TonyMcMapface = 6,
/// Default Filmic Display Transform from blender.
/// Somewhat neutral. Suffers from hue shifting. Brights desaturate across the spectrum.
/// NOTE: Requires the `tonemapping_luts` cargo feature.
BlenderFilmic,
BlenderFilmic = 7,
}

impl Tonemapping {
pub fn is_enabled(&self) -> bool {
*self != Tonemapping::None
}
pub const fn define(self) -> &'static str {
use Tonemapping::SomewhatBoringDisplayTransform;

match self {
Self::None => "TONEMAP_METHOD_NONE",
Self::Reinhard => "TONEMAP_METHOD_REINHARD",
Self::ReinhardLuminance => "TONEMAP_METHOD_REINHARD_LUMINANCE",
Self::AcesFitted => "TONEMAP_METHOD_ACES_FITTED",
Self::AgX => "TONEMAP_METHOD_AGX",
SomewhatBoringDisplayTransform => "TONEMAP_METHOD_SOMEWHAT_BORING_DISPLAY_TRANSFORM",
Self::TonyMcMapface => "TONEMAP_METHOD_TONY_MC_MAPFACE",
Self::BlenderFilmic => "TONEMAP_METHOD_BLENDER_FILMIC",
}
}

pub fn log_feature_error(self) {
#[cfg(not(feature = "tonemapping_luts"))]
if matches!(self, Self::AgX | Self::TonyMcMapface | Self::BlenderFilmic) {
bevy_log::error!(
"{self:?} tonemapping requires the `tonemapping_luts` feature. Either enable the \
`tonemapping_luts` feature for bevy in `Cargo.toml` (recommended), or use a \
different `Tonemapping` method in your `Camera2dBundle`/`Camera3dBundle`."
);
}
}
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
Expand All @@ -185,45 +209,9 @@ impl SpecializedRenderPipeline for TonemappingPipeline {
if let DebandDither::Enabled = key.deband_dither {
shader_defs.push("DEBAND_DITHER".into());
}
key.tonemapping.log_feature_error();
shader_defs.push(key.tonemapping.define().into());

match key.tonemapping {
Tonemapping::None => shader_defs.push("TONEMAP_METHOD_NONE".into()),
Tonemapping::Reinhard => shader_defs.push("TONEMAP_METHOD_REINHARD".into()),
Tonemapping::ReinhardLuminance => {
shader_defs.push("TONEMAP_METHOD_REINHARD_LUMINANCE".into());
}
Tonemapping::AcesFitted => shader_defs.push("TONEMAP_METHOD_ACES_FITTED".into()),
Tonemapping::AgX => {
#[cfg(not(feature = "tonemapping_luts"))]
bevy_log::error!(
"AgX tonemapping requires the `tonemapping_luts` feature.
Either enable the `tonemapping_luts` feature for bevy in `Cargo.toml` (recommended),
or use a different `Tonemapping` method in your `Camera2dBundle`/`Camera3dBundle`."
);
shader_defs.push("TONEMAP_METHOD_AGX".into());
}
Tonemapping::SomewhatBoringDisplayTransform => {
shader_defs.push("TONEMAP_METHOD_SOMEWHAT_BORING_DISPLAY_TRANSFORM".into());
}
Tonemapping::TonyMcMapface => {
#[cfg(not(feature = "tonemapping_luts"))]
bevy_log::error!(
"TonyMcMapFace tonemapping requires the `tonemapping_luts` feature.
Either enable the `tonemapping_luts` feature for bevy in `Cargo.toml` (recommended),
or use a different `Tonemapping` method in your `Camera2dBundle`/`Camera3dBundle`."
);
shader_defs.push("TONEMAP_METHOD_TONY_MC_MAPFACE".into());
}
Tonemapping::BlenderFilmic => {
#[cfg(not(feature = "tonemapping_luts"))]
bevy_log::error!(
"BlenderFilmic tonemapping requires the `tonemapping_luts` feature.
Either enable the `tonemapping_luts` feature for bevy in `Cargo.toml` (recommended),
or use a different `Tonemapping` method in your `Camera2dBundle`/`Camera3dBundle`."
);
shader_defs.push("TONEMAP_METHOD_BLENDER_FILMIC".into());
}
}
RenderPipelineDescriptor {
label: Some("tonemapping pipeline".into()),
layout: vec![self.texture_bind_group.clone()],
Expand Down
5 changes: 2 additions & 3 deletions crates/bevy_gizmos/src/pipeline_3d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ impl SpecializedRenderPipeline for LineGizmoPipeline {
shader_defs.push("PERSPECTIVE".into());
}

let format = if key.mesh_key.contains(MeshPipelineKey::HDR) {
let format = if key.mesh_key.hdr() {
ViewTarget::TEXTURE_FORMAT_HDR
} else {
TextureFormat::bevy_default()
Expand Down Expand Up @@ -168,8 +168,7 @@ fn queue_line_gizmos_3d(
continue;
}

let mesh_key = MeshPipelineKey::from_msaa_samples(msaa.samples())
| MeshPipelineKey::from_hdr(view.hdr);
let mesh_key = MeshPipelineKey::DEFAULT.with_msaa(*msaa).with_hdr(view.hdr);

for (entity, handle) in &line_gizmos {
let Some(line_gizmo) = line_gizmo_assets.get(handle) else {
Expand Down
2 changes: 2 additions & 0 deletions crates/bevy_pbr/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ bevy_window = { path = "../bevy_window", version = "0.12.0-dev" }
bevy_derive = { path = "../bevy_derive", version = "0.12.0-dev" }

# other
arbitrary-int = "1.2.6"
bitbybit = "1.2.2"
bitflags = "2.3"
fixedbitset = "0.4"
# direct dependency required for derive macro
Expand Down
56 changes: 56 additions & 0 deletions crates/bevy_pbr/src/alpha.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use bevy_reflect::std_traits::ReflectDefault;
use bevy_reflect::Reflect;
use bevy_render::render_resource::BlendState;
use bitbybit::bitenum;

// TODO: add discussion about performance.
/// Sets how a material's base color alpha channel is used for transparency.
Expand Down Expand Up @@ -47,5 +49,59 @@ pub enum AlphaMode {
/// Useful for effects like stained glass, window tint film and some colored liquids.
Multiply,
}
impl AlphaMode {
pub fn may_discard(self) -> bool {
matches!(self, Self::Mask(_))
}
}

#[bitenum(u2, exhaustive: true)]
#[derive(PartialEq)]
pub enum BlendMode {
Opaque = 0,
PremultipliedAlpha = 1,
Multiply = 2,
Alpha = 3,
}
impl From<AlphaMode> for BlendMode {
fn from(value: AlphaMode) -> Self {
match value {
AlphaMode::Premultiplied | AlphaMode::Add => BlendMode::PremultipliedAlpha,
AlphaMode::Blend => BlendMode::Alpha,
AlphaMode::Multiply => BlendMode::Multiply,
_ => BlendMode::Opaque,
}
}
}
impl BlendMode {
pub fn is_opaque(self) -> bool {
matches!(self, Self::Opaque)
}
pub fn state(self) -> Option<BlendState> {
use bevy_render::render_resource::*;
match self {
BlendMode::PremultipliedAlpha => Some(BlendState::PREMULTIPLIED_ALPHA_BLENDING),
BlendMode::Multiply => Some(BlendState {
color: BlendComponent {
src_factor: BlendFactor::Dst,
dst_factor: BlendFactor::OneMinusSrcAlpha,
operation: BlendOperation::Add,
},
alpha: BlendComponent::OVER,
}),
BlendMode::Alpha => Some(BlendState::ALPHA_BLENDING),
BlendMode::Opaque => None,
}
}
pub const fn defines(self) -> Option<[&'static str; 2]> {
match self {
BlendMode::Alpha | BlendMode::Opaque => None,
BlendMode::PremultipliedAlpha => {
Some(["PREMULTIPLY_ALPHA", "BLEND_PREMULTIPLIED_ALPHA"])
}
BlendMode::Multiply => Some(["PREMULTIPLY_ALPHA", "BLEND_MULTIPLY"]),
}
}
}

impl Eq for AlphaMode {}
Loading
Loading