/ContentSystem/Rendering/MaterialData.cs
C# | 354 lines | 170 code | 28 blank | 156 comment | 12 complexity | 41a328377d4c3b4b53669b9d3550c0c4 MD5 | raw file
Possible License(s): Apache-2.0
- using System;
- using System.IO;
- using Delta.Utilities;
- using Delta.Utilities.Datatypes;
- using Delta.Utilities.Graphics.ShaderFeatures;
- using Delta.Utilities.Helpers;
-
- namespace Delta.ContentSystem.Rendering
- {
- /// <summary>
- /// Material data for loading and saving materials through the content
- /// system as part of a Model or some UI scene. The actual material is
- /// located in the Delta.Rendering module, which uses this class. This
- /// class is currently used to just load the MaterialData directly via
- /// BinaryReader (for embedded materials in models, UI scenes, etc.).
- /// There are no properties or any dynamic loading in this class.
- /// </summary>
- public class MaterialData : Content, ISaveLoadBinary
- {
- #region Constants
- /// <summary>
- /// Version number for this MaterialData. If this goes above 1, we need
- /// to support loading older versions as well. Saving is always going
- /// to be the latest version (this one).
- /// </summary>
- private const int VersionNumber = 1;
-
- /// <summary>
- /// Default material data, do not modify, just used as fallback data.
- /// </summary>
- public static readonly MaterialData Default = new MaterialData();
- #endregion
-
- #region Get (Static)
- /// <summary>
- /// Get and load content based on the content name. This method makes sure
- /// we do not load the same content twice (the constructor is protected).
- /// </summary>
- /// <param name="contentName">Content name we want to load, this is
- /// passed onto the Content System, which will do the actual loading with
- /// help of the Load method in this class.</param>
- /// <returns>The loaded Content object, always unique for the same
- /// name, this helps comparing data.</returns>
- public static MaterialData Get(string contentName)
- {
- return Get<MaterialData>(contentName, ContentType.Material);
- }
- #endregion
-
- #region ShaderName (Public)
- /// <summary>
- /// Link to the shader we want to use with this material as the content
- /// name. If the content cannot be found or does not exist we will output
- /// a warning and use a fallback generated shader with the help of
- /// material data that is already set (e.g. diffuse map and normal map
- /// is set, then generate a fallback shader that can handle that).
- /// </summary>
- public string ShaderName = "";
- #endregion
-
- #region DiffuseMapName (Public)
- /// <summary>
- /// Diffuse map name, almost always used (else meshes look dull). For
- /// sky cube map shaders this is used as the sky cube map texture, which
- /// even can be in HDR mode if the platform supports it. If unused this
- /// string is empty (same goes for all other strings here), but for
- /// shaders that need a diffuse map (most do), this will result in using
- /// the default fallback image for DiffuseMap (see Image.Default)!
- /// </summary>
- public string DiffuseMapName = "";
- #endregion
-
- #region NormalMapName (Public)
- /// <summary>
- /// Normal map name, used for NormalMapping, only used if a normal map
- /// shader is used. Please note this image might have the red and alpha
- /// channel swapped if this is supported and wanted through shaders. This
- /// trick is used to increase quality of compressed normal maps, e.g. DXT1
- /// compresses nicely (1:6 ratio), but can look crappy for detailed normal
- /// maps, so DXT5 is used instead (1:4 ratio still) with R and A swapped.
- /// </summary>
- public string NormalMapName = "";
- #endregion
-
- #region SpecularMapName (Public)
- /// <summary>
- /// Specular map name. Gloss (specular map) mapping effect for a
- /// directional or point light shaders.
- /// </summary>
- public string SpecularMapName = "";
- #endregion
-
- #region HeightMapName (Public)
- /// <summary>
- /// Height map name, this is usually used for parallax effects and
- /// usually a reduced texture because we don't need much precision or
- /// accuracy for parallax effects. See ShaderConstants for ParallaxHeight.
- /// </summary>
- public string HeightMapName = "";
- #endregion
-
- #region DetailMapName (Public)
- /// <summary>
- /// Detail map name, this is almost a diffuse map with more details.
- /// </summary>
- public string DetailMapName = "";
- #endregion
-
- #region ReflectionCubeMapName (Public)
- /// <summary>
- /// Reflection cube map name to make reflections more shiny (uses usually
- /// the same sky cube map as for the sky cube rendering via DiffuseMap)
- /// </summary>
- public string ReflectionCubeMapName = "";
- #endregion
-
- #region LightMapName (Public)
- /// <summary>
- /// Light map name for mesh data with light mapped images baked on top.
- /// Only used if a light map shader is used.
- /// </summary>
- public string LightMapName = "";
- #endregion
-
- #region ShaderLutTexture (Public)
- /// <summary>
- /// Shader helper texture for pre-calculations. Usually used for 1D or 2D
- /// texture lookups for specular power and fresnel power with some extra
- /// pre-calculated data maybe (combined fresnel and specular, already
- /// applied colors, fresnel factors, etc.).
- /// </summary>
- public string ShaderLutTexture = "";
- #endregion
-
- #region ShadowMapTexture (Public)
- /// <summary>
- /// Texture used for performing shadow casting from given object.
- /// </summary>
- public string ShadowMapTexture = "";
- #endregion
-
- #region Ambient (Public)
- /// <summary>
- /// Ambient is usually always 0.15 (the default), many shaders even ignore
- /// this if all we want is light from light sources.
- /// </summary>
- public Color Ambient = ShaderConstants.DefaultAmbientColor;
- #endregion
-
- #region Diffuse (Public)
- /// <summary>
- /// The diffuse color is usually always white (90% by default), but can
- /// be changed from time to time to other colors. Different diffuse colors
- /// need a extra shader pass and cannot be merged, it is much quicker to
- /// let this stay white (the default) and use colored vertices for effects
- /// or UI, which mostly use the same atlas image, but need all kind of
- /// different colors per vertex!
- /// </summary>
- public Color Diffuse = ShaderConstants.DefaultDiffuseColor;
- #endregion
-
- ///// <summary>
- ///// Specular color is usually white and often even unused or optimized
- ///// out in shaders. Rarely used anyway (white looks best for specular).
- ///// </summary>
- //public Color Specular = DefaultSpecularColor;
-
- #region SpecularPower (Public)
- /// <summary>
- /// Specular shininess power, usually defaults to DefaultShininess.
- /// Sometimes not possible on low end pixel shaders, will be optimized
- /// out or put in the vertex shader instead.
- /// </summary>
- public float SpecularPower = ShaderConstants.DefaultSpecularPower;
- #endregion
-
- #region FresnelPower (Public)
- /// <summary>
- /// Fresnel power if the shader for this material does fresnel,
- /// fresnel bias is 0 (or bias in the shader) and the factor is 1.0 too.
- /// </summary>
- public float FresnelPower = ShaderConstants.DefaultFresnelPower;
- #endregion
-
- #region Constructors
- /// <summary>
- /// Create a material from content, just makes sure we use the material
- /// content type, all loading happens in the Load method below.
- /// Use the static Get method to call this.
- /// </summary>
- /// <param name="setMaterialName">
- /// Name for this content object, should not contain any path, project,
- /// scene or any special character! If this is empty or starts with an
- /// > character, we assume this is code generated content
- /// (e.g. ">IntroScene<" or "") and no loading will happen!
- /// </param>
- protected MaterialData(string setMaterialName)
- : base(setMaterialName, ContentType.Material)
- {
- }
-
- /// <summary>
- /// Create a default material data container. All textures are empty,
- /// just the default color values are used. This has also no content name.
- /// Use the .NET 3 style constructor to assign values easily.
- /// </summary>
- public MaterialData()
- : base(EmptyName, ContentType.Material)
- {
- }
- #endregion
-
- #region ISaveLoadBinary Members
- /// <summary>
- /// Load material data from binary data stream.
- /// </summary>
- /// <param name="reader">BinaryReader for reading the data</param>
- public void Load(BinaryReader reader)
- {
- // We currently only support our version, if more versions are added,
- // we need to do different loading code depending on the version here.
- int version = reader.ReadInt32();
- if (version != VersionNumber)
- {
- Log.InvalidVersionWarning("MaterialData", version, VersionNumber);
- return;
- }
- ShaderName = reader.ReadString();
- DiffuseMapName = reader.ReadString();
- DetailMapName = reader.ReadString();
- NormalMapName = reader.ReadString();
- LightMapName = reader.ReadString();
- SpecularMapName = reader.ReadString();
- ReflectionCubeMapName = reader.ReadString();
- Ambient.Load(reader);
- Diffuse.Load(reader);
- //Specular.Load(reader);
- SpecularPower = reader.ReadSingle();
- FresnelPower = reader.ReadSingle();
- ShaderLutTexture = "";
- HeightMapName = "";
- try
- {
- ShaderLutTexture = reader.ReadString();
- // 2011-02-08: Added HeightMap
- HeightMapName = reader.ReadString();
- }
- catch
- {
- }
- }
-
- /// <summary>
- /// Save material data, which consists of a bunch of strings and some
- /// colors plus some additional settings.
- /// </summary>
- /// <param name="writer">BinaryWriter for the stream to write into</param>
- public void Save(BinaryWriter writer)
- {
- #region Validation
- // Validate strings, it is not allowed to save null, but this should
- // not happen anyway!
- if (ShaderName == null)
- {
- ShaderName = "";
- }
- if (DiffuseMapName == null)
- {
- DiffuseMapName = "";
- }
- if (NormalMapName == null)
- {
- NormalMapName = "";
- }
- /*obs
- if (LightMapName == null)
- {
- LightMapName = "";
- }
- */
- if (ReflectionCubeMapName == null)
- {
- ReflectionCubeMapName = "";
- }
- #endregion
-
- writer.Write(VersionNumber);
- writer.Write(ShaderName);
- writer.Write(DiffuseMapName);
- writer.Write(DetailMapName);
- writer.Write(NormalMapName);
- writer.Write(LightMapName);
- writer.Write(SpecularMapName);
- writer.Write(ReflectionCubeMapName);
- Ambient.Save(writer);
- Diffuse.Save(writer);
- //Specular.Save(writer);
- writer.Write(SpecularPower);
- writer.Write(FresnelPower);
- writer.Write(ShaderLutTexture);
- // 2011-02-08: Added HeightMap
- writer.Write(HeightMapName);
- }
- #endregion
-
- #region ToString (Public)
- /// <summary>
- /// To string
- /// </summary>
- public override string ToString()
- {
- return "MaterialData: DiffuseMapName=" + DiffuseMapName +
- ", NormalMapName=" + NormalMapName +
- ", SpecularMapName=" + SpecularMapName +
- //", DetailMapName=" + DetailMapName +
- ", LightMapName=" + LightMapName;
- }
- #endregion
-
- #region Methods (Private)
-
- #region Load
- /// <summary>
- /// Native load method, will just load the xml data.
- /// </summary>
- /// <param name="alreadyLoadedNativeData">
- /// The first instance that has already loaded the required content data
- /// of this content class or just 'null' if there is none loaded yet (or
- /// anymore).
- /// </param>
- protected override void Load(Content alreadyLoadedNativeData)
- {
- try
- {
- if (String.IsNullOrEmpty(RelativeFilePath) == false)
- {
- // Load via the ISaveLoadBinary interface methods below.
- // Cloning should not really happen for shaders anyway.
- FileHelper.Load(RelativeFilePath, this);
- }
- }
- catch (Exception ex)
- {
- Log.Warning("Failed to load material data from file '" +
- RelativeFilePath + "': " + ex);
- FailedToLoad = true;
- }
- }
- #endregion
-
- #endregion
- }
- }
-