I've been following the LearnOpenGL.com tutorial in C++, but since I didn't like to manually hard-code the shaders into the code I wrote a function that reads the shaders from a file:
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;
}
}
I tried it the first time and it gave me this compilation error:
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.
I've no idea whats causing this, but I think it has something to do with the ReadShader function. Also the shaders are the exact same as the shaders from the tutorial.
Instead of
const char* ReadShader(const char* p_ShaderLocation)
{
return Buffer.str().c_str();
}
do
std::string ReadShader(const char* p_ShaderLocation)
{
return { Buffer.str() };
}
See also https://en.cppreference.com/w/cpp/io/basic_stringstream/str
Notes
The copy of the underlying string returned by
str
is a temporary object that will be destructed at the end of the expression, so directly callingc_str()
on the result ofstr()
(for example inauto *ptr = out.str().c_str();
) results in a dangling pointer.
Once you have the shader code as a string object, you can pass the code to the gl function like this:
auto shader_src = ReadShader();
const char *shader_src_str = shader_src.c_str();
GLint shader_src_len = shader_src.length();
glShaderSource(shader, 1, &shader_src_str, &shader_src_len /* or nullptr */);