我一直在关注 LearnOpenGL.com 的 C++ 教程,但由于我不喜欢将着色器手动硬编码到代码中,所以我编写了一个从文件中读取着色器的函数:
const char* ReadShader(const char* p_ShaderLocation)
{
std::ifstream ShaderStream;
std::stringstream Buffer;
ShaderStream.open(p_ShaderLocation);
if (!ShaderStream)
{
std::cout << "File: " << p_ShaderLocation << " can't be opened!" << '\n';
return 0;
}
if (ShaderStream.is_open())
{
Buffer << ShaderStream.rdbuf();
ShaderStream.close();
return Buffer.str().c_str();
}
else if (!ShaderStream.is_open())
{
std::cout << "File: " << p_ShaderLocation << " can't be read!" << '\n';
return 0;
}
}
我第一次尝试它,它给了我这个编译错误:
ERROR: Vertex Shader Compilaton Failed
ERROR: 0:2: 'Ç' : unexpected token
ERROR: 0:2: '' : compilation terminated
ERROR: 2 compilation errors. No code generated.
ERROR: Fragment Shader Compilaton Failed
ERROR: 0:2: '' : syntax error, unexpected IDENTIFIER
ERROR: 1 compilation errors. No code generated.
我不知道是什么原因造成的,但我认为这与 ReadShader 函数有关。 此外,着色器与教程中的着色器完全相同。
而不是
const char* ReadShader(const char* p_ShaderLocation)
{
return Buffer.str().c_str();
}
做
std::string ReadShader(const char* p_ShaderLocation)
{
return { Buffer.str() };
}
另请参阅 https://en.cppreference.com/w/cpp/io/basic_stringstream/str
注释
返回的基础字符串的副本是一个临时对象,将在表达式末尾被破坏,因此直接对str
的结果调用c_str()
(例如在str()
中)会导致悬空指针。auto *ptr = out.str().c_str();
将着色器代码作为字符串对象后,您可以将代码传递给 gl 函数,如下所示:
auto shader_src = ReadShader();
GLint shader_src_length = shader_src.length();
const char *shader_src_str = shader_src.c_str();
glShaderSource(shader, 1, &shader_src_str, &shader_src_length /* or nullptr */);