three_d/renderer/material/
color_material.rs1use crate::core::*;
2use crate::renderer::*;
3
4#[derive(Clone, Default)]
9pub struct ColorMaterial {
10 pub color: Srgba,
12 pub texture: Option<Texture2DRef>,
15 pub render_states: RenderStates,
17 pub is_transparent: bool,
21}
22
23impl ColorMaterial {
24 pub fn new(context: &Context, cpu_material: &CpuMaterial) -> Self {
30 if super::is_transparent(cpu_material) {
31 Self::new_transparent(context, cpu_material)
32 } else {
33 Self::new_opaque(context, cpu_material)
34 }
35 }
36
37 pub fn new_opaque(context: &Context, cpu_material: &CpuMaterial) -> Self {
39 let texture =
40 cpu_material
41 .albedo_texture
42 .as_ref()
43 .map(|cpu_texture| match &cpu_texture.data {
44 TextureData::RgbU8(_) | TextureData::RgbaU8(_) => {
45 let mut cpu_texture = cpu_texture.clone();
46 cpu_texture.data.to_linear_srgb();
47 Texture2DRef::from_cpu_texture(context, &cpu_texture)
48 }
49 _ => Texture2DRef::from_cpu_texture(context, cpu_texture),
50 });
51 Self {
52 color: cpu_material.albedo,
53 texture,
54 is_transparent: false,
55 render_states: RenderStates::default(),
56 }
57 }
58
59 pub fn new_transparent(context: &Context, cpu_material: &CpuMaterial) -> Self {
61 let texture =
62 cpu_material
63 .albedo_texture
64 .as_ref()
65 .map(|cpu_texture| match &cpu_texture.data {
66 TextureData::RgbU8(_) | TextureData::RgbaU8(_) => {
67 let mut cpu_texture = cpu_texture.clone();
68 cpu_texture.data.to_linear_srgb();
69 Texture2DRef::from_cpu_texture(context, &cpu_texture)
70 }
71 _ => Texture2DRef::from_cpu_texture(context, cpu_texture),
72 });
73 Self {
74 color: cpu_material.albedo,
75 texture,
76 is_transparent: true,
77 render_states: RenderStates {
78 write_mask: WriteMask::COLOR,
79 blend: Blend::TRANSPARENCY,
80 ..Default::default()
81 },
82 }
83 }
84
85 pub fn from_physical_material(physical_material: &PhysicalMaterial) -> Self {
87 Self {
88 color: physical_material.albedo,
89 texture: physical_material.albedo_texture.clone(),
90 render_states: physical_material.render_states,
91 is_transparent: physical_material.is_transparent,
92 }
93 }
94}
95
96impl FromCpuMaterial for ColorMaterial {
97 fn from_cpu_material(context: &Context, cpu_material: &CpuMaterial) -> Self {
98 Self::new(context, cpu_material)
99 }
100}
101
102impl Material for ColorMaterial {
103 fn id(&self) -> EffectMaterialId {
104 EffectMaterialId::ColorMaterial(self.texture.is_some())
105 }
106
107 fn fragment_shader_source(&self, _lights: &[&dyn Light]) -> String {
108 let mut shader = String::new();
109 if self.texture.is_some() {
110 shader.push_str("#define USE_TEXTURE\nin vec2 uvs;\n");
111 }
112 shader.push_str(include_str!("../../core/shared.frag"));
113 shader.push_str(ColorMapping::fragment_shader_source());
114 shader.push_str(include_str!("shaders/color_material.frag"));
115 shader
116 }
117
118 fn use_uniforms(&self, program: &Program, viewer: &dyn Viewer, _lights: &[&dyn Light]) {
119 viewer.color_mapping().use_uniforms(program);
120 program.use_uniform("surfaceColor", self.color.to_linear_srgb());
121 if let Some(ref tex) = self.texture {
122 program.use_uniform("textureTransformation", tex.transformation);
123 program.use_texture("tex", tex);
124 }
125 }
126 fn render_states(&self) -> RenderStates {
127 self.render_states
128 }
129 fn material_type(&self) -> MaterialType {
130 if self.is_transparent {
131 MaterialType::Transparent
132 } else {
133 MaterialType::Opaque
134 }
135 }
136}