A function to load shader files, compile and link to shader program.
std::string readShaderSource(const char* shaderfile)
{
std::ifstream ifile(shaderfile);
std::string filetext;
if (!ifile.good())
{
std::cerr << "Failed to load file" << std::endl;
}
std::stringstream shaderdata;
shaderdata << ifile.rdbuf();
ifile.close();
const std::string &shaderString = shaderdata.str();
//std::cout << shaderString << std::endl;
return shaderString;
}
GLuint createShaderProgram(const char* vshader_file, const char* fshader_file)
{
struct Shader {
const char* filename;
GLenum type;
const GLchar* source;
} shaders[2] = {
{ vshader_file, GL_VERTEX_SHADER, NULL },
{ fshader_file, GL_FRAGMENT_SHADER, NULL }
};
GLuint program = glCreateProgram();
// Load shader and check
for (int i = 0; i < 2; i++)
{
Shader& s = shaders[i];
std::string shader_string = util::readShaderSource(s.filename);
s.source = shader_string.c_str();
GLint const shader_length = shader_string.length();
if (shaders[i].source == NULL){
std::cerr << "Failed to read " << s.filename << std::endl;
exit(EXIT_FAILURE);
}
//printf("%s\n", s.source);
GLuint shader = glCreateShader(s.type);
glShaderSource(shader, 1, &s.source, &shader_length);
glCompileShader(shader);
GLint compiled;
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
if (compiled == GL_FALSE)
{
std::cerr << "Failed to compile " << s.filename << std::endl;
GLint logsize;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logsize);
char* logmsg = new char[logsize];
glGetShaderInfoLog(shader, logsize, NULL, logmsg);
std::cerr << logmsg << std::endl;
delete[] logmsg;
exit(EXIT_FAILURE);
}
//delete[] s.source;
glAttachShader(program, shader);
}
// Link program and check
glLinkProgram(program);
GLint linked;
glGetProgramiv(program, GL_LINK_STATUS, &linked);
if (linked == GL_FALSE)
{
std::cerr << "Shader program failed to link" << std::endl;
GLint logsize;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logsize);
char* logmsg = new char[logsize];
glGetProgramInfoLog(program, logsize, NULL, logmsg);
std::cerr << logmsg << std::endl;
delete[] logmsg;
exit(EXIT_FAILURE);
}
glUseProgram(program);
return program;
}