试图设计一个着色器类,现在只是试图获得处理制服的基本轮廓。我所针对的一些设计目标是避免将字符串传递给函数,因为这很容易出错并且没有类型检查。只有一个地方可能会出错,如果您在定义制服时错误输入制服的名称。
然而,代码膨胀有很多可能,可能会将Name从参数的模板参数中移出,并将其存储为成员变量,该变量将在默认构造函数中分配。
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"
shaderparameters.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());
您对此实施有何看法?您是否有改进建议或者可能是完全不同的系统?我知道我已经看到人们使用哈希映射等但是仍然存在持续使用字符串升级来设置制服等问题(不太喜欢使用宏来定义字符串的想法)。