我有一个自定义着色器生成:
class My_UniformInt { public:
std::string idName;
int glsl_id; //<-- userData-like field
};
class My_Shader{ public:
My_UniformInt textureCoordinate;
public: My_Shader(){
textureCoordinate.idName="textureCoordinate";
}
};
void registerUniform( My_Shader& shader, My_UniformInt & uniInt){
uniInt.glsl_id=5;
//vec3.glsl_id=glGetUniformLocation(uniInt.idName);
}
void passUniformInt( My_Shader& shader, My_UniformInt & uniInt,int k){
std::cout<<"successfully pass name="<<uniInt.idName<<" va="<<k<<std::endl;
//glUniform1i(uniInt.glsl_id,k);
}
我可以生成着色器并像这样使用它:
int main(){
My_Shader shader;
registerUniform( shader , shader.textureCoordinate ) ;
//.. several frame later
passUniformInt( shader , shader.textureCoordinate , 5 ) ;
return 0;
}
它运行速度很快(MCVE),但存在不良耦合。
1. My_UniformInt
缓存 glsl 特定变量 ( glsl_id
)。
2. My_UniformInt
也对glGetUniformLocation
情有独钟.
如何制作My_UniformInt
在不牺牲速度的情况下更独立?
我有几个案例有类似的问题。不幸的是,最明显的选择通常似乎是添加更多类似 userData 的字段。它增加了耦合。
我糟糕的解决方案:
制作
glsl_id
作为void* userData
, 然后分配userData=new int()
不酷+有一点成本+需要稍后删除。创建 map
std::map<My_UniformInt*,int glsl_id>
.不过我负担不起。
最佳答案
这是我的评论作为回答:
我认为您应该尝试将使用 API 的代码包装在自己的空间中,以便以后可以轻松交换 - 创建一个为您访问 API 的类,如果您想切换后端,只需调整该类.以不使用任何特定于 API 的代码或变量的方式构建其余代码,而是使用包装器与其交互。
我认为这通常是处理任何类型的库或任何东西的好方法。它允许您通过不依赖它们提供的任何类型的接口(interface),而仅依赖于您自己的接口(interface)来快速适应其中的变化。挑战在于以提供良好抽象的方式编写包装器,这样您就可以理想地使用另一个使用完全不同接口(interface)的后端,同时尽量做到原生以确保低开销。
关于c++ - 解耦自定义用户数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57439614/