I'm working on a managed OpenGL game engine for C#, and here's how I'm managing shader parameters (uniforms). Is it "alright"? Could it be better? I'm a bit unsure about using generics in this case.
public abstract class ShaderParameter
{
public readonly string Name;
internal readonly int Location;
internal readonly Shader Parent;
internal ShaderParameter(string name, int location, Shader parent)
{
Name = name;
Location = location;
Parent = parent;
}
//Ensures that the value is set on the shader,
//this should be called before using the parent shader
internal abstract void EnsureSet();
//Gives a value to this shader paramerter
public abstract void SetValue<T>(T value);
}
//A shader paramater of type float
public sealed class ShaderParamFloat : ShaderParameter
{
float value = 0;
bool valueChanged = false; //If the value has changed since the last time it was set on the shader
internal ShaderParamFloat(string name, int location, Shader parent)
: base(name, location, parent)
{ }
internal override void EnsureSet()
{
if (valueChanged)
{
//Hands over a single value to OpenGL.
GL.Uniform1(Location, value);
valueChanged = false;
}
}
//Gives a value to this shader parameter
public override void SetValue<T>(T value)
{
if (typeof(T) != typeof(float))
throw new ArgumentException("Value is of type: " + typeof(T).ToString() + ", expected: float", "value");
this.value = (float)(object)value;
valueChanged = true;
}
}
The reason for using inheritance is because other ShaderParameter
classes behave differently in EnsureSet()
. For example, ShaderParamVector3
uses GL.Uniform3(...)
, and ShaderParamTexture
needs to ensure that the texture is valid and set on the graphics card.