1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
/// Material data for a mesh /// /// # Blender /// /// When exporting from Blender we read this data from the first Principled BSDF node in the /// node editor for the material /// /// https://docs.blender.org/manual/en/latest/render/cycles/nodes/types/shaders/principled.html #[derive(Debug, Serialize, Deserialize, PartialEq, Default, Clone)] pub struct PrincipledBSDF { /// [r, g, b] pub(crate) base_color: MaterialInput<[f32; 3], String>, /// roughness pub(crate) roughness: MaterialInput<f32, (String, Channel)>, /// metallic pub(crate) metallic: MaterialInput<f32, (String, Channel)>, /// The filename for the material's normal map pub(crate) normal_map: Option<String>, } /// An input to a material property. /// /// This can either be some uniform value that will get used across all vertices / fragments /// in your shader, or a texture. #[derive(Debug, Serialize, Deserialize, PartialEq, Clone)] pub enum MaterialInput<U, I> { /// Some value that is uniform across all vertices / fragments in your mesh. Uniform(U), /// The name of the texture image (excluding the full path) from an image texture node /// in Blender's material editor. /// /// So a texture stored at /Users/me/hello-world.png /// becomes MaterialInput::Texture("hello-world.png".to_string()) /// /// This means that it is important to have different texture names across all unique textures /// in your application. /// /// ## Note /// /// This is different from the other built in texture nodes, such as brick texture and /// sky texture. We do not currently support these. If these would be useful for you, /// open an issue! /// /// ## Examples /// /// ``` /// // Metalness can be read from the green channel of metal.jpg /// use blender_mesh::{MaterialInput, Channel}; /// let metalness: MaterialInput<f32, (String, Channel)> = /// MaterialInput::ImageTexture((String::from("metal.jpg"), Channel::Green)); /// ``` ImageTexture(I), } /// An individual channel within an image. /// Red, Green, or Blue. #[derive(Debug, Serialize, Deserialize, PartialEq, Copy, Clone)] pub enum Channel { #[serde(rename = "R")] Red, #[serde(rename = "G")] Green, #[serde(rename = "B")] Blue, } impl<U, I> Default for MaterialInput<U, I> where U: Default, { fn default() -> Self { MaterialInput::Uniform(U::default()) } } impl PrincipledBSDF { /// Create a new physically-based material. pub fn new( base_color: MaterialInput<[f32; 3], String>, roughness: MaterialInput<f32, (String, Channel)>, metallic: MaterialInput<f32, (String, Channel)>, normal_map: Option<String>, ) -> Self { PrincipledBSDF { base_color, roughness, metallic, normal_map, } } /// The base_color of the material. /// /// https://docs.blender.org/api/blender2.8/bpy.types.Material.html#bpy.types.Material.diffuse_color #[inline] pub fn base_color(&self) -> &MaterialInput<[f32; 3], String> { &self.base_color } /// The roughness of the material. /// /// https://docs.blender.org/api/blender2.8/bpy.types.Material.html#bpy.types.Material.roughness #[inline] pub fn roughness(&self) -> &MaterialInput<f32, (String, Channel)> { &self.roughness } /// How metallic the material is. Most materials should be 0.0 or 1.0. /// /// https://docs.blender.org/api/blender2.8/bpy.types.Material.html#bpy.types.Material.metallic #[inline] pub fn metallic(&self) -> &MaterialInput<f32, (String, Channel)> { &self.metallic } /// The normal map #[inline] pub fn normal_map(&self) -> Option<&String> { self.normal_map.as_ref() } }