#include "../../../include/RenderBackend/OpenGL/ShaderProgram.hpp" #include "../../../include/RenderBackend/OpenGL/opengl.hpp" #include "../../../include/RenderBackend/OpenGL/CompiledShader.hpp" using namespace std; namespace amalgine { ShaderProgramUsedBeforeBuilt::ShaderProgramUsedBeforeBuilt() : runtime_error("Shader program was used before it was built") { } ShaderProgram::ShaderProgram() : built(false) { shaderProgramId = glCreateProgram(); } ShaderProgram::~ShaderProgram() { GLint numAttachedShaders; glGetProgramiv(shaderProgramId, GL_ATTACHED_SHADERS, &numAttachedShaders); GLuint *attachedShaders = new GLuint[numAttachedShaders]; glGetAttachedShaders(shaderProgramId, numAttachedShaders, nullptr, attachedShaders); for(int i = 0; i < numAttachedShaders; ++i) { GLuint attachedShaderId = attachedShaders[i]; glDetachShader(shaderProgramId, attachedShaderId); } glDeleteProgram(shaderProgramId); } // TODO: Before adding shader to program, check if it has already been added bool ShaderProgram::setVertexShader(CompiledVertexShader *vertexShader) { if(!vertexShader) return false; // TODO: Do not allow adding shader if the program has already been built glAttachShader(shaderProgramId, vertexShader->getShaderId()); return true; } bool ShaderProgram::setPixelShader(CompiledPixelShader *pixelShader) { if(!pixelShader) return false; // TODO: Do not allow adding shader if the program has already been built glAttachShader(shaderProgramId, pixelShader->getShaderId()); const auto &pixelAttributes = pixelShader->getPixelAttributes(); for(const auto &pixelAttribute : pixelAttributes) { const string &attributeName = pixelAttribute.first; i32 attributeLocation = pixelAttribute.second; glBindFragDataLocation(shaderProgramId, attributeLocation, attributeName.c_str()); } return true; } Result ShaderProgram::build() { if(built) return Result::Err("Shader program already built"); glLinkProgram(shaderProgramId); built = true; return Result::Ok(true); } void ShaderProgram::use() { if(built) { glUseProgram(shaderProgramId); } else { throw ShaderProgramUsedBeforeBuilt(); } } }