using System.Collections.Specialized;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace MonoGame.Extended.Graphics.Effects
{
///
/// An that allows objects, within a 3D context, to be represented on a 2D monitor.
///
///
///
public class DefaultEffect : MatrixChainEffect, ITextureEffect
{
///
/// The bitmask for use with indicating wether has
/// changed in the last frame.
///
protected static int DirtyTextureBitMask = BitVector32.CreateMask(UseDefaultProjectionBitMask);
///
/// The bitmask for use with indicating wether the underlying vertex shader and
/// fragment (pixel) shaders have changed to one of the pre-defined shaders in the last frame.
///
protected static int DirtyShaderIndexBitMask = BitVector32.CreateMask(DirtyTextureBitMask);
///
/// The bitmask for use with indicating wether the material color has changed in
/// the last frame.
///
public static int DirtyMaterialColorBitMask = BitVector32.CreateMask(DirtyShaderIndexBitMask);
private Texture2D _texture;
private EffectParameter _textureParameter;
private float _alpha = 1;
private Color _diffuseColor = Color.White;
private EffectParameter _diffuseColorParameter;
private bool _textureEnabled;
private bool _vertexColorEnabled;
///
/// Gets or sets the material .
///
///
/// The material .
///
public Texture2D Texture
{
get { return _texture; }
set
{
_texture = value;
Flags[DirtyTextureBitMask] = true;
}
}
///
/// Gets or sets the material color alpha.
///
///
///
/// The alpha channel uses the premultiplied (associated) representation. This means that the RGB components of a
/// color represent
/// the color of the object of pixel, adjusted for its opacity by multiplication of .
///
///
public float Alpha
{
get { return _alpha; }
set
{
_alpha = value;
Flags[DirtyMaterialColorBitMask] = true;
}
}
///
/// Gets or sets whether texturing is enabled.
///
public bool TextureEnabled
{
get { return _textureEnabled; }
set
{
if (_textureEnabled == value)
return;
_textureEnabled = value;
Flags[DirtyShaderIndexBitMask] = true;
}
}
///
/// Gets or sets whether vertex color is enabled.
///
public bool VertexColorEnabled
{
get { return _vertexColorEnabled; }
set
{
if (_vertexColorEnabled == value)
return;
_vertexColorEnabled = value;
Flags[DirtyShaderIndexBitMask] = true;
}
}
///
/// Initializes a new instance of the class.
///
/// The graphics device.
public DefaultEffect(GraphicsDevice graphicsDevice)
: base(graphicsDevice, EffectResource.DefaultEffect.Bytecode)
{
Initialize();
}
///
/// Initializes a new instance of the class.
///
/// The graphics device.
/// The byte code of the shader program.
public DefaultEffect(GraphicsDevice graphicsDevice, byte[] byteCode)
: base(graphicsDevice, byteCode)
{
Initialize();
}
///
/// Initializes a new instance of the class.
///
/// The clone source.
public DefaultEffect(Effect cloneSource)
: base(cloneSource)
{
Initialize();
}
private void Initialize()
{
Flags[DirtyMaterialColorBitMask] = true;
_textureParameter = Parameters["Texture"];
_diffuseColorParameter = Parameters["DiffuseColor"];
}
///
/// Computes derived parameter values immediately before applying the effect.
///
protected override void OnApply()
{
base.OnApply();
if (Flags[DirtyTextureBitMask])
{
_textureParameter.SetValue(_texture);
Flags[DirtyTextureBitMask] = false;
}
// ReSharper disable once InvertIf
if (Flags[DirtyMaterialColorBitMask])
{
UpdateMaterialColor();
Flags[DirtyMaterialColorBitMask] = false;
}
// ReSharper disable once InvertIf
if (Flags[DirtyShaderIndexBitMask])
{
var shaderIndex = 0;
if (_textureEnabled)
shaderIndex += 1;
if (_vertexColorEnabled)
shaderIndex += 2;
Flags[DirtyShaderIndexBitMask] = false;
CurrentTechnique = Techniques[shaderIndex];
}
}
///
/// Updates the material color parameters associated with this .
///
protected virtual void UpdateMaterialColor()
{
var diffuseColorVector3 = _diffuseColor.ToVector3();
var diffuseColorVector4 = new Vector4()
{
X = diffuseColorVector3.X * Alpha,
Y = diffuseColorVector3.Y * Alpha,
Z = diffuseColorVector3.Z * Alpha,
W = Alpha,
};
_diffuseColorParameter.SetValue(diffuseColorVector4);
}
}
}