How to load a GLSL shader in OpenGL using C++
Got asked how to load a GLSL shader today and as I had an OpenGL wrapper containing this code, I thought it would be nice to share it with you. It also includes loading the files as well as debugging info. Enjoy ;) GLShader.hpp
#ifndef GLSHADER_H
#define GLSHADER_H
#include "GL/glew.h"
GLuint LoadShader(const char *vertex_path, const char *fragment_path);
#endif
GLShader.cpp:
#include "GLShader.hpp"
#include <string>
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
std::string readFile(const char *filePath) {
std::string content;
std::ifstream fileStream(filePath, std::ios::in);
if(!fileStream.is_open()) {
std::cerr << "Could not read file " << filePath << ". File does not exist." << std::endl;
return "";
}
std::string line = "";
while(!fileStream.eof()) {
std::getline(fileStream, line);
content.append(line + "\n");
}
fileStream.close();
return content;
}
GLuint LoadShader(const char *vertex_path, const char *fragment_path) {
GLuint vertShader = glCreateShader(GL_VERTEX_SHADER);
GLuint fragShader = glCreateShader(GL_FRAGMENT_SHADER);
// Read shaders
std::string vertShaderStr = readFile(vertex_path);
std::string fragShaderStr = readFile(fragment_path);
const char *vertShaderSrc = vertShaderStr.c_str();
const char *fragShaderSrc = fragShaderStr.c_str();
GLint result = GL_FALSE;
int logLength;
// Compile vertex shader
std::cout << "Compiling vertex shader." << std::endl;
glShaderSource(vertShader, 1, &vertShaderSrc, NULL);
glCompileShader(vertShader);
// Check vertex shader
glGetShaderiv(vertShader, GL_COMPILE_STATUS, &result);
glGetShaderiv(vertShader, GL_INFO_LOG_LENGTH, &logLength);
std::vector vertShaderError((logLength > 1) ? logLength : 1);
glGetShaderInfoLog(vertShader, logLength, NULL, &vertShaderError[0]);
std::cout << &vertShaderError[0] << std::endl;
// Compile fragment shader
std::cout << "Compiling fragment shader." << std::endl;
glShaderSource(fragShader, 1, &fragShaderSrc, NULL);
glCompileShader(fragShader);
// Check fragment shader
glGetShaderiv(fragShader, GL_COMPILE_STATUS, &result);
glGetShaderiv(fragShader, GL_INFO_LOG_LENGTH, &logLength);
std::vector fragShaderError((logLength > 1) ? logLength : 1);
glGetShaderInfoLog(fragShader, logLength, NULL, &fragShaderError[0]);
std::cout << &fragShaderError[0] << std::endl;
std::cout << "Linking program" << std::endl;
GLuint program = glCreateProgram();
glAttachShader(program, vertShader);
glAttachShader(program, fragShader);
glLinkProgram(program);
glGetProgramiv(program, GL_LINK_STATUS, &result);
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);
std::vector<char> programError( (logLength > 1) ? logLength : 1 );
glGetProgramInfoLog(program, logLength, NULL, &programError[0]);
std::cout << &programError[0] << std::endl;
glDeleteShader(vertShader);
glDeleteShader(fragShader);
return program;
}
This is loaded by calling the following code:
GLuint program = LoadShader("shader.vert", "shader.frag");
glUseProgram(program);
It can also be used to load multiple shaders by calling glUseProgram on different GLuints or 0 as the parameter to disable.
Comments
Stephan
on Oct 13, 2013Reply
Thank you very much!
There’s an error at the line:
content.append(line + "n");
in readFile. I suppose it should be
content.append(line + "\n");
Nex
on Oct 13, 2013Reply
Thank you Stephan! The error is corrected :)
Joe
on Jun 28, 2014Reply
Thanks!
Just wanted to let you know that in using this today I was getting out of bounds errors. I found that when you check errors on the fragment and vertex shaders, it doesn’t check if logLength is less than one like you did after linking the program. I changed the lines to:
std::vector vertShaderError((logLength > 1) ? logLength : 1);
and
std::vector fragShaderError((logLength > 1) ? logLength : 1);
Thanks again!
Kim Einar Larsen
on Oct 15, 2014Reply
Takk! Jeg holder på å lærer meg OpenGL/GLSL så dette var lærerikt. Før jeg kom over dette eksempelet så hadde jeg problemer med å bruke std::string i glShaderSource da jeg ikke ønsket å bruke const char* så jeg googlet meg frem til dette. Note: vector —> vector
Nex
on Oct 18, 2014Reply
Takk for det, Kim! Godt å kunne være til hjelp :)
Joe Kerman
on Mar 22, 2015Reply
just wanted to point out at this line:
std::vector vertShaderError((logLength > 1) ? logLength : 1);
You didn’t specify the type. Its should be:std::vector vertShaderError((logLength > 1) ? logLength : 1);
Thanksnadim farhat
on Mar 30, 2015Reply
2 years laters. Thanks a lot
woop
on May 25, 2016Reply
u missing the template argument where … std::vector vertShaderError((logLength > 1) ? logLength : 1); and std::vector fragShaderError((logLength > 1) ? logLength : 1); that should be (if i didn’t … …) change the std::vector to std::vector
Romualdo Villalobos
on Jun 05, 2016Reply
some faster!! std::string readFile(const char* filepath) { std::ifstream myFile(filepath); std::string content((std::istreambuf_iterator(myFile)), std::istreambuf_iterator()); return content; }
hsaturn
on Feb 19, 2017Reply
std::vector vertShaderError Error there !!!
This is probably not your fault, the template argument may have been deleted by any html token cleaner etc..
I’ve used GLchar and it compiles correctly
std::vector (char) vertShaderError …
replace parenthesis of course
hsaturn
on Feb 21, 2017Reply
template arguments are char.
I think they have disapear for some html tag cut reason.
RG
on Aug 06, 2017Reply
.\src\GLShader.cpp:52:54: error: ‘vertShaderError’ was not declared in this scope glGetShaderInfoLog(vertShader, logLength, NULL, &vertShaderError[0]); ^ ..\src\GLShader.cpp:63:17: error: missing template arguments before ‘fragShaderError’ std::vector fragShaderError((logLength > 1) ? logLength : 1);
No clue ^
Mukyu
on Dec 22, 2017Reply
std::vector might be std::vector to get the string of error
Reself
on Dec 31, 2017Reply
?? thats the same
Seyed Morteza Kamali
on Jan 03, 2019Reply
std::vector might be std::vector to get the string of error
I uploaded my project in github if fix all problems
https://github.com/smkplus/OpenGLPractice
Leave a comment