khora_core/asset/materials/wireframe.rs
1// Copyright 2025 eraflo
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Defines wireframe materials for debug visualization and editor tools.
16
17use crate::{
18 asset::{Asset, Material},
19 math::LinearRgba,
20};
21
22/// A material that renders geometry as a wireframe for debugging and editor visualization.
23///
24/// Wireframe materials are essential for debug views, editor gizmos, and understanding
25/// the underlying geometry of meshes. This material will integrate with the future
26/// EditorGizmo RenderLane (issue #167) and is designed for development and debugging,
27/// not production rendering.
28///
29/// # Performance Note
30///
31/// Wireframe rendering typically requires either:
32/// - A geometry shader to generate line primitives
33/// - Barycentric coordinates in the fragment shader
34///
35/// The exact implementation will depend on the graphics backend capabilities.
36/// This material is intended for debug/editor contexts where performance is less critical.
37///
38/// # Examples
39///
40/// ```
41/// use khora_core::asset::WireframeMaterial;
42/// use khora_core::math::LinearRgba;
43///
44/// // Create a green wireframe for debug visualization
45/// let debug_wireframe = WireframeMaterial {
46/// color: LinearRgba::new(0.0, 1.0, 0.0, 1.0),
47/// line_width: 1.5,
48/// };
49///
50/// // Create a thin white wireframe for mesh inspection
51/// let mesh_inspector = WireframeMaterial {
52/// color: LinearRgba::new(1.0, 1.0, 1.0, 1.0),
53/// line_width: 1.0,
54/// };
55/// ```
56#[derive(Clone, Debug)]
57pub struct WireframeMaterial {
58 /// The color of the wireframe lines.
59 ///
60 /// This color is used for all edges of the geometry. Typically bright colors
61 /// like green, cyan, or white are used for maximum visibility against the scene.
62 pub color: LinearRgba,
63
64 /// The width of the wireframe lines in pixels.
65 ///
66 /// Note that line width support varies by platform and graphics backend:
67 /// - **Vulkan**: Limited support for line widths other than 1.0
68 /// - **Metal/DX12**: Good support for varying line widths
69 /// - **WebGPU**: Limited to 1.0 pixel lines
70 ///
71 /// For maximum compatibility, use 1.0. The rendering system may clamp this value
72 /// based on backend capabilities.
73 pub line_width: f32,
74}
75
76impl Default for WireframeMaterial {
77 fn default() -> Self {
78 Self {
79 color: LinearRgba::new(0.0, 1.0, 0.0, 1.0), // Green - common for wireframes
80 line_width: 1.0, // Standard 1-pixel lines
81 }
82 }
83}
84
85impl Asset for WireframeMaterial {}
86impl Material for WireframeMaterial {}
87
88#[cfg(test)]
89mod tests {
90 use super::*;
91
92 #[test]
93 fn test_wireframe_material_default() {
94 let material = WireframeMaterial::default();
95
96 assert_eq!(material.color, LinearRgba::new(0.0, 1.0, 0.0, 1.0));
97 assert_eq!(material.line_width, 1.0);
98 }
99
100 #[test]
101 fn test_wireframe_material_custom_color() {
102 let material = WireframeMaterial {
103 color: LinearRgba::new(1.0, 0.0, 0.0, 1.0),
104 ..Default::default()
105 };
106
107 assert_eq!(material.color, LinearRgba::new(1.0, 0.0, 0.0, 1.0));
108 }
109
110 #[test]
111 fn test_wireframe_material_line_widths() {
112 // Test default line width
113 let thin = WireframeMaterial {
114 line_width: 1.0,
115 ..Default::default()
116 };
117 assert_eq!(thin.line_width, 1.0);
118
119 // Test thicker line
120 let thick = WireframeMaterial {
121 line_width: 2.5,
122 ..Default::default()
123 };
124 assert_eq!(thick.line_width, 2.5);
125 }
126
127 #[test]
128 fn test_wireframe_material_clone() {
129 let original = WireframeMaterial {
130 color: LinearRgba::new(0.5, 0.5, 1.0, 1.0),
131 line_width: 1.5,
132 };
133
134 let cloned = original.clone();
135 assert_eq!(cloned.color, original.color);
136 assert_eq!(cloned.line_width, original.line_width);
137 }
138
139 #[test]
140 fn test_wireframe_material_common_colors() {
141 // Test common wireframe colors
142 let green = WireframeMaterial {
143 color: LinearRgba::new(0.0, 1.0, 0.0, 1.0),
144 ..Default::default()
145 };
146 assert_eq!(green.color.g, 1.0);
147
148 let cyan = WireframeMaterial {
149 color: LinearRgba::new(0.0, 1.0, 1.0, 1.0),
150 ..Default::default()
151 };
152 assert_eq!(cyan.color.g, 1.0);
153 assert_eq!(cyan.color.b, 1.0);
154
155 let white = WireframeMaterial {
156 color: LinearRgba::new(1.0, 1.0, 1.0, 1.0),
157 ..Default::default()
158 };
159 assert_eq!(white.color.r, 1.0);
160 assert_eq!(white.color.g, 1.0);
161 assert_eq!(white.color.b, 1.0);
162 }
163}