C++ 使用面向对象的方法加载着色器
我的应用程序将是一个OpenGL游戏,使用C++ 使用面向对象的方法加载着色器,c++,string,opengl,C++,String,Opengl,我的应用程序将是一个OpenGL游戏,使用OpenGL4.2、GLFW和GLEW。问题在于如何从文件加载GLSL着色器。对于所有与着色器相关的任务,我使用名为ShadersObject的类 class ShadersObject { public: // ... private: // ... void LoadFile(string Name, string Path); string FolderPath; Shaders ShaderList; };
OpenGL4.2
、GLFW
和GLEW
。问题在于如何从文件加载GLSL着色器。对于所有与着色器相关的任务,我使用名为ShadersObject
的类
class ShadersObject
{
public:
// ...
private:
// ...
void LoadFile(string Name, string Path);
string FolderPath;
Shaders ShaderList;
};
该类使用ShaderObject
s的映射来存储着色器
enum ShaderType{ Vertex = GL_VERTEX_SHADER,
Geometry = GL_GEOMETRY_SHADER,
Fragment = GL_FRAGMENT_SHADER };
struct ShaderObject
{
const GLchar* File;
ShaderType Type;
GLuint Shader;
// ...
};
typedef map<string, ShaderObject> Shaders;
我希望使用ShaderList[Name].File中的值的另一种方法,使用glShaderSource
和glCompileShader
加载和编译着色器。其中,glShaderSource
需要指向保存源代码的const GLchar*
的指针。在我的例子中,这将是&ShaderList[Name].File
不久前,我使用了ShaderList[Name].File=Output.c_str()代码>而不是现在不编译的行。结果是,只有指针保存在着色器列表中
,方法退出后,源代码就消失了。这就是为什么我尝试使用strcpy
,但此函数不接受const GLchar*
作为参数类型
如何将读取的文件保存到类成员中?这不是一个复杂的问题:存储字符串。将输出
存储在着色器对象
类中。当需要调用glShaderSource
时,使用string::c_str
将其转换为const GLchar*
或者更好;不要存储它们中的任何一个;OpenGL将在着色器对象中保留着色器字符串。可以通过API从OpenGL查询着色器字符串。因此,在着色器对象中存储OpenGL已经存储的内容是毫无意义的。这不是一个复杂的问题:存储字符串。将输出
存储在着色器对象
类中。当需要调用glShaderSource
时,使用string::c_str
将其转换为const GLchar*
或者更好;不要存储它们中的任何一个;OpenGL将在着色器对象中保留着色器字符串。可以通过API从OpenGL查询着色器字符串。因此,在着色器对象中存储OpenGL已经存储的内容是毫无意义的。为什么不在ShaderObject
中将其存储为std::string
,并在必要时使用c_str()
?如果您想使用strcpy()
您需要为.File
分配内存,并将其设为非const
。谢谢,我不明白为什么我以前没有尝试过它?!简单的解决方案。为什么不将其存储为std::string
中的ShaderObject
并在必要时使用c_str()
?如果您想使用strcpy()
您需要为.File
分配内存,并将其设为非const
。谢谢,我不明白为什么我以前没有尝试过它?!简单的解决方案。OpenGL是否也存储着色器的类型以便我可以查询它?@sharethis:可以。谢谢,所以我只需要存储字符串名称和OpenGL int名称以及着色器是否处于活动状态。再次感谢你!编辑:我想存储源代码,以便打开和关闭着色器。如果这很聪明,你能给我一个建议吗?@sharethis:存储源代码不会有帮助。链接程序后,除非重新链接该程序,否则对构成该程序的着色器所做的操作是无关的。而且很贵。所以没有。通过绑定/解除绑定着色器程序来打开和关闭着色器程序。如果将着色器类和程序类分开,则可以使用OpenGL API允许的功能,并将单个着色器链接到多个程序中,其中每个程序可能由一组不同的着色器组成。例如,对于使用相同的顶点变换,但使用不同的片段着色器(阴影缓冲区计算,与最终渲染过程或类似过程)来说,这很有用。OpenGL是否也存储着色器的类型,以便我可以查询它?@sharethis:可以。谢谢,因此,我只需要存储字符串名称和OpenGL int名称,以及着色器是否处于活动状态。再次感谢你!编辑:我想存储源代码,以便打开和关闭着色器。如果这很聪明,你能给我一个建议吗?@sharethis:存储源代码不会有帮助。链接程序后,除非重新链接该程序,否则对构成该程序的着色器所做的操作是无关的。而且很贵。所以没有。通过绑定/解除绑定着色器程序来打开和关闭着色器程序。如果将着色器类和程序类分开,则可以使用OpenGL API允许的功能,并将单个着色器链接到多个程序中,其中每个程序可能由一组不同的着色器组成。例如,对于使用相同的顶点变换,但使用不同的片段着色器(阴影缓冲区计算,与最终渲染过程或类似过程)非常有用。
void ShadersObject::LoadFile(string Name, string Path)
{
string FilePath = FolderPath + Path;
ifstream Stream(FilePath);
if(Stream.is_open())
{
cout << "Loading Shader from " << FilePath << endl;
string Output;
Stream.seekg(0, ios::end);
Output.reserve(Stream.tellg());
Stream.seekg(0, ios::beg);
Output.assign((istreambuf_iterator<char>(Stream)),istreambuf_iterator<char>());
// this line doesn't compile
strcpy(ShaderList[Name].File, Output.c_str());
}
else cout << "Can not load Shader from " << FilePath << endl;
}