我有一个读取文件并将其内容作为std::string
返回的方法。我使用返回的std::string
来编译OpenGL程序。由于一个或两个着色器部分(读取文件内容)为NULL
,链接失败(编译顶点着色器已损坏。)。
为什么它表现不同,哪里是我的错?
最后的cout
始终打印正确的文件内容:
std::string read_file(const char* filePath) {
std::string content;
std::ifstream stream(filePath, std::ios::in);
if (stream.is_open()) {
std::string line = "";
while(getline(stream, line)) {
content += "\n" + line;
}
}
std::cout << "read_file " << content << "end read_file" << std::endl; // always prints the correct content
return content; // makes a copy, don't like that, unless RVO?..
}
fragmentSource
和/或vertextSource
有时是空的:
GLuint fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
GLuint vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
const char* fragmentSource = tools::read_file(_fragmentShaderPath).c_str();
std::cout << "vertext shader source: " << std::endl << fragmentSource; // empty sometimes
glShaderSource(fragmentShaderID, 1, &fragmentSource, NULL);
glCompileShader(fragmentShaderID);
CheckCompilation(fragmentShaderID);
const char* vertexSource = tools::read_file(_vertexShaderPath).c_str();
std::cout << "vertext shader source: " << std::endl << vertexSource; // empty sometimes
glShaderSource(vertexShaderID, 1, &vertexSource, NULL);
glCompileShader(vertexShaderID);
CheckCompilation(vertexShaderID);
GLuint programId = glCreateProgram();
glAttachShader(programId, fragmentShaderID);
glAttachShader(programId, vertexShaderID);
glLinkProgram(programId);
GLint result = GL_FALSE;
GLint infoLogLength;
glGetProgramiv(programId, GL_LINK_STATUS, &result);
glGetProgramiv(programId, GL_INFO_LOG_LENGTH, &infoLogLength);
if (infoLogLength > 0) { // this fails sometimes, corresponding to either vertexSource or fragmentSource being empty
std::vector<char> infoLog(infoLogLength + 1);
glGetProgramInfoLog(programId, infoLogLength, NULL, &infoLog[0]);
std::cout << &infoLog[0] << std::endl;
}
答案 0 :(得分:10)
替换
const char* fragmentSource = tools::read_file(_fragmentShaderPath).c_str();
带
std::string fragmentSourceStr = tools::read_file(_fragmentShaderPath);
const char* fragmentSource = fragmentSourceStr.c_str();
与vertexSource
相同。
问题是您返回的字符串是临时的,因此在使用指向其数据的指针初始化fragmentSource
后会将其销毁,这会使fragmentSource
指向已经被破坏的存储。
答案 1 :(得分:0)
如果是我,我宁愿只处理c ++类型,直到我们真正触及openGL C api。
首先,我在tools
命名空间中创建一个轻量级代理函数:
namespace tools {
auto shaderSource(GLuint shaderId, const std::string& source)
{
auto ptr = std::addressof(source[0]);
return glShaderSource(shaderId, 1, std::addressof(ptr), nullptr);
}
}
然后完全替换原始指针的使用:
auto fragmentSource = tools::read_file(_fragmentShaderPath);
std::cout << "vertext shader source: " << std::endl << fragmentSource; // empty sometimes
tools::shaderSource(fragmentShaderID, fragmentSource);