port from perforce
This commit is contained in:
232
aiwaz/Aiwaz.Resources/Shader.cs
Normal file
232
aiwaz/Aiwaz.Resources/Shader.cs
Normal file
@@ -0,0 +1,232 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Aiwaz.Contracts;
|
||||
using Aiwaz.Common;
|
||||
using Aiwaz.Core;
|
||||
using Aiwaz.Resources.Attributes;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
|
||||
namespace Aiwaz.Resources
|
||||
{
|
||||
public class TechniqueNotFoundException : Exception { }
|
||||
public class UnableToLoadShaderException : Exception
|
||||
{
|
||||
public UnableToLoadShaderException(string errors)
|
||||
: base(errors)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[CreationParameters("Load a shader from file")]
|
||||
public class ShaderParams : ICreationParams
|
||||
{
|
||||
[RequiredParameter]
|
||||
public string FileName;
|
||||
public string TechniqueName;
|
||||
|
||||
public ShaderParams()
|
||||
{
|
||||
FileName = null;
|
||||
TechniqueName = null;
|
||||
}
|
||||
}
|
||||
|
||||
[AiwazResource("Shader", "A complex shader to perform individual shading operations when rendering geometry buffers.")]
|
||||
public class Shader : CommandUser, IShader
|
||||
{
|
||||
#region IShader Members
|
||||
|
||||
const byte applyFirstPassCommandType = 0;
|
||||
const byte nextPassCommandType = 1;
|
||||
|
||||
private InternalShader internalShader;
|
||||
private string techniqueName;
|
||||
private byte priority = 0;
|
||||
public bool Changed { get; set; }
|
||||
|
||||
public Shader(ShaderParams parameters)
|
||||
{
|
||||
creationParams = parameters;
|
||||
Console.WriteLine(string.Format("Creating Shader ({0} Technique: {1})..", parameters.FileName, parameters.TechniqueName));
|
||||
|
||||
internalShader = Engine.FindNamedObject(parameters.FileName) as InternalShader;
|
||||
if (internalShader == null)
|
||||
internalShader = new InternalShader(parameters.FileName);
|
||||
|
||||
internalShader.OnChanged += internalShader_OnChanged;
|
||||
Commands.Add(new Command(this, CommandFlags.StartChain | CommandFlags.SubChainStart, applyFirstPassCommandType, 2, this.Priority));
|
||||
Commands.Add(new Command(this, CommandFlags.SubChainEnd, nextPassCommandType, byte.MaxValue, this.Priority));
|
||||
|
||||
this.TechniqueName = creationParams.TechniqueName;
|
||||
}
|
||||
|
||||
void internalShader_OnChanged(object sender, EventArgs e)
|
||||
{
|
||||
this.TechniqueName = creationParams.TechniqueName;
|
||||
Changed = true;
|
||||
}
|
||||
|
||||
public string TechniqueName
|
||||
{
|
||||
get { return techniqueName; }
|
||||
set
|
||||
{
|
||||
techniqueName = value;
|
||||
|
||||
if (string.IsNullOrEmpty(techniqueName))
|
||||
{
|
||||
this.Technique = internalShader.Effect.GetTechniqueByIndex(0);
|
||||
|
||||
if (this.Technique != null)
|
||||
techniqueName = this.Technique.Description.Name;
|
||||
}
|
||||
else
|
||||
this.Technique = internalShader.Effect.GetTechniqueByName(TechniqueName);
|
||||
|
||||
if (this.Technique == null)
|
||||
throw new TechniqueNotFoundException();
|
||||
|
||||
CurrentPass = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public SlimDX.Direct3D10.EffectTechnique Technique { get; protected set; }
|
||||
|
||||
public SlimDX.Direct3D10.Effect Effect { get { return internalShader.Effect; } }
|
||||
|
||||
public byte Priority
|
||||
{
|
||||
get
|
||||
{
|
||||
return priority;
|
||||
}
|
||||
set
|
||||
{
|
||||
priority = value;
|
||||
foreach (var command in Commands)
|
||||
if (command.Type == applyFirstPassCommandType)
|
||||
command.SubPriority = priority;
|
||||
}
|
||||
}
|
||||
|
||||
public int CurrentPass { get; protected set; }
|
||||
|
||||
#endregion
|
||||
|
||||
public override CommandExecuteResult ExecuteCommand(byte commandType, CommandBuffer currentBuffer, int currentPositon)
|
||||
{
|
||||
if (commandType == applyFirstPassCommandType)
|
||||
{
|
||||
CurrentPass = 0;
|
||||
Engine.EngineStates.LastShader = this;
|
||||
}
|
||||
else if (commandType == nextPassCommandType)
|
||||
{
|
||||
if (this.Technique == null)
|
||||
return CommandExecuteResult.None;
|
||||
|
||||
if (CurrentPass >= this.Technique.Description.PassCount)
|
||||
CurrentPass = this.Technique.Description.PassCount;
|
||||
else
|
||||
CurrentPass++;
|
||||
|
||||
if (CurrentPass >= this.Technique.Description.PassCount)
|
||||
return CommandExecuteResult.None;
|
||||
return CommandExecuteResult.RetrySubChainSkipHead;
|
||||
}
|
||||
return CommandExecuteResult.None;
|
||||
}
|
||||
|
||||
#region IDisposable Members
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
Engine.EngineStates.LastShader = null;
|
||||
|
||||
base.Dispose();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private ShaderParams creationParams;
|
||||
public override ICreationParams CreationParams
|
||||
{
|
||||
get { return creationParams; }
|
||||
}
|
||||
|
||||
public override ObservableCollection<IResource> Children
|
||||
{
|
||||
get { return null; }
|
||||
}
|
||||
}
|
||||
|
||||
internal class InternalShader : IDisposable
|
||||
{
|
||||
#region IInternalShader Members
|
||||
|
||||
private string fileName;
|
||||
|
||||
public InternalShader(string fileName)
|
||||
{
|
||||
this.fileName = fileName;
|
||||
Engine.RegisterNamedObject(fileName, this);
|
||||
Engine.RegisterEngineDisposable(this);
|
||||
|
||||
Engine.FileSystem.Attach(fileName, OnShaderChanged);
|
||||
}
|
||||
|
||||
public event EventHandler OnChanged;
|
||||
private void OnShaderChanged(Stream stream)
|
||||
{
|
||||
using (stream)
|
||||
{
|
||||
if (Effect != null)
|
||||
Effect.Dispose();
|
||||
|
||||
string errors;
|
||||
Effect = SlimDX.Direct3D10.Effect.FromStream(Engine.Device, stream, "fx_4_0",
|
||||
#if DEBUG
|
||||
SlimDX.Direct3D10.ShaderFlags.EnableStrictness | SlimDX.Direct3D10.ShaderFlags.Debug,
|
||||
#else
|
||||
SlimDX.Direct3D10.ShaderFlags.EnableStrictness,
|
||||
#endif
|
||||
SlimDX.Direct3D10.EffectFlags.None, null, null, out errors);
|
||||
|
||||
if (!string.IsNullOrEmpty(errors))
|
||||
throw new UnableToLoadShaderException(errors);
|
||||
else if (OnChanged != null)
|
||||
OnChanged(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
~InternalShader()
|
||||
{
|
||||
if (!Engine.Initialized)
|
||||
return;
|
||||
|
||||
Engine.UnregisterNamedObject(fileName);
|
||||
if (Engine.UnregisterEngineDisposable(this))
|
||||
this.Dispose();
|
||||
}
|
||||
|
||||
public SlimDX.Direct3D10.Effect Effect { get; protected set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region IDisposable Members
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (this.Effect != null)
|
||||
this.Effect.Dispose();
|
||||
this.Effect = null;
|
||||
Engine.UnregisterNamedObject(fileName);
|
||||
Engine.UnregisterEngineDisposable(this);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user