使用结构从.txt文件读取着色器 [英] Reading a shader from a .txt file using a structure
问题描述
我开始学习如何使用OpenGL,我绝对讨厌在我的main()之前将我的着色器声明为全局变量。
我认为从我的项目目录中的文件中读取着色器的结构或类是很酷的。文件读取工作完全正常,但由于某种原因,它不会实际输出一个图像,如果我有在main之前声明的着色器。这是我的例子。
着色器阅读结构:
#includeallHeader.h
struct shaderReader
{
shaderReader :: shaderReader(std :: string);
const GLchar * source;
};
shaderReader :: shaderReader(std :: string name)
{
std :: string line,allLines;
std :: ifstream theFile(name);
if(theFile.is_open())
{
while(std :: getline(theFile,line))
{
allLines = allLines + line + \\ n;
}
source = allLines.c_str();
std :: cout<<资源;
theFile.close();
}
else
{
std :: cout< 无法打开文件。;
}
}
shaderReader vertexShader = shaderReader(vertex.txt);
shaderReader fragmentShader = shaderReader(fragment.txt);
const GLchar * vertexSource =
#version 150 core\\\
in vec2 position;
void main(){
gl_Position = vec4(position,0.0,1.0);
};
const GLchar * fragmentSource =
#version 150 core\\\
out vec4 outColor;
void main(){
outColor = vec4(1.0,1.0,1.0,1.0);
};
int main()
{
// stuff
}
工作
GLuint vertexShaderObject = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShaderObject,1,& vertexSource,NULL);
glCompileShader(vertexShaderObject);
//现在让我们创建Fragment着色器对象
GLuint fragmentShaderObject = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShaderObject,1,& fragmentSource,NULL);
glCompileShader(fragmentShaderObject);
对某些原因无效
const GLchar * ob1 = vertexShader.source;
const GLchar * ob2 = fragmentShader.source;
GLuint vertexShaderObject = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShaderObject,1,& ob1,NULL);
glCompileShader(vertexShaderObject);
//现在让我们创建Fragment Shader对象
GLuint fragmentShaderObject = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShaderObject,1,& ob2,NULL);
glCompileShader(fragmentShaderObject);
也无效
GLuint vertexShaderObject = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShaderObject,1,& vertexShader.source,NULL);
glCompileShader(vertexShaderObject);
//现在让我们创建Fragment Shader对象
GLuint fragmentShaderObject = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShaderObject,1,& fragmentShader.source,NULL);
glCompileShader(fragmentShaderObject);
上述代码在黑色屏幕中间打印出一个白色三角形。然而,当不工作,我只得到一个黑色的屏幕。我试着检查着色器的编译错误,我没有任何错误。我认为在结构中可能有错误,有些事情我做不对。谢谢你阅读我的问题,如果你有一个类似的问题,我希望我的问题可以帮助你。
您使用的是C ++( std :: string
)和C( char *
)字符串。
在C ++ string
中的代码,它是一个对象,它自动分配和重新分配内存,以在字符串增长时保存字符串数据。
问题的根源在于:
source = allLines.c_str();
其中 source
是一个类/ 。 string
上的 c_str()
方法为您提供了指向对象的内部字符串数据的指针。如上所述,当 allLines
超出了 shaderReader
构造函数末尾的范围时,此数据将被释放,因此结束了一个指向释放内存的指针。这导致未定义的行为,因为这个内存现在可以用于别的东西。
解决这个问题的最简单的方法是使用C ++字符串。将结构体定义更改为:
struct shaderReader
{
shaderReader :: shaderReader(std :: string );
std :: string source;
};然后在构造函数中,你可以直接读取这个类成员的源代码:
while(std :: getline(theFile,line))
{
source = source + line +\ n。
}
你必须用 char *
是因为 glShaderSource()
需要一个。最安全的方法是在最后一刻转换:
const GLchar * ob1 = vertexShader.source.c_str
GLuint vertexShaderObject = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShaderObject,1,& ob1,NULL);
glCompileShader(vertexShaderObject);这样,你只使用指向内部字符串$>的指针
$ b c $ c>数据非常临时,你不必费心C风格的字符串和内存管理否则。
I've started learning how to use OpenGL and I absolutely hate having my shaders declared as global variables before my main().
I thought it would be cool to make a structure or class that would read the shader from a file in my project directory. The file reading works perfectly fine, but for some reason it won't actually output an image like it would if I had the shader declared before main. Here is my example.
Shader Reading Structure:
#include "allHeader.h"
struct shaderReader
{
shaderReader::shaderReader(std::string);
const GLchar* source;
};
shaderReader::shaderReader(std::string name)
{
std::string line, allLines;
std::ifstream theFile(name);
if (theFile.is_open())
{
while (std::getline(theFile, line))
{
allLines = allLines + line + "\n";
}
source = allLines.c_str();
std::cout << source;
theFile.close();
}
else
{
std::cout << "Unable to open file.";
}
}
Snapshot of Area right before main()
shaderReader vertexShader = shaderReader("vertex.txt");
shaderReader fragmentShader = shaderReader("fragment.txt");
const GLchar* vertexSource =
"#version 150 core\n"
"in vec2 position;"
"void main() {"
" gl_Position = vec4(position, 0.0, 1.0);"
"}";
const GLchar* fragmentSource =
"#version 150 core\n"
"out vec4 outColor;"
"void main() {"
" outColor = vec4(1.0, 1.0, 1.0, 1.0);"
"}";
int main()
{
//stuff
}
Works
GLuint vertexShaderObject = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShaderObject, 1, &vertexSource, NULL);
glCompileShader(vertexShaderObject);
//Now let's create the Fragment Shader Object
GLuint fragmentShaderObject = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShaderObject, 1, &fragmentSource, NULL);
glCompileShader(fragmentShaderObject);
Doesn't work for some Reason
const GLchar* ob1 = vertexShader.source;
const GLchar* ob2 = fragmentShader.source;
GLuint vertexShaderObject = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShaderObject, 1, &ob1, NULL);
glCompileShader(vertexShaderObject);
//Now let's create the Fragment Shader Object
GLuint fragmentShaderObject = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShaderObject, 1, &ob2, NULL);
glCompileShader(fragmentShaderObject);
Also Doesn't Work
GLuint vertexShaderObject = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShaderObject, 1, &vertexShader.source, NULL);
glCompileShader(vertexShaderObject);
//Now let's create the Fragment Shader Object
GLuint fragmentShaderObject = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShaderObject, 1, &fragmentShader.source, NULL);
glCompileShader(fragmentShaderObject);
The above code when working prints out a white triangle in the middle of a black screen. However, when not working I just get a black screen. I tried checking the shaders for compile errors and I got no errors at all. I'm think perhaps something is wrong within the structure, something there I didn't do right. Thank you for reading my question, if you had a similar problem I hope my question helps you.
解决方案 You're using a mix of C++ (std::string
) and C (char*
) strings in an invalid way.
In the constructor, you're building up the code in a C++ string
, which is an object that automatically allocates and re-allocates the memory to hold the string data as the string grows. It will also automatically free that data when it goes out of scope at the end of the constructor.
The root of the problem is here:
source = allLines.c_str();
where source
is a class/struct member. The c_str()
method on the string
gives you a pointer to the internal string data of the object. As explained above, this data is freed when allLines
goes out of scope at the end of the shaderReader
constructor, so you end up with a pointer to freed memory. This results in undefined behavior, because this memory could now be used for something else.
The cleanest way to fix this is to use C++ strings consistently. Change the struct definition to:
struct shaderReader
{
shaderReader::shaderReader(std::string);
std::string source;
};
Then in the constructor, you can read the source code directly into this class member:
while (std::getline(theFile, line))
{
source = source + line + "\n";
}
The only reason why you have to bother with a char*
is because glShaderSource()
needs one. The safest approach is to convert this at the last moment:
const GLchar* ob1 = vertexShader.source.c_str();
GLuint vertexShaderObject = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShaderObject, 1, &ob1, NULL);
glCompileShader(vertexShaderObject);
This way, you only use the pointer to the internal string
data very temporarily, and you don't have to bother with C-style strings and memory management otherwise.
这篇关于使用结构从.txt文件读取着色器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!