使用结构从.txt文件读取着色器 [英] Reading a shader from a .txt file using a structure

查看:145
本文介绍了使用结构从.txt文件读取着色器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我开始学习如何使用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆