#include #include #include "client/engine/shader/ShaderProgram.h" ShaderProgram::ShaderProgram() { } ShaderProgram::~ShaderProgram() { glDeleteShader(vertexShader); glDeleteShader(fragmentShader); glDeleteProgram(program); } bool ShaderProgram::isValid() const { return valid; } GLuint ShaderProgram::getProgram() const { return program; } void ShaderProgram::compile(const GLchar* vertexPath, const GLchar* fragmentPath) { if(valid) { return; } GLchar* vertexData = readFile(vertexPath); if(vertexData == nullptr) { cout << "cannot read " << vertexPath << endl; return; } GLchar* fragmentData = readFile(fragmentPath); if(fragmentData == nullptr) { cout << "cannot read " << fragmentPath << endl; delete[] vertexData; return; } compile(vertexPath, vertexData, fragmentPath, fragmentData); delete[] vertexData; delete[] fragmentData; } GLchar* ShaderProgram::readFile(const GLchar* name) { ifstream in; in.open(name); if(!in.fail()) { int size = 128; int index = 0; GLchar* content = new GLchar[size]; while(true) { GLchar c = in.get(); if(in.eof()) { break; } if(index >= size - 1) { GLchar* newContent = new GLchar[size * 2]; memcpy(newContent, content, size); size *= 2; delete[] content; content = newContent; } content[index] = c; index++; } content[index] = '\0'; index++; in.close(); return content; } return nullptr; } bool ShaderProgram::checkShaderErrors(const GLchar* name, GLuint shader) { bool returnValue = false; //cout << "compiling " << name << " shader ..." << endl; GLenum error = glGetError(); if(error) { cout << "compiling of " << name << " failed" << endl; cout << "error: " << glGetError() << endl; returnValue = true; } //else //{ // cout << "no error occured ..." << endl; //} GLint compiled[1]; glGetShaderiv(shader, GL_COMPILE_STATUS, compiled); if(compiled[0]) { //cout << name << " shader successfully compiled" << endl; } else { cout << "compiling of " << name << " failed:" << endl; GLchar buffer[512]; GLsizei bufferSize = 512; GLsizei charsUsed = 0; glGetShaderInfoLog(shader, bufferSize, &charsUsed, buffer); // glGetProgramInfoLog should be null terminated ... buffer[bufferSize - 1] = '\0'; cout << buffer << endl; returnValue = true; } return returnValue; } void ShaderProgram::compile(const GLchar* vertexPath, const GLchar* vertexData, const GLchar* fragmentPath, const GLchar* fragmentData) { vertexShader = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vertexShader, 1, &vertexData, nullptr); glCompileShader(vertexShader); if(checkShaderErrors(vertexPath, vertexShader)) { return; } fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragmentShader, 1, &fragmentData, nullptr); glCompileShader(fragmentShader); if(checkShaderErrors(fragmentPath, fragmentShader)) { return; } program = glCreateProgram(); glAttachShader(program, vertexShader); glAttachShader(program, fragmentShader); glLinkProgram(program); //cout << "linking shaders to program ..." << endl; GLenum error = glGetError(); if(error) { cout << "linking of " << vertexPath << " and " << fragmentPath << " failed" << endl; cout << "error: " << glGetError() << endl; return; } //else //{ // cout << "no error occured ..." << endl; //} GLint compiled[1]; glGetProgramiv(program, GL_LINK_STATUS, compiled); if(compiled[0]) { //cout << "shaders successfully linked" << endl; } else { cout << "linking of " << vertexPath << " and " << fragmentPath << " failed:" << endl; GLchar buffer[512]; GLsizei bufferSize = 512; GLsizei charsUsed = 0; glGetProgramInfoLog(program, bufferSize, &charsUsed, buffer); // glGetProgramInfoLog should be null terminated ... buffer[bufferSize - 1] = '\0'; cout << buffer << endl; return; } valid = true; }