fix(render): colour-7 solid edges contrast with a layout's paper

A solid's edges and silhouettes were drawn in its face colour, and the
edge shader read that from the material instead of the edge vertices.
Colour 7 is white, so in Wireframe 2D a solid vanished white-on-white in
a layout viewport (and on a light model background), while wires and
block solids already turned black there. Solids now keep a separate
edge colour, colour 7 turned against the background they are drawn on,
and the edge shader uses the edge vertices' colour again, which also
brings back visual-style edge colours. Shaded faces keep their colour
so they still read as lit. (#1446)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Hakan SevenandClaude Opus 5.5 committed 2026-10-15 21:07:05 +03:00
1 parent 44c6ddc513
commit 19cc2e1073
6 files changed
+24 -8

No files matched your search

+1
View File
@@ -2549,6 +2549,7 @@ mod tests {
instance_transform: None,
instance_handle: None,
instance_color: None,
edge_color: None,
instance_aabb: None,
}
}
+7
View File
@@ -1991,6 +1991,7 @@ fn transform_block_mesh_lod_set(set: &MeshLodSet, xform: &codec::types::Transfor
instance_transform: Some(*xform),
instance_handle: None,
instance_color: set.display_color(),
edge_color: set.edge_color,
instance_aabb: bounds
.iter()
.all(|value| value.is_finite())
@@ -8994,6 +8995,12 @@ impl Scene {
entity,
viewport,
);
// Colour 7 lines contrast with what the solid is drawn
// on; shaded faces keep the colour so they still read as
// lit. White edges on a white sheet hid a wireframe solid
// in a layout viewport. (#1446)
let edge = crate::scene::view::render::adapt_to_bg(style.0, self.current_bg());
set.edge_color = (edge != style.0).then_some(edge);
let attached_material = set
.material
.as_ref()
+4
View File
@@ -145,6 +145,9 @@ pub struct MeshLodSet {
pub instance_handle: Option<codec::Handle>,
/// Effective colour after INSERT inheritance, without copying the mesh.
pub instance_color: Option<[f32; 4]>,
/// Colour of the edge and silhouette lines when it differs from the
/// faces': colour 7 drawn against the background it sits on.
pub edge_color: Option<[f32; 4]>,
/// Precise world bounds used by the interaction index.
pub instance_aabb: Option<[f64; 6]>,
}
@@ -249,6 +252,7 @@ impl MeshLodSet {
instance_transform: None,
instance_handle: None,
instance_color: None,
edge_color: None,
instance_aabb: None,
}
}
+4 -6
View File
@@ -1412,13 +1412,12 @@ fn build_instanced_chunks(
Vec::new()
};
let vertices_at = profile_enabled.then(iced::time::Instant::now);
let edge_base = first.set.edge_color.unwrap_or(first.display_color);
let edge_color = first
.set
.visual_style
.as_ref()
.map_or(first.display_color, |style| {
style.edge_color(first.display_color)
});
.map_or(edge_base, |style| style.edge_color(edge_base));
let edge_key = (source_handle, edge_color.map(f32::to_bits));
let shared_edge_buffer = (first.include_edges && !split_geometry)
.then(|| buffers.edges.get(&edge_key).cloned())
@@ -2215,12 +2214,11 @@ pub fn build_mesh_batch_filtered(
let uv_mesh = part.uv_mesh;
let local_bounds = mesh_bounds(uv_mesh);
let model_bounds = mesh_bounds(mesh);
let edge_base = set.edge_color.unwrap_or(part.display_color);
let edge_color = set
.visual_style
.as_ref()
.map_or(part.display_color, |style| {
style.edge_color(part.display_color)
});
.map_or(edge_base, |style| style.edge_color(edge_base));
let vtx = |vi: usize,
local_mapping_normal: Option<[f32; 3]>,
model_mapping_normal: Option<[f32; 3]>| {
+4 -1
View File
@@ -3191,7 +3191,10 @@ analytic={:.1} regular={:.1} blocks={:.1}",
let mut slots = rustc_hash::FxHashMap::default();
let mut groups: Vec<Vec<&crate::scene::model::mesh_model::MeshLodSet>> = Vec::new();
for (index, set) in sets.iter().enumerate() {
let color = set.display_color().unwrap_or([0.0, 0.0, 0.0, 1.0]);
let color = set
.edge_color
.or_else(|| set.display_color())
.unwrap_or([0.0, 0.0, 0.0, 1.0]);
let key = match (&set.instance_source, set.instance_transform) {
(Some(source), Some(transform)) => {
let matrix = &transform.matrix.m;
+4 -1
View File
@@ -594,7 +594,10 @@ fn fs_main(in: VertexOut) -> @location(0) vec4<f32> {
// wireframe and hidden-line edge passes so lines read at their true colour.
@fragment
fn fs_edge(in: EdgeVertexOut) -> @location(0) vec4<f32> {
return vec4<f32>(surface.face_color.rgb, 1.0);
// The edge buffers carry their own colour (keyed by it, so instances
// share a buffer only with the same colour): a visual style's edge
// colour, or colour 7 turned against the background (#1446).
return vec4<f32>(in.color.rgb, 1.0);
}
// Edge fragment for filled render modes: force black so edges frame the shaded