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 isosurface_material;
75#[doc(inline)]
76pub use isosurface_material::*;
77
78use std::{ops::Deref, sync::Arc};
79
80#[derive(Clone)]
84pub struct Texture2DRef {
85 pub texture: Arc<Texture2D>,
87 pub transformation: Mat3,
90}
91
92impl Texture2DRef {
93 pub fn from_cpu_texture(context: &Context, cpu_texture: &CpuTexture) -> Self {
95 Self {
96 texture: Arc::new(Texture2D::new(context, cpu_texture)),
97 transformation: Mat3::identity(),
98 }
99 }
100
101 pub fn from_texture(texture: Texture2D) -> Self {
103 Self {
104 texture: Arc::new(texture),
105 transformation: Mat3::identity(),
106 }
107 }
108}
109
110impl std::ops::Deref for Texture2DRef {
111 type Target = Texture2D;
112 fn deref(&self) -> &Self::Target {
113 &self.texture
114 }
115}
116
117impl std::convert::From<Texture2D> for Texture2DRef {
118 fn from(texture: Texture2D) -> Self {
119 Self::from_texture(texture)
120 }
121}
122
123impl std::convert::From<Arc<Texture2D>> for Texture2DRef {
124 fn from(texture: Arc<Texture2D>) -> Self {
125 Self {
126 texture,
127 transformation: Mat3::identity(),
128 }
129 }
130}
131
132#[derive(Clone, Copy, PartialEq, PartialOrd, Ord, Eq, Debug)]
137pub enum MaterialType {
138 Opaque,
140 Transparent,
142 Deferred,
144}
145
146pub trait Material {
161 fn fragment_shader_source(&self, lights: &[&dyn Light]) -> String;
165
166 fn id(&self) -> EffectMaterialId;
173
174 fn use_uniforms(&self, program: &Program, viewer: &dyn Viewer, lights: &[&dyn Light]);
178
179 fn render_states(&self) -> RenderStates;
183
184 fn material_type(&self) -> MaterialType;
188}
189
190pub trait FromCpuMaterial: std::marker::Sized {
194 fn from_cpu_material(context: &Context, cpu_material: &CpuMaterial) -> Self;
198}
199
200pub trait FromCpuVoxelGrid: std::marker::Sized {
204 fn from_cpu_voxel_grid(context: &Context, cpu_voxel_grid: &CpuVoxelGrid) -> Self;
208}
209
210impl<T: Material + ?Sized> Material for &T {
211 impl_material_body!(deref);
212}
213
214impl<T: Material + ?Sized> Material for &mut T {
215 impl_material_body!(deref);
216}
217
218impl<T: Material> Material for Box<T> {
219 impl_material_body!(as_ref);
220}
221
222impl<T: Material> Material for std::rc::Rc<T> {
223 impl_material_body!(as_ref);
224}
225
226impl<T: Material> Material for std::sync::Arc<T> {
227 impl_material_body!(as_ref);
228}
229
230impl<T: Material> Material for std::cell::RefCell<T> {
231 impl_material_body!(borrow);
232}
233
234impl<T: Material> Material for std::sync::RwLock<T> {
235 fn fragment_shader_source(&self, lights: &[&dyn Light]) -> String {
236 self.read().unwrap().fragment_shader_source(lights)
237 }
238 fn use_uniforms(&self, program: &Program, viewer: &dyn Viewer, lights: &[&dyn Light]) {
239 self.read().unwrap().use_uniforms(program, viewer, lights)
240 }
241 fn render_states(&self) -> RenderStates {
242 self.read().unwrap().render_states()
243 }
244 fn material_type(&self) -> MaterialType {
245 self.read().unwrap().material_type()
246 }
247 fn id(&self) -> EffectMaterialId {
248 self.read().unwrap().id()
249 }
250}
251
252fn is_transparent(cpu_material: &CpuMaterial) -> bool {
253 cpu_material.albedo.a != 255
254 || cpu_material
255 .albedo_texture
256 .as_ref()
257 .map(|t| match &t.data {
258 TextureData::RgbaU8(data) => data.iter().any(|d| d[3] != 255),
259 TextureData::RgbaF16(data) => data.iter().any(|d| d[3] < f16::from_f32(0.99)),
260 TextureData::RgbaF32(data) => data.iter().any(|d| d[3] < 0.99),
261 _ => false,
262 })
263 .unwrap_or(false)
264}