// Copyright (c) 2022 Dominic Masters // // This software is released under the MIT License. // https://opensource.org/licenses/MIT #include "ShaderProgram.hpp" using namespace Dawn; void ShaderProgram::compileShader( std::map attributeLocations, std::string vertexShader, std::string fragmentShader ) { GLint isSuccess; int32_t maxLength; char error[1024]; // Load the vertex shader first this->shaderVertex = glCreateShader(GL_VERTEX_SHADER); auto vertShaderC = vertexShader.c_str(); glShaderSource(this->shaderVertex, 1, &vertShaderC, 0); glCompileShader(this->shaderVertex); // Validate glGetShaderiv(this->shaderVertex, GL_COMPILE_STATUS, &isSuccess); if(!isSuccess) { glGetShaderiv(this->shaderVertex, GL_INFO_LOG_LENGTH, &maxLength); glGetShaderInfoLog(this->shaderVertex, maxLength, &maxLength, error); debugMessage("Error compiling vert shader"); debugMessage(error); throw error; } // Now load the Frag shader this->shaderFrag = glCreateShader(GL_FRAGMENT_SHADER); auto fragShaderC = fragmentShader.c_str(); glShaderSource(this->shaderFrag, 1, &fragShaderC, 0); glCompileShader(this->shaderFrag); glGetShaderiv(this->shaderFrag, GL_COMPILE_STATUS, &isSuccess); if(!isSuccess) { glGetShaderiv(this->shaderFrag, GL_INFO_LOG_LENGTH, &maxLength); glGetShaderInfoLog(this->shaderFrag, maxLength, &maxLength, error); glDeleteShader(this->shaderVertex); debugMessage("Error compiling frag shader"); debugMessage(error); throw error; } // Now create the shader program. this->shaderProgram = glCreateProgram(); glAttachShader(this->shaderProgram, this->shaderVertex); glAttachShader(this->shaderProgram, this->shaderFrag); // Now parse out the variables. #if DAWN_OPENGL_HLSL auto itAttr = attributeLocations.begin(); while(itAttr != attributeLocations.end()) { this->bindAttributeLocation(itAttr->first, itAttr->second); ++itAttr; } #endif //Bind, Verify & Use the shader program glLinkProgram(this->shaderProgram); glGetProgramiv(this->shaderProgram, GL_LINK_STATUS, &isSuccess); if(!isSuccess) { glGetProgramiv(this->shaderProgram, GL_INFO_LOG_LENGTH, &maxLength); glGetProgramInfoLog(this->shaderProgram, maxLength, &maxLength, error); glDeleteShader(this->shaderVertex); glDeleteShader(this->shaderFrag); debugMessage("Error compiling shader program"); debugMessage(error); throw error; } } void ShaderProgram::bindAttributeLocation(std::string name, int32_t location) { if(this->shaderProgram == -1) throw "Shader has not yet been compiled"; glBindAttribLocation(this->shaderProgram, location, name.c_str()); } void ShaderProgram::setTexture(shaderparameter_t param, textureslot_t slot) { glUniform1i(param, slot); } shaderparameter_t ShaderProgram::getParameterByName(std::string name) { return glGetUniformLocation(this->shaderProgram, name.c_str()); } shaderbufferlocation_t ShaderProgram::getBufferLocationByName(std::string name) { return glGetUniformBlockIndex(this->shaderProgram, name.c_str()); } void ShaderProgram::setParameterBuffer(shaderbufferlocation_t location, shaderbufferslot_t slot) { glUniformBlockBinding(this->shaderProgram, location, slot); } void ShaderProgram::setMatrix(shaderparameter_t uniform, glm::mat4 matrix) { glUniformMatrix4fv(uniform, 1, GL_FALSE, glm::value_ptr(matrix)); } void ShaderProgram::setBoolean(shaderparameter_t uni, bool value) { glUniform1i(uni, value); } void ShaderProgram::setColor(shaderparameter_t uniform, struct Color color) { auto precise = color.precision(); glUniform4f(uniform, precise.r, precise.g, precise.b, precise.a); } void ShaderProgram::setVector3(shaderparameter_t uniform, glm::vec3 vector) { glUniform3f(uniform, vector.x, vector.y, vector.z); } void ShaderProgram::setFloat(shaderparameter_t param, float_t value) { glUniform1f(param, value); } void ShaderProgram::bind() { if(this->shaderProgram == -1) throw "Shader has not yet been compiled"; glUseProgram(this->shaderProgram); } ShaderProgram::~ShaderProgram() { if(this->shaderProgram != -1) glDeleteProgram(this->shaderProgram); if(this->shaderVertex != -1) glDeleteShader(this->shaderVertex); if(this->shaderFrag != -1) glDeleteShader(this->shaderFrag); }