using Kav.Data; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; namespace Kav { public class DiffuseLitSpriteEffect : Effect { EffectParameter ambientColorParam; EffectParameter directionalLightDirectionParam; EffectParameter directionalLightColorParam; EffectParameter uvOffsetAndDimensionsParam; EffectParameter worldParam; EffectParameter worldViewProjectionParam; EffectParameter worldInverseTransposeParam; EffectParameter shaderIndexParam; Texture2D texture; Texture2D normal; bool normalMapEnabled = false; Vector3 ambientColor; Vector3 directionalLightDirection; Vector3 directionalLightColor; Matrix world = Matrix.Identity; Matrix view = Matrix.Identity; Matrix projection = Matrix.Identity; Vector4 uvData; EffectDirtyFlags dirtyFlags = EffectDirtyFlags.All; public bool NormalMapEnabled { get { return normalMapEnabled; } set { if (normalMapEnabled != value) { normalMapEnabled = value; dirtyFlags |= EffectDirtyFlags.PixelShaderIndex; } } } public Matrix World { get { return world; } set { world = value; dirtyFlags |= EffectDirtyFlags.World | EffectDirtyFlags.WorldViewProj; } } public Matrix View { get { return view; } set { view = value; dirtyFlags |= EffectDirtyFlags.WorldViewProj | EffectDirtyFlags.EyePosition; } } public Matrix Projection { get { return projection; } set { projection = value; dirtyFlags |= EffectDirtyFlags.WorldViewProj; } } public int MaxPointLights { get; } = 8; public Vector3 AmbientColor { get { return ambientColor; } set { ambientColor = value; ambientColorParam.SetValue(ambientColor); } } public PointLightCollection PointLights { get; private set; } public Vector3 DirectionalLightDirection { get { return directionalLightDirection; } set { directionalLightDirection = value; directionalLightDirectionParam.SetValue(directionalLightDirection); } } public Vector3 DirectionalLightColor { get { return directionalLightColor; } set { directionalLightColor = value; directionalLightColorParam.SetValue(directionalLightColor); } } public Vector4 UVData { get { return uvData; } set { uvData = value; dirtyFlags |= EffectDirtyFlags.UVData; } } public DiffuseLitSpriteEffect(GraphicsDevice graphicsDevice) : base(graphicsDevice, Resources.DiffuseLitSpriteEffect) { CacheEffectParameters(); PointLights = new PointLightCollection( Parameters["PointLightPositions"], Parameters["PointLightColors"], MaxPointLights ); } protected override void OnApply() { if ((dirtyFlags & EffectDirtyFlags.World) != 0) { worldParam.SetValue(world); Matrix.Invert(ref world, out Matrix worldInverse); Matrix.Transpose(ref worldInverse, out Matrix worldInverseTranspose); worldInverseTransposeParam.SetValue(worldInverseTranspose); dirtyFlags &= ~EffectDirtyFlags.World; } if ((dirtyFlags & EffectDirtyFlags.WorldViewProj) != 0) { Matrix.Multiply(ref world, ref view, out Matrix worldView); Matrix.Multiply(ref worldView, ref projection, out Matrix worldViewProj); worldViewProjectionParam.SetValue(worldViewProj); dirtyFlags &= ~EffectDirtyFlags.WorldViewProj; } if ((dirtyFlags & EffectDirtyFlags.UVData) != 0) { uvOffsetAndDimensionsParam.SetValue(uvData); dirtyFlags &= ~EffectDirtyFlags.UVData; } if ((dirtyFlags & EffectDirtyFlags.PixelShaderIndex) != 0) { int shaderIndex = 0; if (normalMapEnabled) { shaderIndex = 1; } shaderIndexParam.SetValue(shaderIndex); } } private void CacheEffectParameters() { worldParam = Parameters["World"]; worldViewProjectionParam = Parameters["WorldViewProjection"]; worldInverseTransposeParam = Parameters["WorldInverseTranspose"]; ambientColorParam = Parameters["AmbientColor"]; directionalLightDirectionParam = Parameters["DirectionalLightDirection"]; directionalLightColorParam = Parameters["DirectionalLightColor"]; uvOffsetAndDimensionsParam = Parameters["UVOffsetAndDimensions"]; shaderIndexParam = Parameters["ShaderIndex"]; } } }