feat(render): double-single fills for the face3d pipeline

Table / PolyfaceMesh / greek-text / mleader-background fills go through
the face3d pipeline; their vertices were single f32 and quantized at UTM
scale. WireModel now carries a fill_tris_low residual (filled by the
tessellate Lines path), Face3DVertex gains position_low (location 3), and
face3d.wgsl reconstructs the eye-relative position from the pair. 3DFACE
quads built from key_vertices use a zero residual (no low source).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Hakan Seven 2026-06-23 18:03:40 +03:00
commit c0f3d0de5e
41 changed files with 107 additions and 28 deletions

View file

@ -3069,6 +3069,7 @@ impl OpenCADStudio {
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
}; };
previews.push(guide); previews.push(guide);
} }
@ -3101,6 +3102,7 @@ impl OpenCADStudio {
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
}); });
} }
} }

View file

@ -1172,6 +1172,7 @@ fn tessellate_dimension_inner(
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
}); });
} }
if !ext2.is_empty() { if !ext2.is_empty() {
@ -1192,6 +1193,7 @@ fn tessellate_dimension_inner(
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
}); });
} }
} else { } else {
@ -1212,6 +1214,7 @@ fn tessellate_dimension_inner(
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
}); });
} }
} }
@ -1233,6 +1236,7 @@ fn tessellate_dimension_inner(
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: geom.arrow_fill, fill_tris: geom.arrow_fill,
fill_tris_low: Vec::new(),
}); });
// DIMTFILL: 0=none, 1=drawing background (mask), 2=DIMTFILLCLR. // DIMTFILL: 0=none, 1=drawing background (mask), 2=DIMTFILLCLR.
@ -1265,6 +1269,7 @@ fn tessellate_dimension_inner(
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: rect, fill_tris: rect,
fill_tris_low: Vec::new(),
}); });
} }
} }

View file

@ -617,6 +617,7 @@ impl LeaderTess for Leader {
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
}; };
} }
@ -716,6 +717,7 @@ impl LeaderTess for Leader {
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris, fill_tris,
fill_tris_low: Vec::new(),
} }
} }
} }

View file

@ -1309,6 +1309,7 @@ impl MultiLeaderTess for MultiLeader {
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: arrow_fill, fill_tris: arrow_fill,
fill_tris_low: Vec::new(),
}); });
// ── Block content ─────────────────────────────────────────────────────── // ── Block content ───────────────────────────────────────────────────────
@ -1556,6 +1557,7 @@ impl MultiLeaderTess for MultiLeader {
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
}); });
} }
} else if lod_mode == 1 { } else if lod_mode == 1 {
@ -1597,6 +1599,7 @@ impl MultiLeaderTess for MultiLeader {
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: greek_tris, fill_tris: greek_tris,
fill_tris_low: Vec::new(),
}); });
} }
} else { } else {
@ -1636,6 +1639,7 @@ impl MultiLeaderTess for MultiLeader {
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
}); });
} }
} }
@ -1694,6 +1698,7 @@ impl MultiLeaderTess for MultiLeader {
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris, fill_tris,
fill_tris_low: Vec::new(),
}); });
} }
@ -1723,6 +1728,7 @@ impl MultiLeaderTess for MultiLeader {
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
}); });
} }
} }

View file

@ -716,6 +716,7 @@ pub fn tessellate_table(
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris, fill_tris,
fill_tris_low: Vec::new(),
} }
}; };

View file

@ -108,6 +108,7 @@ impl CadCommand for AlignedDimensionCommand {
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
}) })
} }
} }
@ -149,6 +150,7 @@ fn preview_aligned(p1: Vec3, p2: Vec3, dim_pt: Vec3) -> WireModel {
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
} }
} }

View file

@ -140,6 +140,7 @@ fn preview_wire(points: Vec<Vec3>) -> WireModel {
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
} }
} }

View file

@ -111,6 +111,7 @@ fn preview_line(a: Vec3, b: Vec3) -> WireModel {
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
} }
} }

View file

@ -169,6 +169,7 @@ impl CadCommand for DimBaselineCommand {
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
}) })
} }
} }

View file

@ -149,6 +149,7 @@ impl CadCommand for DimContinueCommand {
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
}) })
} }
} }

View file

@ -106,6 +106,7 @@ impl CadCommand for DimJogLineCommand {
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
}) })
} }
} }

View file

@ -120,6 +120,7 @@ impl CadCommand for DimTeditCommand {
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
}) })
} }

View file

@ -179,6 +179,7 @@ fn preview_wire(pts: &[Vec3]) -> WireModel {
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
} }
} }

View file

@ -147,6 +147,7 @@ fn preview_wire(points: Vec<Vec3>) -> WireModel {
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
} }
} }

View file

@ -165,6 +165,7 @@ fn preview_wire(pts: &[Vec3]) -> WireModel {
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
} }
} }

View file

@ -472,6 +472,7 @@ fn preview_wire(pts: &[Vec3]) -> WireModel {
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
} }
} }

View file

@ -104,6 +104,7 @@ impl CadCommand for QdimCommand {
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
}) })
} }
} }

View file

@ -116,6 +116,7 @@ fn preview_wire(points: Vec<Vec3>) -> WireModel {
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
} }
} }

View file

@ -164,6 +164,7 @@ impl CadCommand for TableCommand {
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
}) })
} else { } else {
None None

View file

@ -106,6 +106,7 @@ impl CadCommand for ToleranceCommand {
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
}) })
} }
} }

View file

@ -182,6 +182,7 @@ impl CadCommand for AttdefCommand {
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
}) })
} }
} }

View file

@ -627,6 +627,7 @@ fn line_wire(from: Vec3, to: Vec3) -> WireModel {
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
} }
} }

View file

@ -92,6 +92,7 @@ impl CadCommand for LineCommand {
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
}) })
} }
} }

View file

@ -147,6 +147,7 @@ impl CadCommand for MlineCommand {
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
}) })
} }
} }

View file

@ -124,6 +124,7 @@ impl CadCommand for ImageCommand {
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
}) })
} }
} }

View file

@ -90,6 +90,7 @@ impl CadCommand for RayCommand {
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
}) })
} }
} }
@ -172,6 +173,7 @@ impl CadCommand for XLineCommand {
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
}) })
} }
} }

View file

@ -96,6 +96,7 @@ impl CadCommand for RevCloudCommand {
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
}) })
} }
} }

View file

@ -136,6 +136,7 @@ impl CadCommand for WipeoutCommand {
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
}) })
} }
WipeoutMode::Polygonal => { WipeoutMode::Polygonal => {
@ -163,6 +164,7 @@ impl CadCommand for WipeoutCommand {
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
}) })
} }
} }

View file

@ -80,6 +80,7 @@ impl CadCommand for AreaCommand {
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
}) })
} }
} }

View file

@ -75,6 +75,7 @@ impl CadCommand for DistCommand {
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
}) })
} }
} }

View file

@ -102,6 +102,7 @@ impl CadCommand for MviewCommand {
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
}) })
} }
} }

View file

@ -321,5 +321,6 @@ fn wire(name: &str, points: Vec<[f32; 3]>) -> WireModel {
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
} }
} }

View file

@ -73,6 +73,7 @@ impl CadCommand for PlotWindowCommand {
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
}) })
} }
} }

View file

@ -73,6 +73,7 @@ impl CadCommand for ZoomWindowCommand {
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
}) })
} }
} }

View file

@ -1130,6 +1130,7 @@ impl Batches {
plinegen: b.plinegen, plinegen: b.plinegen,
vp_scissor: None, vp_scissor: None,
fill_tris: b.fill_tris, fill_tris: b.fill_tris,
fill_tris_low: Vec::new(),
} }
}) })
.collect() .collect()

View file

@ -239,6 +239,7 @@ pub fn tessellate(
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
}]; }];
} }
@ -278,6 +279,7 @@ pub fn tessellate(
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
}); });
} }
return out; return out;
@ -324,6 +326,7 @@ pub fn tessellate(
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
}]; }];
} }
_ => {} _ => {}
@ -358,6 +361,7 @@ pub fn tessellate(
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
}]; }];
} }
} }
@ -390,6 +394,7 @@ pub fn tessellate(
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
}]; }];
} }
} }
@ -409,11 +414,7 @@ pub fn tessellate(
.into_iter() .into_iter()
.map(|[x, y, z]| [(x - ox) as f32, (y - oy) as f32, (z - oz) as f32]) .map(|[x, y, z]| [(x - ox) as f32, (y - oy) as f32, (z - oz) as f32])
.collect(); .collect();
let fill_tris: Vec<[f32; 3]> = te let (fill_tris, fill_tris_low) = offset_to_ds(te.fill_tris, world_offset);
.fill_tris
.into_iter()
.map(|[x, y, z]| [(x - ox) as f32, (y - oy) as f32, (z - oz) as f32])
.collect();
return vec![WireModel { return vec![WireModel {
name, name,
points: local_pts, points: local_pts,
@ -431,6 +432,7 @@ pub fn tessellate(
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris, fill_tris,
fill_tris_low,
}]; }];
} }
@ -460,6 +462,7 @@ pub fn tessellate(
vp_scissor: None, vp_scissor: None,
aabb: WireModel::UNBOUNDED_AABB, aabb: WireModel::UNBOUNDED_AABB,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
}]; }];
} }
@ -501,6 +504,7 @@ pub fn tessellate(
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
}] }]
} }

View file

@ -8210,6 +8210,7 @@ fn tessellate_entity(
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
}; };
if let Some(cache) = block_cache { if let Some(cache) = block_cache {
@ -8422,6 +8423,7 @@ fn tessellate_entity(
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
}]; }];
} }
if h_px < 5.0 && aabb != WireModel::UNBOUNDED_AABB { if h_px < 5.0 && aabb != WireModel::UNBOUNDED_AABB {
@ -8460,6 +8462,7 @@ fn tessellate_entity(
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris, fill_tris,
fill_tris_low: Vec::new(),
}]; }];
} }
} }
@ -8569,6 +8572,7 @@ fn lod_stub_wire(
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
} }
} }
@ -8628,6 +8632,7 @@ fn lod_stub_wire_3d(
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
} }
} }

View file

@ -79,6 +79,9 @@ pub struct WireModel {
/// Pre-triangulated solid fill: flat vertex list, 3 per triangle (world-offset applied). /// Pre-triangulated solid fill: flat vertex list, 3 per triangle (world-offset applied).
/// Non-empty only for PolyfaceMesh / PolygonMesh entities. /// Non-empty only for PolyfaceMesh / PolygonMesh entities.
pub fill_tris: Vec<[f32; 3]>, pub fill_tris: Vec<[f32; 3]>,
/// Low residual paired with [`fill_tris`] (double-single). Empty = all-zero;
/// tessellation from CAD f64 fills it so fills stay precise at UTM scale.
pub fill_tris_low: Vec<[f32; 3]>,
} }
impl WireModel { impl WireModel {
@ -114,6 +117,7 @@ impl WireModel {
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
} }
} }
@ -237,6 +241,7 @@ impl Default for WireModel {
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: Vec::new(), fill_tris: Vec::new(),
fill_tris_low: Vec::new(),
} }
} }
} }

View file

@ -33,30 +33,40 @@ pub struct Face3DVertex {
/// applied as a small clip-z bias in the shader. 0.0 for true 3D mesh /// applied as a small clip-z bias in the shader. 0.0 for true 3D mesh
/// faces (PolyfaceMesh / PolygonMesh) so their real depth is preserved. /// faces (PolyfaceMesh / PolygonMesh) so their real depth is preserved.
pub draw_depth: f32, pub draw_depth: f32,
/// Double-single low residual of `position` so fills stay precise at
/// UTM-scale coordinates (zero for 3DFACE quads built from key_vertices,
/// which don't carry a residual).
pub position_low: [f32; 3],
} }
impl Face3DVertex { impl Face3DVertex {
pub fn layout<'a>() -> wgpu::VertexBufferLayout<'a> { pub fn layout<'a>() -> wgpu::VertexBufferLayout<'a> {
const ATTRS: &[wgpu::VertexAttribute] = &[
wgpu::VertexAttribute {
offset: std::mem::offset_of!(Face3DVertex, position) as u64,
shader_location: 0,
format: wgpu::VertexFormat::Float32x3,
},
wgpu::VertexAttribute {
offset: std::mem::offset_of!(Face3DVertex, color) as u64,
shader_location: 1,
format: wgpu::VertexFormat::Float32x4,
},
wgpu::VertexAttribute {
offset: std::mem::offset_of!(Face3DVertex, draw_depth) as u64,
shader_location: 2,
format: wgpu::VertexFormat::Float32,
},
wgpu::VertexAttribute {
offset: std::mem::offset_of!(Face3DVertex, position_low) as u64,
shader_location: 3,
format: wgpu::VertexFormat::Float32x3,
},
];
wgpu::VertexBufferLayout { wgpu::VertexBufferLayout {
array_stride: std::mem::size_of::<Face3DVertex>() as u64, array_stride: std::mem::size_of::<Face3DVertex>() as u64,
step_mode: wgpu::VertexStepMode::Vertex, step_mode: wgpu::VertexStepMode::Vertex,
attributes: &[ attributes: ATTRS,
wgpu::VertexAttribute {
offset: 0,
shader_location: 0,
format: wgpu::VertexFormat::Float32x3,
},
wgpu::VertexAttribute {
offset: 12,
shader_location: 1,
format: wgpu::VertexFormat::Float32x4,
},
wgpu::VertexAttribute {
offset: 28,
shader_location: 2,
format: wgpu::VertexFormat::Float32,
},
],
} }
} }
} }
@ -120,6 +130,7 @@ impl Face3DGpu {
position: p[i], position: p[i],
color: fill_color, color: fill_color,
draw_depth: depth, draw_depth: depth,
position_low: [0.0; 3],
}; };
verts_3d.push(v(0)); verts_3d.push(v(0));
verts_3d.push(v(1)); verts_3d.push(v(1));
@ -153,21 +164,23 @@ impl Face3DGpu {
let fill_color = [r * 0.45, g * 0.45, b * 0.45, a]; let fill_color = [r * 0.45, g * 0.45, b * 0.45, a];
// True 3D surface: keep real depth (no draw-order bias) so // True 3D surface: keep real depth (no draw-order bias) so
// hidden-surface shading is preserved. // hidden-surface shading is preserved.
for &position in &wire.fill_tris { for (i, &position) in wire.fill_tris.iter().enumerate() {
verts_3d.push(Face3DVertex { verts_3d.push(Face3DVertex {
position, position,
color: fill_color, color: fill_color,
draw_depth: 0.0, draw_depth: 0.0,
position_low: wire.fill_tris_low.get(i).copied().unwrap_or([0.0; 3]),
}); });
} }
} else { } else {
let fill_color = [r, g, b, a]; let fill_color = [r, g, b, a];
let depth = depth_of(wire); let depth = depth_of(wire);
for &position in &wire.fill_tris { for (i, &position) in wire.fill_tris.iter().enumerate() {
verts_2d.push(Face3DVertex { verts_2d.push(Face3DVertex {
position, position,
color: fill_color, color: fill_color,
draw_depth: depth, draw_depth: depth,
position_low: wire.fill_tris_low.get(i).copied().unwrap_or([0.0; 3]),
}); });
} }
} }

View file

@ -224,6 +224,7 @@ pub fn apply_along(
plinegen: true, plinegen: true,
vp_scissor: None, vp_scissor: None,
fill_tris: vec![], fill_tris: vec![],
fill_tris_low: Vec::new(),
}) })
.collect() .collect()
} }

View file

@ -25,9 +25,10 @@ struct Uniforms {
var<uniform> u: Uniforms; var<uniform> u: Uniforms;
struct VertexIn { struct VertexIn {
@location(0) position: vec3<f32>, @location(0) position: vec3<f32>,
@location(1) color: vec4<f32>, @location(1) color: vec4<f32>,
@location(2) draw_depth: f32, @location(2) draw_depth: f32,
@location(3) position_low: vec3<f32>,
}; };
struct VertexOut { struct VertexOut {
@ -42,7 +43,8 @@ const DRAW_ORDER_BIAS: f32 = 0.001;
@vertex @vertex
fn vs_main(v: VertexIn) -> VertexOut { fn vs_main(v: VertexIn) -> VertexOut {
var out: VertexOut; var out: VertexOut;
out.clip_pos = u.view_rot * vec4<f32>((v.position - u.eye_high) - u.eye_low, 1.0); let rel = (v.position - u.eye_high) + (v.position_low - u.eye_low);
out.clip_pos = u.view_rot * vec4<f32>(rel, 1.0);
out.clip_pos.z = out.clip_pos.z - v.draw_depth * DRAW_ORDER_BIAS * out.clip_pos.w; out.clip_pos.z = out.clip_pos.z - v.draw_depth * DRAW_ORDER_BIAS * out.clip_pos.w;
out.color = v.color; out.color = v.color;
return out; return out;