using System; using ANX.Framework.NonXNA; using ANX.Framework.NonXNA.Development; // This file is part of the ANX.Framework created by the // "ANX.Framework developer group" and released under the Ms-PL license. // For details see: http://anxframework.codeplex.com/license namespace ANX.Framework.Graphics { [PercentageComplete(100)] [TestState(TestStateAttribute.TestState.Untested)] [Developer("AstrorEnales")] public class AlphaTestEffect : Effect, IEffectMatrices, IEffectFog, IGraphicsResource { #region Private private Matrix world; private Matrix view; private Matrix projection; private Vector3 fogColor; private Vector3 diffuseColor; private bool isVertexColorEnabled; private bool isFogEnabled; private CompareFunction alphaFunction; #endregion #region Public public float Alpha { get; set; } public float FogEnd { get; set; } public float FogStart { get; set; } public Texture2D Texture { get; set; } public int ReferenceAlpha { get; set; } public CompareFunction AlphaFunction { get { return alphaFunction; } set { alphaFunction = value; SelectTechnique(); } } public bool FogEnabled { get { return isFogEnabled; } set { isFogEnabled = value; SelectTechnique(); } } public bool VertexColorEnabled { get { return isVertexColorEnabled; } set { isVertexColorEnabled = value; SelectTechnique(); } } public Vector3 DiffuseColor { get { return diffuseColor; } set { diffuseColor = value; } } public Vector3 FogColor { get { return fogColor; } set { fogColor = value; } } public Matrix Projection { get { return projection; } set { projection = value; } } public Matrix View { get { return view; } set { view = value; } } public Matrix World { get { return world; } set { world = value; } } #endregion #region Constructor public AlphaTestEffect(GraphicsDevice device) : base(device, GetByteCode(), GetSourceLanguage()) { Alpha = 1f; isFogEnabled = false; isVertexColorEnabled = false; FogEnd = 1f; alphaFunction = CompareFunction.Greater; world = Matrix.Identity; view = Matrix.Identity; projection = Matrix.Identity; diffuseColor = Vector3.One; SelectTechnique(); } protected AlphaTestEffect(AlphaTestEffect cloneSource) : base(cloneSource) { world = cloneSource.world; view = cloneSource.view; projection = cloneSource.projection; fogColor = cloneSource.fogColor; diffuseColor = cloneSource.diffuseColor; isFogEnabled = cloneSource.isFogEnabled; isVertexColorEnabled = cloneSource.isVertexColorEnabled; alphaFunction = cloneSource.alphaFunction; Alpha = cloneSource.Alpha; FogEnd = cloneSource.FogEnd; FogStart = cloneSource.FogStart; ReferenceAlpha = cloneSource.ReferenceAlpha; Texture = cloneSource.Texture; SelectTechnique(); } #endregion #region GetByteCode private static byte[] GetByteCode() { var creator = AddInSystemFactory.Instance.GetDefaultCreator(); return creator.GetShaderByteCode(PreDefinedShader.AlphaTestEffect); } #endregion #region GetSourceLanguage private static EffectSourceLanguage GetSourceLanguage() { var creator = AddInSystemFactory.Instance.GetDefaultCreator(); return creator.GetStockShaderSourceLanguage; } #endregion #region Clone public override Effect Clone() { return new AlphaTestEffect(this); } #endregion #region PreBindSetParameters internal override void PreBindSetParameters() { Matrix worldView; Matrix.Multiply(ref world, ref view, out worldView); Matrix wvp; Matrix.Multiply(ref worldView, ref projection, out wvp); Parameters["WorldViewProj"].SetValue(wvp); Parameters["DiffuseColor"].SetValue(new Vector4(diffuseColor * Alpha, Alpha)); Parameters["FogColor"].SetValue(fogColor); if (Texture != null) Parameters["Texture"].SetValue(Texture); SetAlphaTestValue(); if (isFogEnabled) SetFogVector(ref worldView); else Parameters["FogVector"].SetValue(Vector4.Zero); } #endregion #region SetAlphaTestValue private void SetAlphaTestValue() { Vector4 alphaTestValue = Vector4.Zero; float num = (float)ReferenceAlpha / 255f; switch (alphaFunction) { case CompareFunction.Never: alphaTestValue.Z = -1f; alphaTestValue.W = -1f; break; case CompareFunction.Less: alphaTestValue.X = num - 0.00196078443f; alphaTestValue.Z = 1f; alphaTestValue.W = -1f; break; case CompareFunction.LessEqual: alphaTestValue.X = num + 0.00196078443f; alphaTestValue.Z = 1f; alphaTestValue.W = -1f; break; case CompareFunction.Equal: alphaTestValue.X = num; alphaTestValue.Y = 0.00196078443f; alphaTestValue.Z = 1f; alphaTestValue.W = -1f; break; case CompareFunction.GreaterEqual: alphaTestValue.X = num - 0.00196078443f; alphaTestValue.Z = -1f; alphaTestValue.W = 1f; break; case CompareFunction.Greater: alphaTestValue.X = num + 0.00196078443f; alphaTestValue.Z = -1f; alphaTestValue.W = 1f; break; case CompareFunction.NotEqual: alphaTestValue.X = num; alphaTestValue.Y = 0.00196078443f; alphaTestValue.Z = -1f; alphaTestValue.W = 1f; break; default: alphaTestValue.Z = 1f; alphaTestValue.W = 1f; break; } Parameters["AlphaTest"].SetValue(alphaTestValue); } #endregion #region SelectTechnique private void SelectTechnique() { string extra = (alphaFunction == CompareFunction.Equal || alphaFunction == CompareFunction.NotEqual) ? "EqNe" : "LtGt"; if (isVertexColorEnabled) { if (isFogEnabled) CurrentTechnique = Techniques["AlphaTestVertexColor" + extra]; if (isFogEnabled == false) CurrentTechnique = Techniques["AlphaTestVertexColorNoFog" + extra]; } else { if (isFogEnabled) CurrentTechnique = Techniques["AlphaTest" + extra]; if (isFogEnabled == false) CurrentTechnique = Techniques["AlphaTestNoFog" + extra]; } } #endregion #region SetFogVector private void SetFogVector(ref Matrix worldView) { if (FogStart == FogEnd) { Parameters["FogVector"].SetValue(new Vector4(0f, 0f, 0f, 1f)); return; } float fogFactor = 1f / (FogStart - FogEnd); Vector4 value; value.X = worldView.M13 * fogFactor; value.Y = worldView.M23 * fogFactor; value.Z = worldView.M33 * fogFactor; value.W = (worldView.M43 + FogStart) * fogFactor; Parameters["FogVector"].SetValue(value); } #endregion } }