EffectHandles made easy, using a hashtable-based utility classBy Rim van Wersch, January 26 2006 |
Using effect handles to set parameters on your effects can drastically improve the performance of your application. This snippet provides a 'proxy' class that allows you to use these effect handles while you can still reference parameters with their string name. You can find the code for this class in the block below or you can download it from the links at the bottom of the page.
using System; using System.Collections; using Microsoft.DirectX; using Microsoft.DirectX.Direct3D; using System.Runtime.InteropServices; namespace Clouds.Util { ? ?///? ?/// The EffectHandleProxy caches effecthandles to efficiently set ? ?/// effect parameters while using the name strings in the main app. ? ?/// ? ?public class EffectHandleProxy ? ?{ ? ? ? ?private Hashtable effectHandles = new Hashtable(); ? ? ? ?private Effect effect; ? ? ? ?public EffectHandleProxy() ? ? ? ?{ ? ? ? ? ? ? ? ? ? ?} ? ? ? ?public void Reset( Effect effect ) ? ? ? ?{ ? ? ? ? ? ?this.effect = effect; ? ? ? ? ? ?effectHandles.Clear(); ? ? ? ?} ? ? ? ?public void SetValue( string name, BaseTexture val ) ? ? ? ?{ ? ? ? ? ? ?effect.SetValue( GetHandle( name ), val ); ? ? ? ?} ? ? ? ?public void SetValue( string name, bool val ) ? ? ? ?{ ? ? ? ? ? ?effect.SetValue( GetHandle( name ), val ); ? ? ? ?} ? ? ? ?public void SetValue( string name, bool[] val ) ? ? ? ?{ ? ? ? ? ? ?effect.SetValue( GetHandle( name ), val ); ? ? ? ?} ? ? ? ?public void SetValue( string name, ColorValue val ) ? ? ? ?{ ? ? ? ? ? ?effect.SetValue( GetHandle( name ), val ); ? ? ? ?} ? ? ? ?public void SetValue( string name, ColorValue[] val ) ? ? ? ?{ ? ? ? ? ? ?effect.SetValue( GetHandle( name ), val ); ? ? ? ?} ? ? ? ?public void SetValue( string name, GraphicsStream val ) ? ? ? ?{ ? ? ? ? ? ?effect.SetValue( GetHandle( name ), val ); ? ? ? ?} ? ? ? ?public void SetValue( string name, int val ) ? ? ? ?{ ? ? ? ? ? ?effect.SetValue( GetHandle( name ), val ); ? ? ? ?} ? ? ? ?public void SetValue( string name, int[] val ) ? ? ? ?{ ? ? ? ? ? ?effect.SetValue( GetHandle( name ), val ); ? ? ? ?} ? ? ? ?public void SetValue( string name, Matrix val ) ? ? ? ?{ ? ? ? ? ? ?effect.SetValue( GetHandle( name ), val ); ? ? ? ?} ? ? ? ?public void SetValue( string name, Matrix[] val ) ? ? ? ?{ ? ? ? ? ? ?effect.SetValue( GetHandle( name ), val ); ? ? ? ?} ? ? ? ?public void SetValue( string name, float val ) ? ? ? ?{ ? ? ? ? ? ?effect.SetValue( GetHandle( name ), val ); ? ? ? ?} ? ? ? ?public void SetValue( string name, float[] val ) ? ? ? ?{ ? ? ? ? ? ?effect.SetValue( GetHandle( name ), val ); ? ? ? ?} ? ? ? ?public void SetValue( string name, string val ) ? ? ? ?{ ? ? ? ? ? ?effect.SetValue( GetHandle( name ), val ); ? ? ? ?} ? ? ? ?public void SetValue( string name, Vector4 val ) ? ? ? ?{ ? ? ? ? ? ?effect.SetValue( GetHandle( name ), val ); ? ? ? ?} ? ? ? ?public void SetValue( string name, Vector4[] val ) ? ? ? ?{ ? ? ? ? ? ?effect.SetValue( GetHandle( name ), val ); ? ? ? ?} ? ? ? ?public unsafe void SetValue( string name, void* val, int len ) ? ? ? ?{ ? ? ? ? ? ?effect.SetValue( GetHandle( name ), val, len ); ? ? ? ?} ? ? ? ?public unsafe void SetStructure(string name, object objStr) ? ? ? ?{ ? ? ? ? ? ?int nSize = Marshal.SizeOf(objStr); ? ? ? ? ? ?IntPtr unmanagedPointer = Marshal.AllocHGlobal(nSize); ? ? ? ? ? ?Marshal.StructureToPtr(objStr, unmanagedPointer, true); ? ? ? ? ? ?effect.SetValue(GetHandle(name), unmanagedPointer.ToPointer(), nSize); ? ? ? ? ? ?Marshal.FreeHGlobal(unmanagedPointer); ? ? ? ?} ? ? ? ?private EffectHandle GetHandle( string name ) ? ? ? ?{ ? ? ? ? ? ?if (!effectHandles.ContainsKey(name)) ? ? ? ? ? ?{ ? ? ? ? ? ? ? ?effectHandles.Add( name, effect.GetParameter( null, name ) ); ? ? ? ? ? ?} ? ? ? ? ? ?return (EffectHandle)effectHandles[name]; ? ? ? ?} ? ? ? ?public void PrintHandleDeclaration() ? ? ? ?{ ? ? ? ? ? ?foreach( string name in effectHandles.Keys ) ? ? ? ? ? ?{ ? ? ? ? ? ? ? ?System.Diagnostics.Debug.WriteLine(string.Format("private EffectHandle {0}Handle;", name)); ? ? ? ? ? ?} ? ? ? ?} ? ? ? ?public void PrintHandleAssignment(string effectName) ? ? ? ?{ ? ? ? ? ? ?foreach( string name in effectHandles.Keys ) ? ? ? ? ? ?{ ? ? ? ? ? ? ? ?System.Diagnostics.Debug.WriteLine(string.Format("{0}Handle = {1}.GetParameter(null, \"{2}\");", name, effectName, name)); ? ? ? ? ? ?} ? ? ? ?} ? ?} }
Using the proxy
The EffectHandleProxy class allows you to easily use handles for setting effect parameters, with a minimum of recoding. You can create an instance of the EffectHandleProxy alongside an effect. When you create the Effect object during a device reset (or initialization), simply call the Reset(Effect) method on the proxy object. This will bind the proxy to the effect and it will recreate any handles that were used on the effect before. Note that you need one proxy per effect and that you can keep reusing this proxy for the same effect over a device reset, using the Reset(Effect) method.
Actually setting the parameters is easy as well. You simply replace effect.SetParameter with proxyObject.SetParameter and that's that. The proxy supports all overloads of the Effect method (plus an extra one for structs) and it will automatically create a new EffectHandle for any parameter name that hasn't been used before.
Files for this resource
Filename | Size |
? EffectHandleProxy.zip | 911.0 B |
Further reading
-
?