Files
bluflame/aiwaz/Backup/Aiwaz.Resources/ShaderParameterSet.cs
2026-04-18 22:31:51 +02:00

319 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)
{
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);
}
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
}
}