#include #include #include "rendering/Shader.h" #include "wrapper/GL.h" Shader::Shader(const char* vertexPath, const char* fragmentPath, const char* geometryPath) : vertexShader(0), geometryShader(0), fragmentShader(0), program(0) { if(compile(vertexPath, vertexShader, GL::VERTEX_SHADER) || compile(fragmentPath, fragmentShader, GL::FRAGMENT_SHADER)) { return; } if(geometryPath != nullptr && compile(geometryPath, geometryShader, GL::GEOMETRY_SHADER)) { return; } program = GL::createProgram(); GL::attachShader(program, vertexShader); if(geometryPath != nullptr) { GL::attachShader(program, geometryShader); } GL::attachShader(program, fragmentShader); GL::linkProgram(program); if(GL::printError("cannot link")) { return; } if(GL::logLinkerError(program)) { clean(); return; } } Shader::~Shader() { clean(); } void Shader::clean() { GL::deleteShader(vertexShader); GL::deleteShader(geometryShader); GL::deleteShader(fragmentShader); GL::deleteProgram(program); program = 0; } bool Shader::compile(const char* path, GL::Shader& s, GL::ShaderType st) { std::cout << "shader: " << path << '\n'; List code; if(readFile(code, path)) { return true; } return compile(s, code, st); } bool Shader::readFile(List& code, const char* path) const { std::ifstream in; in.open(path); if(!in.good()) { std::cout << "cannot read file\n"; return true; } while(true) { int c = in.get(); if(c == EOF) { return false; } code.add(c); } return false; } bool Shader::hasError() const { return vertexShader == 0 || fragmentShader == 0 || program == 0; } bool Shader::compile(GL::Shader& s, const List& code, GL::ShaderType st) { s = GL::createShader(st); GL::compileShader(s, code.begin()); if(GL::printError("compile error")) { return true; } return GL::logCompileError(s); } void Shader::use() const { GL::useProgram(program); } void Shader::setMatrix(const char* name, const float* data) { GL::setMatrix(program, name, data); } void Shader::setInt(const char* name, int data) { GL::setInt(program, name, data); } void Shader::setFloat(const char* name, float data) { GL::setFloat(program, name, data); } void Shader::setVector(const char* name, const Vector2& v) { GL::set2Float(program, name, &(v[0])); } void Shader::setVector(const char* name, const Vector3& v) { GL::set3Float(program, name, &(v[0])); } void Shader::setVector(const char* name, const Vector4& v) { GL::set4Float(program, name, &(v[0])); }