シェーダー クラスを設計しようとしています。今のところ、ユニフォームを処理するための基本的な概要を取得しようとしています。私が目指した設計目標のいくつかは、文字列を関数に渡さないようにすることです。これは、エラーが発生しやすく、型チェックがないためです。これがうまくいかない可能性がある場所は 1 つだけです。それは、ユニフォームを定義するときにユニフォームの名前を間違って入力した場合です。
ただし、コードが肥大化する可能性はたくさんあります。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"
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());
この実装についてどう思いますか? 改善案や、まったく異なるシステムについて何か提案はありますか? 人々がハッシュマップなどを使用しているのを見てきましたが、ユニフォームなどを設定するために文字列リテラルを継続的に使用するという問題がまだあります (マクロを使用して文字列を定義するという考えもあまり好きではありません)。