Last active
April 3, 2018 07:04
-
-
Save RobertHue/57e465f5edfd9ab6f57ef954ccaffd17 to your computer and use it in GitHub Desktop.
OpenGL - glsl Shader loader class
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef SHADER_H | |
#define SHADER_H | |
#include <GL/glew.h> | |
#include <iostream> // std::cout std::cin | |
#include <fstream> // std::ifstream | |
#include <string> // std::string | |
#include <sstream> // std::stringstream | |
/////////////////////////////////////////////////////////////////////////////////////////////////// | |
/// @class used to compile a vertex and fragment shader and | |
/// link them to a program which will get loaded onto the GPU | |
class Shader | |
{ | |
public: | |
/// @brief creates, loads and activates a shader program to run on GPU | |
Shader(const std::string& filePathVertexShader, const std::string& filePathFragmentShader); | |
/// @brief destroys the shader program | |
~Shader(); | |
private: | |
/// @brief reads the file give by its path filePath | |
/// @return a copy of the content of the file | |
std::string readFile(const std::string& filePath); | |
/// @brief compiles a shader of give type with give GLSL source code as string | |
/// @param type GL_VERTEX_SHADER or GL_FRAGMENT_SHADER | |
/// @param source a reference to the GLSL source code as std::string | |
/// @return hShader if succeeded, otherwhise 0 | |
GLuint compileShader(GLuint type, const std::string& source); | |
/// @brief compiles and links a GLSL-Shader-Pair | |
/// @note to activate the shader created by this use glUseProgram(hProgram); | |
void createShader(const std::string& vertexShader, const std::string& fragmentShader); | |
private: | |
GLuint hProgram; | |
}; | |
/////////////////////////////////////////////////////////////////////////////////////////////////// | |
////////////////////////////////////////// public implementations: | |
inline | |
Shader::Shader(const std::string& filePathVertexShader, const std::string& filePathFragmentShader) | |
{ | |
// read compile link and load a GLSL shader as a program | |
std::string vertexShader = readFile(filePathVertexShader); | |
std::string fragmentShader = readFile(filePathFragmentShader); | |
createShader(vertexShader, fragmentShader); | |
glUseProgram(hProgram); | |
} | |
inline | |
Shader::~Shader() | |
{ | |
if (hProgram != 0) | |
{ | |
glDeleteProgram(hProgram); | |
} | |
} | |
/////////////////////////////////////////////////////////////////////////////////////////////////// | |
////////////////////////////////////////// private implementations: | |
inline | |
std::string Shader::readFile(const std::string& filePath) { | |
std::ifstream fs(filePath, std::ios::in); | |
if (!fs.is_open()) { | |
std::cerr << "Could not read file " << filePath << ". File does not exist." << std::endl; | |
return ""; | |
} | |
std::stringstream buffer; | |
std::string line; | |
while (std::getline(fs, line)) { | |
// debug: | |
// std::cout << line << "\n"; | |
buffer << line << "\n"; | |
} | |
fs.close(); | |
return buffer.str(); | |
} | |
inline | |
GLuint Shader::compileShader(GLuint type, const std::string& source) | |
{ | |
// creates an empty shader obj, ready to accept source-code and be compiled | |
GLuint hShader = glCreateShader(type); | |
// hands the shader source code to the shader object so that it can keep a copy of it | |
const char* src = source.c_str(); | |
glShaderSource(hShader, 1, &src, nullptr); | |
// compiles whatever source code is contained in the shader object | |
glCompileShader(hShader); | |
// Error Handling: Check whether the shader has been compiled | |
GLint result; | |
glGetShaderiv(hShader, GL_COMPILE_STATUS, &result); // assigns result with compile operation status | |
if (result == GL_FALSE) | |
{ | |
int length; | |
glGetShaderiv(hShader, GL_INFO_LOG_LENGTH, &length); // assigns length with length of information log | |
char* infoLog = (char*)alloca(length * sizeof(char)); // allocate on stack frame of caller | |
glGetShaderInfoLog(hShader, length, &length, infoLog); // returns the information log for a shader object | |
std::cout << "Failed to compile shader!" | |
<< (type == GL_VERTEX_SHADER ? "vertex" : "fragment") | |
<< std::endl; | |
std::cout << infoLog << std::endl; | |
glDeleteShader(hShader); | |
return static_cast<GLuint>(0); | |
} | |
return hShader; | |
} | |
inline | |
void Shader::createShader(const std::string& vertexShader, const std::string& fragmentShader) { | |
// compile the two shaders given as string reference | |
GLuint vs = compileShader(GL_VERTEX_SHADER, vertexShader); | |
GLuint fs = compileShader(GL_FRAGMENT_SHADER, fragmentShader); | |
if (vs == 0 || fs == 0) { return; } | |
// create a container for the program-object to which you can attach shader objects | |
hProgram = glCreateProgram(); | |
// attaches the shader objects to the program object | |
glAttachShader(hProgram, vs); | |
glAttachShader(hProgram, fs); | |
// links all the shader objects, that are attached to a program object, together | |
glLinkProgram(hProgram); | |
// Error Handling: Check whether program has been linked successfully | |
GLint result; | |
glGetShaderiv(hProgram, GL_COMPILE_STATUS, &result); // assigns result with compile operation status | |
if (result == GL_FALSE) | |
{ | |
int length; | |
glGetShaderiv(hProgram, GL_INFO_LOG_LENGTH, &length); // assigns length with length of information log | |
char* infoLog = (char*)alloca(length * sizeof(char)); // allocate on stack frame of caller | |
glGetShaderInfoLog(hProgram, length, &length, infoLog); // returns the information log for a shader object | |
std::cout << "Failed to link vertex and fragment shader!" | |
<< std::endl; | |
std::cout << infoLog << std::endl; | |
glDeleteProgram(hProgram); | |
return; | |
} | |
glValidateProgram(hProgram); | |
// deletes intermediate objects | |
glDeleteShader(vs); | |
glDeleteShader(fs); | |
// activate the program into the state machine of opengl | |
// glUseProgram(hProgram); | |
} | |
#endif /* SHADER_H */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment