pub struct Material { /* private fields */ }
Expand description
Material defines a set of resource bindings for a shader. It could be textures and property groups. Textures contains graphical information (such as diffuse, normal, height, emission, etc. maps), while property groups contains numerical values (matrices, vectors, numbers, etc.).
Each resource binding can be changed in runtime giving you the ability to create animated materials. However, in practice most materials are static, this means that once it created, it won’t be changed anymore.
Please keep in mind that the actual “rules” of drawing an entity are stored in the shader, material is only a storage for specific uses of the shader.
Multiple materials can share the same shader, for example standard shader covers 95% of most common use cases, and it is shared across multiple materials. The only difference are property values, for example you can draw multiple cubes using the same shader, but with different textures.
Material itself can be shared across multiple places as well as the shader. This gives you the ability to render multiple objects with the same material efficiently.
§Performance
It is very important to re-use materials as much as possible, because the amount of materials used per frame significantly correlates with performance. The more unique materials you have per frame, the more work has to be done by the renderer and the video driver to render a frame and the more time the frame will require for rendering, thus lowering your FPS.
§Examples
A material can only be created using a shader instance, every material must have a shader. The shader provides information about its resources. Default values of each property defined in the shader.
§Standard material
Usually standard shader is enough for most cases, Material
even has a Material::standard()
method to create a material with standard shader:
fn create_brick_material(resource_manager: ResourceManager) -> Material {
let mut material = Material::standard();
material.bind(
"diffuseTexture",
resource_manager.request::<Texture>("Brick_DiffuseTexture.jpg")
);
material
}
As you can see it is pretty simple with standard material, all you need is to set values to desired properties and you good to go. All you need to do is to apply the material, for example it could be mesh surface or some other place that supports materials. For the full list of properties of the standard shader see shader module docs.
§Custom material
Custom materials is a bit more complex, you need to get a shader instance using the resource manager (or create a shader in-place by embedding its source code in the binary) and then create the material and populate it with a set of property values.
async fn create_grass_material(resource_manager: ResourceManager) -> Material {
let shader = resource_manager.request::<Shader>("my_grass_shader.ron").await.unwrap();
// Here we assume that the material really has the properties defined below.
let mut material = Material::from_shader(shader);
material.set_property("windDirection", Vector3::new(1.0, 0.0, 0.5));
material
}
As you can see it is slightly more complex that with the standard shader. The main difference here is that we using resource manager to get shader instance, and then we just use the instance to create material instance. Then we populate properties as usual.
Implementations§
Source§impl Material
impl Material
Sourcepub fn standard() -> Self
pub fn standard() -> Self
Creates a new instance of material with the standard shader.
§Example
fn create_brick_material(resource_manager: ResourceManager) -> Material {
let mut material = Material::standard();
material.bind(
"diffuseTexture",
resource_manager.request::<Texture>("Brick_DiffuseTexture.jpg")
);
material
}
Sourcepub fn standard_2d() -> Self
pub fn standard_2d() -> Self
Creates new instance of standard 2D material.
Sourcepub fn standard_particle_system() -> Self
pub fn standard_particle_system() -> Self
Creates new instance of standard 2D material.
Sourcepub fn standard_sprite() -> Self
pub fn standard_sprite() -> Self
Creates new instance of standard sprite material.
Sourcepub fn standard_two_sides() -> Self
pub fn standard_two_sides() -> Self
Creates new instance of standard material that renders both sides of a face.
Sourcepub fn standard_terrain() -> Self
pub fn standard_terrain() -> Self
Creates new instance of standard terrain material.
Sourcepub fn standard_tile() -> Self
pub fn standard_tile() -> Self
Creates new instance of standard tile material.
Sourcepub fn from_shader(shader: ShaderResource) -> Self
pub fn from_shader(shader: ShaderResource) -> Self
Creates a new material instance with given shader. By default, a material does not store any resource bindings. In this case the renderer will use shader default values for rendering. Materials could be considered as container with values that overwrites shader values.
§Example
async fn create_grass_material(resource_manager: ResourceManager) -> Material {
let shader = resource_manager.request::<Shader>("my_grass_shader.ron").await.unwrap();
// Here we assume that the material really has the properties defined below.
let mut material = Material::from_shader(shader);
material.set_property("windDirection", Vector3::new(1.0, 0.0, 0.5));
material
}
Sourcepub async fn from_file<P>(
path: P,
io: &dyn ResourceIo,
resource_manager: ResourceManager,
) -> Result<Self, MaterialError>
pub async fn from_file<P>( path: P, io: &dyn ResourceIo, resource_manager: ResourceManager, ) -> Result<Self, MaterialError>
Loads a material from file.
Sourcepub fn binding_ref(
&self,
name: impl Into<ImmutableString>,
) -> Option<&MaterialResourceBinding>
pub fn binding_ref( &self, name: impl Into<ImmutableString>, ) -> Option<&MaterialResourceBinding>
Searches for a resource binding with the given name and returns immutable reference to it (if any).
§Complexity
O(1)
Sourcepub fn binding_mut(
&mut self,
name: impl Into<ImmutableString>,
) -> Option<&mut MaterialResourceBinding>
pub fn binding_mut( &mut self, name: impl Into<ImmutableString>, ) -> Option<&mut MaterialResourceBinding>
Searches for a resource binding with the given name and returns mutable reference to it, allowing you to modify the value.
§Complexity
O(1)
Sourcepub fn texture_ref(
&self,
name: impl Into<ImmutableString>,
) -> Option<&MaterialTextureBinding>
pub fn texture_ref( &self, name: impl Into<ImmutableString>, ) -> Option<&MaterialTextureBinding>
Searches for a texture with the given name.
Sourcepub fn texture_mut(
&mut self,
name: impl Into<ImmutableString>,
) -> Option<&mut MaterialTextureBinding>
pub fn texture_mut( &mut self, name: impl Into<ImmutableString>, ) -> Option<&mut MaterialTextureBinding>
Searches for a texture with the given name.
Sourcepub fn property_group_ref(
&self,
name: impl Into<ImmutableString>,
) -> Option<&MaterialPropertyGroup>
pub fn property_group_ref( &self, name: impl Into<ImmutableString>, ) -> Option<&MaterialPropertyGroup>
Sourcepub fn property_group_mut(
&mut self,
name: impl Into<ImmutableString>,
) -> Option<&mut MaterialPropertyGroup>
pub fn property_group_mut( &mut self, name: impl Into<ImmutableString>, ) -> Option<&mut MaterialPropertyGroup>
Searches for a property group binding with the given name and returns immutable reference to it (if any).
§Complexity
O(1)
§Examples
use fyrox_impl::core::sstorage::ImmutableString;
let mut material = Material::standard();
let color = material
.property_group_mut("properties")
.unwrap()
.set_property("diffuseColor", Color::RED);
Sourcepub fn try_get_or_insert_property_group(
&mut self,
name: impl Into<ImmutableString>,
) -> &mut MaterialPropertyGroup
pub fn try_get_or_insert_property_group( &mut self, name: impl Into<ImmutableString>, ) -> &mut MaterialPropertyGroup
Tries to find a property group with the given name, creates a new group with the given name if there’s no such group.
Sourcepub fn bind(
&mut self,
name: impl Into<ImmutableString>,
new_value: impl Into<MaterialResourceBinding>,
)
pub fn bind( &mut self, name: impl Into<ImmutableString>, new_value: impl Into<MaterialResourceBinding>, )
Sets new value of the resource binding with given name.
§Type checking
A new value must have the same type as in shader, otherwise an error will be generated at attempt to render something with this material.
§Example
let mut material = Material::standard();
material.set_property("diffuseColor", Color::WHITE);
Sourcepub fn unbind(
&mut self,
name: impl Into<ImmutableString>,
) -> Option<MaterialResourceBinding>
pub fn unbind( &mut self, name: impl Into<ImmutableString>, ) -> Option<MaterialResourceBinding>
Tries to remove a resource bound to the given name.
Sourcepub fn set_property(
&mut self,
name: impl Into<ImmutableString>,
new_value: impl Into<MaterialProperty>,
)
pub fn set_property( &mut self, name: impl Into<ImmutableString>, new_value: impl Into<MaterialProperty>, )
Sets new value of the property with given name to the property group with properties
name.
It is a standard property group, that could be used to store pretty much any values.
§Type checking
A new value must have the same type as in shader, otherwise an error will be generated at attempt to render something with this material.
§Example
let mut material = Material::standard();
material.set_property("diffuseColor", Color::WHITE);
// A full equivalent of the above:
material.try_get_or_insert_property_group("properties")
.set_property("diffuseColor", Color::WHITE);
Sourcepub fn shader(&self) -> &ShaderResource
pub fn shader(&self) -> &ShaderResource
Returns a reference to current shader.
Sourcepub fn bindings(&self) -> &FxHashMap<ImmutableString, MaterialResourceBinding>
pub fn bindings(&self) -> &FxHashMap<ImmutableString, MaterialResourceBinding>
Returns immutable reference to internal property storage.
Sourcepub fn texture(
&self,
name: impl Into<ImmutableString>,
) -> Option<TextureResource>
pub fn texture( &self, name: impl Into<ImmutableString>, ) -> Option<TextureResource>
Tries to find a sampler with the given name and returns its texture (if any).
Trait Implementations§
Source§impl Reflect for Materialwhere
Self: 'static,
ShaderResource: Reflect,
FxHashMap<ImmutableString, MaterialResourceBinding>: Reflect,
impl Reflect for Materialwhere
Self: 'static,
ShaderResource: Reflect,
FxHashMap<ImmutableString, MaterialResourceBinding>: Reflect,
fn source_path() -> &'static str
fn type_name(&self) -> &'static str
fn doc(&self) -> &'static str
Source§fn assembly_name(&self) -> &'static str
fn assembly_name(&self) -> &'static str
#[derive(Reflect)]
) to ensure that this method will return correct assembly
name. In other words - there’s no guarantee, that any implementation other than proc-macro
will return a correct name of the assembly. Alternatively, you can use env!("CARGO_PKG_NAME")
as an implementation.Source§fn type_assembly_name() -> &'static str
fn type_assembly_name() -> &'static str
#[derive(Reflect)]
) to ensure that this method will return correct assembly
name. In other words - there’s no guarantee, that any implementation other than proc-macro
will return a correct name of the assembly. Alternatively, you can use env!("CARGO_PKG_NAME")
as an implementation.fn fields_info(&self, func: &mut dyn FnMut(&[FieldInfo<'_, '_>]))
fn into_any(self: Box<Self>) -> Box<dyn Any>
fn set( &mut self, value: Box<dyn Reflect>, ) -> Result<Box<dyn Reflect>, Box<dyn Reflect>>
fn as_any(&self, func: &mut dyn FnMut(&dyn Any))
fn as_any_mut(&mut self, func: &mut dyn FnMut(&mut dyn Any))
fn as_reflect(&self, func: &mut dyn FnMut(&dyn Reflect))
fn as_reflect_mut(&mut self, func: &mut dyn FnMut(&mut dyn Reflect))
fn fields(&self, func: &mut dyn FnMut(&[&dyn Reflect]))
fn fields_mut(&mut self, func: &mut dyn FnMut(&mut [&mut dyn Reflect]))
fn field(&self, name: &str, func: &mut dyn FnMut(Option<&dyn Reflect>))
fn field_mut( &mut self, name: &str, func: &mut dyn FnMut(Option<&mut dyn Reflect>), )
Source§fn set_field(
&mut self,
field: &str,
value: Box<dyn Reflect>,
func: &mut dyn FnMut(Result<Box<dyn Reflect>, Box<dyn Reflect>>),
)
fn set_field( &mut self, field: &str, value: Box<dyn Reflect>, func: &mut dyn FnMut(Result<Box<dyn Reflect>, Box<dyn Reflect>>), )
#[reflect(setter = ..)]
or falls back to
Reflect::field_mut
fn as_array(&self, func: &mut dyn FnMut(Option<&(dyn ReflectArray + 'static)>))
fn as_array_mut( &mut self, func: &mut dyn FnMut(Option<&mut (dyn ReflectArray + 'static)>), )
fn as_list(&self, func: &mut dyn FnMut(Option<&(dyn ReflectList + 'static)>))
fn as_list_mut( &mut self, func: &mut dyn FnMut(Option<&mut (dyn ReflectList + 'static)>), )
fn as_inheritable_variable( &self, func: &mut dyn FnMut(Option<&(dyn ReflectInheritableVariable + 'static)>), )
fn as_inheritable_variable_mut( &mut self, func: &mut dyn FnMut(Option<&mut (dyn ReflectInheritableVariable + 'static)>), )
fn as_hash_map( &self, func: &mut dyn FnMut(Option<&(dyn ReflectHashMap + 'static)>), )
fn as_hash_map_mut( &mut self, func: &mut dyn FnMut(Option<&mut (dyn ReflectHashMap + 'static)>), )
Source§impl ResourceData for Material
impl ResourceData for Material
Source§fn save(&mut self, path: &Path) -> Result<(), Box<dyn Error>>
fn save(&mut self, path: &Path) -> Result<(), Box<dyn Error>>
Source§fn can_be_saved(&self) -> bool
fn can_be_saved(&self) -> bool
true
if the resource data can be saved to a file, false
- otherwise. Not every
resource type supports saving, for example there might be temporary resource type that is
used only at runtime which does not need saving at all.Auto Trait Implementations§
impl Freeze for Material
impl !RefUnwindSafe for Material
impl Send for Material
impl Sync for Material
impl Unpin for Material
impl !UnwindSafe for Material
Blanket Implementations§
Source§impl<T> AsyncTaskResult for T
impl<T> AsyncTaskResult for T
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait>
(where Trait: Downcast
) to Box<dyn Any>
. Box<dyn Any>
can
then be further downcast
into Box<ConcreteType>
where ConcreteType
implements Trait
.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait>
(where Trait: Downcast
) to Rc<Any>
. Rc<Any>
can then be
further downcast
into Rc<ConcreteType>
where ConcreteType
implements Trait
.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &Any
’s vtable from &Trait
’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &mut Any
’s vtable from &mut Trait
’s.Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
Any
. Could be used to downcast a trait object
to a particular type.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
Any
. Could be used to downcast a trait object
to a particular type.fn into_any(self: Box<T>) -> Box<dyn Any>
Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
Source§impl<T> FieldValue for Twhere
T: 'static,
impl<T> FieldValue for Twhere
T: 'static,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> Pointable for T
impl<T> Pointable for T
Source§impl<R, P> ReadPrimitive<R> for P
impl<R, P> ReadPrimitive<R> for P
Source§fn read_from_little_endian(read: &mut R) -> Result<Self, Error>
fn read_from_little_endian(read: &mut R) -> Result<Self, Error>
ReadEndian::read_from_little_endian()
.Source§impl<T> ReflectBase for Twhere
T: Reflect,
impl<T> ReflectBase for Twhere
T: Reflect,
fn as_any_raw(&self) -> &(dyn Any + 'static)
fn as_any_raw_mut(&mut self) -> &mut (dyn Any + 'static)
Source§impl<T> ResolvePath for Twhere
T: Reflect,
impl<T> ResolvePath for Twhere
T: Reflect,
fn resolve_path<'p>( &self, path: &'p str, func: &mut dyn FnMut(Result<&(dyn Reflect + 'static), ReflectPathError<'p>>), )
fn resolve_path_mut<'p>( &mut self, path: &'p str, func: &mut dyn FnMut(Result<&mut (dyn Reflect + 'static), ReflectPathError<'p>>), )
fn get_resolve_path<'p, T>(
&self,
path: &'p str,
func: &mut dyn FnMut(Result<&T, ReflectPathError<'p>>),
)where
T: Reflect,
fn get_resolve_path_mut<'p, T>(
&mut self,
path: &'p str,
func: &mut dyn FnMut(Result<&mut T, ReflectPathError<'p>>),
)where
T: Reflect,
Source§impl<T> ScriptMessagePayload for T
impl<T> ScriptMessagePayload for T
Source§fn as_any_ref(&self) -> &(dyn Any + 'static)
fn as_any_ref(&self) -> &(dyn Any + 'static)
self
as &dyn Any
Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
self
as &dyn Any
Source§impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
Source§fn to_subset(&self) -> Option<SS>
fn to_subset(&self) -> Option<SS>
self
from the equivalent element of its
superset. Read moreSource§fn is_in_subset(&self) -> bool
fn is_in_subset(&self) -> bool
self
is actually part of its subset T
(and can be converted to it).Source§fn to_subset_unchecked(&self) -> SS
fn to_subset_unchecked(&self) -> SS
self.to_subset
but without any property checks. Always succeeds.Source§fn from_subset(element: &SS) -> SP
fn from_subset(element: &SS) -> SP
self
to the equivalent element of its superset.