Skip to content

Commit 36a9762

Browse files
Add white furnace analog for 2D color consistency (#23589)
# Objective Create a regression test for #23577. ## Solution Copy the white furnace test idea by spawning a bunch of 2D things with exactly the same color. Split out from #23584. ## Testing `cargo run -example testbed_2d`. Press space to get to the example that's all grey. Locally, this is all one uniform grey for me: I could not reproduce #23577. Still, this is a useful property to test for!
1 parent f7fb218 commit 36a9762

1 file changed

Lines changed: 80 additions & 1 deletion

File tree

examples/testbed/2d.rs

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ fn main() {
3434
OnEnter(Scene::TextureAtlasBuilder),
3535
texture_atlas_builder::setup,
3636
)
37+
.add_systems(OnEnter(Scene::ColorConsistency), color_consistency::setup)
38+
.add_systems(OnExit(Scene::ColorConsistency), color_consistency::teardown)
3739
.add_systems(Update, switch_scene)
3840
.add_systems(Update, gizmos::draw_gizmos.run_if(in_state(Scene::Gizmos)));
3941

@@ -58,6 +60,7 @@ enum Scene {
5860
SpriteSlicing,
5961
Gizmos,
6062
TextureAtlasBuilder,
63+
ColorConsistency,
6164
}
6265

6366
impl std::str::FromStr for Scene {
@@ -84,7 +87,8 @@ impl Next for Scene {
8487
Scene::Sprite => Scene::SpriteSlicing,
8588
Scene::SpriteSlicing => Scene::Gizmos,
8689
Scene::Gizmos => Scene::TextureAtlasBuilder,
87-
Scene::TextureAtlasBuilder => Scene::Shapes,
90+
Scene::TextureAtlasBuilder => Scene::ColorConsistency,
91+
Scene::ColorConsistency => Scene::Shapes,
8892
}
8993
}
9094
}
@@ -543,3 +547,78 @@ mod texture_atlas_builder {
543547
}
544548
}
545549
}
550+
551+
mod color_consistency {
552+
//! Visual regression test for <https://github.com/bevyengine/bevy/issues/23577>.
553+
//!
554+
//! The clear color and shapes rendered using different pipelines (sprites,
555+
//! 2D meshes, UI background) should produce identical pixel values for the
556+
//! same sRGB input color.
557+
//!
558+
//! If the color conversion paths are consistent, the entire window will appear
559+
//! as a uniform solid color with no visible boundaries between the strips.
560+
561+
use bevy::{core_pipeline::tonemapping::Tonemapping, prelude::*};
562+
563+
// We've chosen the sRGB value from issue #23577, in case it can be reproduced elsewhere.
564+
const TEST_COLOR: Color = Color::srgb(0.1, 0.1, 0.1);
565+
const DEFAULT_WIDTH: f32 = 1280.0;
566+
const DEFAULT_HEIGHT: f32 = 720.0;
567+
const STRIP_WIDTH: f32 = DEFAULT_WIDTH / 3.0;
568+
const STRIP_HEIGHT: f32 = DEFAULT_HEIGHT / 3.0;
569+
570+
pub fn setup(
571+
mut commands: Commands,
572+
mut meshes: ResMut<Assets<Mesh>>,
573+
mut materials: ResMut<Assets<ColorMaterial>>,
574+
) {
575+
// The window background is drawn with the clear color.
576+
commands.insert_resource(ClearColor(TEST_COLOR));
577+
578+
// Make sure there's no tonemapping
579+
commands.spawn((
580+
Camera2d,
581+
Tonemapping::None,
582+
DespawnOnExit(super::Scene::ColorConsistency),
583+
));
584+
585+
// Top third for sprites
586+
commands.spawn((
587+
Sprite {
588+
color: TEST_COLOR,
589+
custom_size: Some(Vec2::new(STRIP_WIDTH, STRIP_HEIGHT)),
590+
..default()
591+
},
592+
Transform::from_xyz(0.0, STRIP_HEIGHT, 0.0),
593+
DespawnOnExit(super::Scene::ColorConsistency),
594+
));
595+
596+
// Middle third for 2D meshes
597+
commands.spawn((
598+
Mesh2d(meshes.add(Rectangle::new(STRIP_WIDTH, STRIP_HEIGHT))),
599+
MeshMaterial2d(materials.add(ColorMaterial::from_color(TEST_COLOR))),
600+
Transform::from_xyz(0.0, 0.0, 0.0),
601+
DespawnOnExit(super::Scene::ColorConsistency),
602+
));
603+
604+
// Bottom third for UI nodes
605+
commands.spawn((
606+
Node {
607+
position_type: PositionType::Absolute,
608+
bottom: Val::Px(0.0),
609+
left: Val::Px(0.0),
610+
width: Val::Percent(33.3),
611+
height: Val::Px(STRIP_HEIGHT),
612+
..default()
613+
},
614+
BackgroundColor(TEST_COLOR),
615+
DespawnOnExit(super::Scene::ColorConsistency),
616+
));
617+
}
618+
619+
// Remember to reset the clear color
620+
// Tonemapping is per-camera, and is reset when the camera despawns
621+
pub fn teardown(mut commands: Commands) {
622+
commands.insert_resource(ClearColor::default());
623+
}
624+
}

0 commit comments

Comments
 (0)