three_d/renderer/
material.rs1macro_rules! impl_material_body {
9 ($inner:ident) => {
10 fn fragment_shader_source(&self, lights: &[&dyn Light]) -> String {
11 self.$inner().fragment_shader_source(lights)
12 }
13 fn use_uniforms(&self, program: &Program, viewer: &dyn Viewer, lights: &[&dyn Light]) {
14 self.$inner().use_uniforms(program, viewer, lights)
15 }
16 fn render_states(&self) -> RenderStates {
17 self.$inner().render_states()
18 }
19 fn material_type(&self) -> MaterialType {
20 self.$inner().material_type()
21 }
22 fn id(&self) -> EffectMaterialId {
23 self.$inner().id()
24 }
25 };
26}
27
28use crate::renderer::*;
29
30pub use three_d_asset::material::{
31 GeometryFunction, LightingModel, NormalDistributionFunction, PbrMaterial as CpuMaterial,
32};
33
34mod color_material;
35#[doc(inline)]
36pub use color_material::*;
37
38mod depth_material;
39#[doc(inline)]
40pub use depth_material::*;
41
42mod intersection_material;
43#[doc(inline)]
44pub use intersection_material::*;
45
46mod normal_material;
47#[doc(inline)]
48pub use normal_material::*;
49
50mod orm_material;
51#[doc(inline)]
52pub use orm_material::*;
53
54mod position_material;
55#[doc(inline)]
56pub use position_material::*;
57
58mod uv_material;
59#[doc(inline)]
60pub use uv_material::*;
61
62mod physical_material;
63#[doc(inline)]
64pub use physical_material::*;
65
66mod deferred_physical_material;
67#[doc(inline)]
68pub use deferred_physical_material::*;
69
70mod skybox_material;
71#[doc(inline)]
72pub(in crate::renderer) use skybox_material::*;
73
74mod wireframe_material;
75#[doc(inline)]
76pub(in crate::renderer) use wireframe_material::*;
77
78mod isosurface_material;
79#[doc(inline)]
80pub use isosurface_material::*;
81
82use std::{ops::Deref, sync::Arc};
83
84#[derive(Clone)]
88pub struct Texture2DRef {
89 pub texture: Arc<Texture2D>,
91 pub transformation: Mat3,
94}
95
96impl Texture2DRef {
97 pub fn from_cpu_texture(context: &Context, cpu_texture: &CpuTexture) -> Self {
99 Self {
100 texture: Arc::new(Texture2D::new(context, cpu_texture)),
101 transformation: Mat3::identity(),
102 }
103 }
104
105 pub fn from_texture(texture: Texture2D) -> Self {
107 Self {
108 texture: Arc::new(texture),
109 transformation: Mat3::identity(),
110 }
111 }
112}
113
114impl std::ops::Deref for Texture2DRef {
115 type Target = Texture2D;
116 fn deref(&self) -> &Self::Target {
117 &self.texture
118 }
119}
120
121impl std::convert::From<Texture2D> for Texture2DRef {
122 fn from(texture: Texture2D) -> Self {
123 Self::from_texture(texture)
124 }
125}
126
127impl std::convert::From<Arc<Texture2D>> for Texture2DRef {
128 fn from(texture: Arc<Texture2D>) -> Self {
129 Self {
130 texture,
131 transformation: Mat3::identity(),
132 }
133 }
134}
135
136#[derive(Clone, Copy, PartialEq, PartialOrd, Ord, Eq, Debug)]
141pub enum MaterialType {
142 Opaque,
144 Transparent,
146 Deferred,
148}
149
150pub trait Material {
165 fn fragment_shader_source(&self, lights: &[&dyn Light]) -> String;
169
170 fn id(&self) -> EffectMaterialId;
177
178 fn use_uniforms(&self, program: &Program, viewer: &dyn Viewer, lights: &[&dyn Light]);
182
183 fn render_states(&self) -> RenderStates;
187
188 fn material_type(&self) -> MaterialType;
192}
193
194pub trait FromCpuMaterial: std::marker::Sized {
198 fn from_cpu_material(context: &Context, cpu_material: &CpuMaterial) -> Self;
202}
203
204pub trait FromCpuVoxelGrid: std::marker::Sized {
208 fn from_cpu_voxel_grid(context: &Context, cpu_voxel_grid: &CpuVoxelGrid) -> Self;
212}
213
214impl<T: Material + ?Sized> Material for &T {
215 impl_material_body!(deref);
216}
217
218impl<T: Material + ?Sized> Material for &mut T {
219 impl_material_body!(deref);
220}
221
222impl<T: Material> Material for Box<T> {
223 impl_material_body!(as_ref);
224}
225
226impl<T: Material> Material for std::rc::Rc<T> {
227 impl_material_body!(as_ref);
228}
229
230impl<T: Material> Material for std::sync::Arc<T> {
231 impl_material_body!(as_ref);
232}
233
234impl<T: Material> Material for std::cell::RefCell<T> {
235 impl_material_body!(borrow);
236}
237
238impl<T: Material> Material for std::sync::RwLock<T> {
239 fn fragment_shader_source(&self, lights: &[&dyn Light]) -> String {
240 self.read().unwrap().fragment_shader_source(lights)
241 }
242 fn use_uniforms(&self, program: &Program, viewer: &dyn Viewer, lights: &[&dyn Light]) {
243 self.read().unwrap().use_uniforms(program, viewer, lights)
244 }
245 fn render_states(&self) -> RenderStates {
246 self.read().unwrap().render_states()
247 }
248 fn material_type(&self) -> MaterialType {
249 self.read().unwrap().material_type()
250 }
251 fn id(&self) -> EffectMaterialId {
252 self.read().unwrap().id()
253 }
254}
255
256fn is_transparent(cpu_material: &CpuMaterial) -> bool {
257 cpu_material.albedo.a != 255
258 || cpu_material
259 .albedo_texture
260 .as_ref()
261 .map(|t| match &t.data {
262 TextureData::RgbaU8(data) => data.iter().any(|d| d[3] != 255),
263 TextureData::RgbaF16(data) => data.iter().any(|d| d[3] < f16::from_f32(0.99)),
264 TextureData::RgbaF32(data) => data.iter().any(|d| d[3] < 0.99),
265 _ => false,
266 })
267 .unwrap_or(false)
268}