#include "ShaderProgram.h" #include <fstream> #include <cstring> ShaderProgram::ShaderProgram() { } ShaderProgram::~ShaderProgram() { if(vertexShader != 0) { glDeleteShader(vertexShader); } if(fragmentShader != 0) { glDeleteShader(fragmentShader); } if(program != 0) { glDeleteProgram(program); } } bool ShaderProgram::isValid() { return valid; } GLuint ShaderProgram::getProgram() { 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 << "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 << name << "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 << "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 shaders 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; }