three_d/renderer/material/
orm_material.rs1use crate::core::*;
2use crate::renderer::*;
3
4#[derive(Clone)]
9pub struct ORMMaterial {
10 pub metallic: f32,
12 pub roughness: f32,
14 pub metallic_roughness_texture: Option<Texture2DRef>,
17 pub occlusion_strength: f32,
19 pub occlusion_texture: Option<Texture2DRef>,
22 pub render_states: RenderStates,
24}
25
26impl ORMMaterial {
27 pub fn new(context: &Context, cpu_material: &CpuMaterial) -> Self {
29 let metallic_roughness_texture =
30 if let Some(ref cpu_texture) = cpu_material.occlusion_metallic_roughness_texture {
31 Some(Texture2DRef::from_cpu_texture(context, cpu_texture))
32 } else {
33 cpu_material
34 .metallic_roughness_texture
35 .as_ref()
36 .map(|cpu_texture| Texture2DRef::from_cpu_texture(context, cpu_texture))
37 };
38 let occlusion_texture = if cpu_material.occlusion_metallic_roughness_texture.is_some() {
39 metallic_roughness_texture.clone()
40 } else {
41 cpu_material
42 .occlusion_texture
43 .as_ref()
44 .map(|cpu_texture| Texture2DRef::from_cpu_texture(context, cpu_texture))
45 };
46 Self {
47 metallic: cpu_material.metallic,
48 roughness: cpu_material.roughness,
49 metallic_roughness_texture,
50 occlusion_texture,
51 occlusion_strength: cpu_material.occlusion_strength,
52 render_states: RenderStates::default(),
53 }
54 }
55
56 pub fn from_physical_material(physical_material: &PhysicalMaterial) -> Self {
58 Self {
59 metallic: physical_material.metallic,
60 roughness: physical_material.roughness,
61 metallic_roughness_texture: physical_material.metallic_roughness_texture.clone(),
62 occlusion_strength: physical_material.occlusion_strength,
63 occlusion_texture: physical_material.occlusion_texture.clone(),
64 render_states: RenderStates {
65 write_mask: WriteMask::default(),
66 blend: Blend::Disabled,
67 ..physical_material.render_states
68 },
69 }
70 }
71}
72
73impl FromCpuMaterial for ORMMaterial {
74 fn from_cpu_material(context: &Context, cpu_material: &CpuMaterial) -> Self {
75 Self::new(context, cpu_material)
76 }
77}
78
79impl Material for ORMMaterial {
80 fn id(&self) -> EffectMaterialId {
81 EffectMaterialId::ORMMaterial(
82 self.metallic_roughness_texture.is_some(),
83 self.occlusion_texture.is_some(),
84 )
85 }
86
87 fn fragment_shader_source(&self, _lights: &[&dyn Light]) -> String {
88 let mut source = String::new();
89 if self.metallic_roughness_texture.is_some() || self.occlusion_texture.is_some() {
90 source.push_str("in vec2 uvs;\n");
91 if self.metallic_roughness_texture.is_some() {
92 source.push_str("#define USE_METALLIC_ROUGHNESS_TEXTURE;\n");
93 }
94 if self.occlusion_texture.is_some() {
95 source.push_str("#define USE_OCCLUSION_TEXTURE;\n");
96 }
97 }
98 source.push_str(include_str!("shaders/orm_material.frag"));
99 source
100 }
101
102 fn use_uniforms(&self, program: &Program, _viewer: &dyn Viewer, _lights: &[&dyn Light]) {
103 program.use_uniform("metallic", self.metallic);
104 program.use_uniform("roughness", self.roughness);
105 if let Some(ref texture) = self.metallic_roughness_texture {
106 program.use_texture("metallicRoughnessTexture", texture);
107 program.use_uniform("metallicRoughnessTexTransform", texture.transformation);
108 }
109 if let Some(ref texture) = self.occlusion_texture {
110 program.use_uniform("occlusionStrength", self.occlusion_strength);
111 program.use_texture("occlusionTexture", texture);
112 program.use_uniform("occlusionTexTransform", texture.transformation);
113 }
114 }
115
116 fn render_states(&self) -> RenderStates {
117 self.render_states
118 }
119
120 fn material_type(&self) -> MaterialType {
121 MaterialType::Opaque
122 }
123}
124
125impl Default for ORMMaterial {
126 fn default() -> Self {
127 Self {
128 metallic: 0.0,
129 roughness: 1.0,
130 metallic_roughness_texture: None,
131 occlusion_texture: None,
132 occlusion_strength: 1.0,
133 render_states: RenderStates::default(),
134 }
135 }
136}