324 lines
12 KiB
C#
324 lines
12 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using Aiwaz.Contracts;
|
|
using Aiwaz.Core;
|
|
using Aiwaz.Common;
|
|
using System.Collections.ObjectModel;
|
|
|
|
namespace Aiwaz.Resources
|
|
{
|
|
public class ShaderNotSetException : Exception {}
|
|
public class UnsupportedShaderParameterTypeException : Exception {}
|
|
|
|
[AiwazResource("Shader parameter set", "A set of parameters for one or more shaders.")]
|
|
public class ShaderParameterSet : CommandUser, IShaderParameterSet
|
|
{
|
|
#region IShaderParameterSet Members
|
|
|
|
const byte setShaderParameterCollectionCommandType = 0;
|
|
const byte setFollowingShaderParameterCollectionCommandType = 1;
|
|
|
|
private bool isPreconditionForFollowingShaders;
|
|
private byte basePriority;
|
|
|
|
protected BaseShaderParameterSet baseShaderParameterSet = new BaseShaderParameterSet();
|
|
|
|
public ShaderParameterSet()
|
|
: this(4)
|
|
{
|
|
}
|
|
|
|
protected ShaderParameterSet(byte basePriority)
|
|
{
|
|
this.basePriority = basePriority;
|
|
this.IsPreconditionForFollowingShaders = false;
|
|
}
|
|
|
|
public bool IsPreconditionForFollowingShaders
|
|
{
|
|
get
|
|
{
|
|
return isPreconditionForFollowingShaders;
|
|
}
|
|
|
|
set
|
|
{
|
|
if (Commands.Count > 0 && value == isPreconditionForFollowingShaders)
|
|
return;
|
|
|
|
isPreconditionForFollowingShaders = value;
|
|
|
|
Commands.Clear();
|
|
|
|
if (isPreconditionForFollowingShaders)
|
|
Commands.Add(new Command(this, CommandFlags.EndChain | CommandFlags.FlushChain, setFollowingShaderParameterCollectionCommandType, 0, 0));
|
|
else
|
|
Commands.Add(new Command(this, CommandFlags.None, setShaderParameterCollectionCommandType, basePriority, 0));
|
|
|
|
this.MarkCommandsAsDirty();
|
|
}
|
|
}
|
|
|
|
public void SetParameter(string parameterName, IShaderParameter parameter)
|
|
{
|
|
baseShaderParameterSet.SetShaderParameter(parameterName, parameter);
|
|
}
|
|
|
|
public void SetParameter(string parameterName, ITexture argParameter, ParameterBindType argParamNameType)
|
|
{
|
|
this.SetParameter(parameterName, new Reference(argParameter), argParamNameType);
|
|
}
|
|
|
|
public void SetParameter(string parameterName, float argParameter, ParameterBindType argParamNameType)
|
|
{
|
|
this.SetParameter(parameterName, new Reference(argParameter), argParamNameType);
|
|
}
|
|
|
|
public void SetParameter(string parameterName, SlimDX.Vector3 argParameter, ParameterBindType argParamNameType)
|
|
{
|
|
this.SetParameter(parameterName, new Reference(argParameter), argParamNameType);
|
|
}
|
|
|
|
public void SetParameter(string parameterName, SlimDX.Vector4 argParameter, ParameterBindType argParamNameType)
|
|
{
|
|
this.SetParameter(parameterName, new Reference(argParameter), argParamNameType);
|
|
}
|
|
|
|
public void SetParameter(string parameterName, SlimDX.Matrix argParameter, ParameterBindType argParamNameType)
|
|
{
|
|
this.SetParameter(parameterName, new Reference(argParameter), argParamNameType);
|
|
}
|
|
|
|
public void SetParameter(string parameterName, bool argParameter, ParameterBindType argParamNameType)
|
|
{
|
|
this.SetParameter(parameterName, new Reference(argParameter), argParamNameType);
|
|
}
|
|
|
|
public void SetParameter(string parameterName, Reference argParameter, ParameterBindType argParamNameType)
|
|
{
|
|
baseShaderParameterSet.SetShaderParameter(parameterName, new ShaderParameter(argParamNameType, argParameter));
|
|
}
|
|
|
|
public void RemoveParameter(string name)
|
|
{
|
|
baseShaderParameterSet.RemoveShaderParameter(name);
|
|
}
|
|
|
|
#endregion
|
|
|
|
public override CommandExecuteResult ExecuteCommand(byte commandType, CommandBuffer currentBuffer, int currentPositon)
|
|
{
|
|
if (commandType == setShaderParameterCollectionCommandType)
|
|
{
|
|
if (Engine.EngineStates.LastShader == null)
|
|
throw new ShaderNotSetException();
|
|
baseShaderParameterSet.UseParametersOnShader(Engine.EngineStates.LastShader);
|
|
}
|
|
else if (commandType == setFollowingShaderParameterCollectionCommandType)
|
|
{
|
|
var shaders = currentBuffer.BufferedCommands.Where(c => c.Owner is IShader && c.Type == 0).Select(c => c.Owner as IShader);
|
|
foreach (var shader in shaders)
|
|
baseShaderParameterSet.UseParametersOnShader(shader);
|
|
}
|
|
return CommandExecuteResult.None;
|
|
}
|
|
|
|
#region IDisposable Members
|
|
|
|
public override void Dispose()
|
|
{
|
|
base.Dispose();
|
|
}
|
|
|
|
#endregion
|
|
|
|
public override ICreationParams CreationParams
|
|
{
|
|
get { return null; }
|
|
}
|
|
|
|
public override ObservableCollection<IResource> Children
|
|
{
|
|
get { return null; }
|
|
}
|
|
}
|
|
|
|
public class BaseShaderParameterSet
|
|
{
|
|
Dictionary<string, IShaderParameter> parameterMap = new Dictionary<string, IShaderParameter>();
|
|
Dictionary<WeakReference, List<Pair<IShaderParameter, SlimDX.Direct3D10.EffectVariable>>> shaderToParameterMap = new Dictionary<WeakReference, List<Pair<IShaderParameter, SlimDX.Direct3D10.EffectVariable>>>();
|
|
|
|
public void UseParametersOnShader(IShader shader)
|
|
{
|
|
if (parameterMap.Count == 0)
|
|
return;
|
|
|
|
List<Pair<IShaderParameter, SlimDX.Direct3D10.EffectVariable>> shaderParams = null;
|
|
var searchedShaderPair = shaderToParameterMap.FirstOrDefault(a => a.Key.IsAlive && a.Key.Target == shader);
|
|
if (searchedShaderPair.Key != null)
|
|
shaderParams = searchedShaderPair.Value;
|
|
if (shaderParams == null || shader.Changed)
|
|
{
|
|
shader.Changed = false;
|
|
shaderParams = new List<Pair<IShaderParameter, SlimDX.Direct3D10.EffectVariable>>();
|
|
|
|
// (re)create shader entries
|
|
foreach (var parameter in parameterMap)
|
|
if (parameter.Value != null)
|
|
{
|
|
SlimDX.Direct3D10.EffectVariable effectvar = null;
|
|
if (parameter.Value.ParameterNameType == ParameterBindType.BindByVariable)
|
|
effectvar = shader.Effect.GetVariableByName(parameter.Key);
|
|
else if (parameter.Value.ParameterNameType == ParameterBindType.BindBySemantic)
|
|
effectvar = shader.Effect.GetVariableBySemantic(parameter.Key);
|
|
|
|
if (effectvar != null && effectvar.IsValid)
|
|
shaderParams.Add(new Pair<IShaderParameter, SlimDX.Direct3D10.EffectVariable>(parameter.Value, effectvar));
|
|
}
|
|
|
|
if (shaderParams.Count == 0)
|
|
return;
|
|
|
|
shaderToParameterMap[new WeakReference(shader)] = shaderParams;
|
|
}
|
|
|
|
foreach (var parameter in shaderParams)
|
|
parameter.First.ApplyValue(parameter.Second);
|
|
}
|
|
|
|
private void InitFromShader(IShader shader)
|
|
{
|
|
}
|
|
|
|
public void SetShaderParameter(string name, IShaderParameter parameter)
|
|
{
|
|
this.RemoveShaderParameter(name);
|
|
parameterMap[name] = parameter;
|
|
}
|
|
|
|
public void RemoveShaderParameter(string name)
|
|
{
|
|
shaderToParameterMap.Clear();
|
|
parameterMap.Remove(name);
|
|
}
|
|
|
|
public void RemoveAllShaderParameters()
|
|
{
|
|
parameterMap.Clear();
|
|
shaderToParameterMap.Clear();
|
|
}
|
|
}
|
|
|
|
public class ShaderParameter : IShaderParameter
|
|
{
|
|
private enum ObjectType
|
|
{
|
|
Int,
|
|
IntArray,
|
|
Float,
|
|
FloatArray,
|
|
Bool,
|
|
BoolArray,
|
|
Vector2,
|
|
Vector3,
|
|
Vector4,
|
|
Vector4Array,
|
|
Matrix,
|
|
MatrixArray,
|
|
Texture
|
|
}
|
|
|
|
private Reference valueObject;
|
|
private ObjectType type;
|
|
|
|
public ShaderParameter(ParameterBindType parameterNameType, Reference valueObject)
|
|
{
|
|
this.ParameterNameType = parameterNameType;
|
|
this.valueObject = valueObject;
|
|
|
|
if (valueObject.RawValue is bool)
|
|
this.type = ObjectType.Bool;
|
|
else if (valueObject.RawValue is bool[])
|
|
this.type = ObjectType.BoolArray;
|
|
else if (valueObject.RawValue is int)
|
|
this.type = ObjectType.Int;
|
|
else if (valueObject.RawValue is int[])
|
|
this.type = ObjectType.IntArray;
|
|
else if (valueObject.RawValue is float)
|
|
this.type = ObjectType.Float;
|
|
else if (valueObject.RawValue is float[])
|
|
this.type = ObjectType.FloatArray;
|
|
else if (valueObject.RawValue is SlimDX.Matrix)
|
|
this.type = ObjectType.Matrix;
|
|
else if (valueObject.RawValue is SlimDX.Matrix[])
|
|
this.type = ObjectType.MatrixArray;
|
|
else if (valueObject.RawValue is SlimDX.Vector2)
|
|
this.type = ObjectType.Vector2;
|
|
else if (valueObject.RawValue is SlimDX.Vector3)
|
|
this.type = ObjectType.Vector3;
|
|
else if (valueObject.RawValue is SlimDX.Vector4)
|
|
this.type = ObjectType.Vector4;
|
|
else if (valueObject.RawValue is SlimDX.Vector4[])
|
|
this.type = ObjectType.Vector4Array;
|
|
else if (valueObject.RawValue is ITexture)
|
|
this.type = ObjectType.Texture;
|
|
else
|
|
throw new UnsupportedShaderParameterTypeException();
|
|
}
|
|
|
|
#region IShaderParameter Members
|
|
|
|
public ParameterBindType ParameterNameType { get; protected set; }
|
|
|
|
public void ApplyValue(SlimDX.Direct3D10.EffectVariable variable)
|
|
{
|
|
switch (this.type)
|
|
{
|
|
case ObjectType.Bool:
|
|
variable.AsScalar().Set((bool)valueObject.RawValue);
|
|
break;
|
|
case ObjectType.BoolArray:
|
|
variable.AsScalar().Set((bool[])valueObject.RawValue);
|
|
break;
|
|
case ObjectType.Int:
|
|
variable.AsScalar().Set((int)valueObject.RawValue);
|
|
break;
|
|
case ObjectType.IntArray:
|
|
variable.AsScalar().Set((int[])valueObject.RawValue);
|
|
break;
|
|
case ObjectType.Float:
|
|
variable.AsScalar().Set((float)valueObject.RawValue);
|
|
break;
|
|
case ObjectType.FloatArray:
|
|
variable.AsScalar().Set((float[])valueObject.RawValue);
|
|
break;
|
|
case ObjectType.Vector2:
|
|
variable.AsVector().Set((SlimDX.Vector2)valueObject.RawValue);
|
|
break;
|
|
case ObjectType.Vector3:
|
|
variable.AsVector().Set((SlimDX.Vector3)valueObject.RawValue);
|
|
break;
|
|
case ObjectType.Vector4:
|
|
variable.AsVector().Set((SlimDX.Vector4)valueObject.RawValue);
|
|
break;
|
|
case ObjectType.Vector4Array:
|
|
variable.AsVector().Set((SlimDX.Vector4[])valueObject.RawValue);
|
|
break;
|
|
case ObjectType.Matrix:
|
|
variable.AsMatrix().SetMatrix((SlimDX.Matrix)valueObject.RawValue);
|
|
break;
|
|
case ObjectType.MatrixArray:
|
|
variable.AsMatrix().SetMatrix((SlimDX.Matrix[])valueObject.RawValue);
|
|
break;
|
|
case ObjectType.Texture:
|
|
variable.AsResource().SetResource(((ITexture)valueObject.RawValue).ResourceView);
|
|
break;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|