#ifndef SHADER_CPP #define SHADER_CPP #include #include #include "shader.hpp" #include "misc.hpp" unsigned int Shader::linkShaderObjectsShaderProgram(const unsigned int vertexShaders, const unsigned int fragmentShader) const { // link shader objects into shader program // will store shader program id // creates program const unsigned int shaderProgram = glCreateProgram(); // attachShaders glAttachShader(shaderProgram, vertexShaders); glAttachShader(shaderProgram, fragmentShader); // link shaders glLinkProgram(shaderProgram); if (!shaderSuccessful(shaderProgram, false)) return 0; // delete shaders (they are linked into shaderProgram and we do not need them anymore) glDeleteShader(vertexShaders); glDeleteShader(fragmentShader); if (shaderProgram == 0) print("Shader Program Linking Failed"); return shaderProgram; } unsigned int Shader::compileShader(const GLenum shaderType, const char *shaderSource) const { // we create vertex shader and assign its id to shader variable const unsigned int shaderID = glCreateShader(shaderType); // attach shader source code to shader object // from left: shader object to compile, how many strings as source code, actual source code (we leave the 4th as NULL) glShaderSource(shaderID, 1, &shaderSource, NULL); // compile shader glCompileShader(shaderID); if (!shaderSuccessful(shaderID, true)) return 0; return shaderID; } const char* Shader::getSourceCode(const std::string_view sourcePath) const { // 1. retrieve the vertex/fragment source code from filePath std::string sourceCode; std::ifstream sourceFile; // ensure ifstream objects can throw exceptions: sourceFile.exceptions (std::ifstream::failbit | std::ifstream::badbit); try { sourceCode = fileBufferToString(sourcePath, sourceFile); } // https://stackoverflow.com/a/62030396 catch(std::ifstream::failure const& e) { std::cerr << "ERROR::SHADER::FILE_NOT_SUCCESSFULLY_READ for sourcePath: " << sourcePath << std::endl; } const char* cSourceCode = sourceCode.c_str(); return cSourceCode; } void Shader::use() { glUseProgram(ID); } void Shader::setBool(const std::string_view &name, const bool value) const { const int vertexColorLocation = glGetUniformLocation(ID, name.c_str()); if(vertexColorLocation != -1) { glUniform1i(vertexColorLocation, (int)value); } } void Shader::setInt(const std::string_view &name, const int value) const { const int vertexColorLocation = glGetUniformLocation(ID, name.c_str()); if(vertexColorLocation != -1) { glUniform1i(vertexColorLocation, value); } } void Shader::setFloat(const std::string_view &name, const float value) const { const int vertexColorLocation = glGetUniformLocation(ID, name.c_str()); if(vertexColorLocation != -1) { glUniform1f(vertexColorLocation, value); } } Shader::Shader(const std::string_view vertexPath, const std::string_view fragmentPath) { const char* vShaderCode = getSourceCode(vertexPath); const char* fShaderCode = getSourceCode(fragmentPath); const int vectorShaderID = compileShader(GL_VERTEX_SHADER, vShaderCode); const int fragmentShaderID = compileShader(GL_FRAGMENT_SHADER, fShaderCode); ID = linkShaderObjectsShaderProgram(vectorShaderID, fragmentShaderID); } #endif // SHADER_CPP