很好地尝试设计一个着色器类,现在只是尝试获得处理制服的基本轮廓。我的一些设计目标是避免将字符串传递给函数,因为这很容易出错并且没有类型检查。只有一个地方会出错,如果你在定义制服的时候打错了制服的名字。
但是,代码膨胀的可能性很大,可能会将 Name 从 Parameter 的模板参数中移出,并将其存储为成员变量,该成员变量将在默认构造函数中分配。
template<typename ParamType>
class Shader
{
public:
template<typename Type, const char* (*Name)()>
class Parameter
{
static const char* name;
static GLuint location;
static GLuint program;
template<typename> friend class Shader;
};
template<typename Type, const char* (*Name)()>
void SetParameter(const Parameter<Type,Name>&, const Type& value )
{
// static_assert(!std::is_same<Type,Type>::value, "Unsupported type, needs specialization.");
typedef Parameter<Type,Name> Param;
if(program != -1 && Param::program != program)
{
// set Param::location
Param::program = program;
}
std::cout << Param::name << std::endl;
}
private:
GLuint program;
};
template<typename ParamType>
template<typename Type, const char* (*Name)()>
const char* Shader<ParamType>::Parameter<Type, Name>::name = Name();
template<typename ParamType>
template<typename Type, const char* (*Name)()>
GLuint Shader<ParamType>::Parameter<Type, Name>::program = -1;
#include "shaderparameters.inl"
着色器参数.inl:
#define MY_PARAMETER(shader, type, name) \
private: static const char* ShaderParameterStr##shader##type##name##() { return #name ; } \
public: typedef Shader< shader >::Parameter< type, &ShaderParameterStr##shader##type##name > name;
struct ShaderParam
{
struct Generic
{
MY_PARAMETER( Generic, Vec4, position )
MY_PARAMETER( Generic, Mat4, projection )
};
};
#undef MY_PARAMETER
用法:
Shader<ShaderParam::Generic> s;
s.SetParameter(ShaderParam::Generic::projection(), Mat4());
s.SetParameter(ShaderParam::Generic::position(), Vec4());
您对此实施有何看法?您对改进或完全不同的系统有什么建议吗?我知道我见过人们使用哈希映射等,但仍然存在连续使用字符串文字来设置制服等的问题(也不太喜欢使用宏来定义字符串的想法)。