#include "../../../include/RenderBackend/OpenGL/ShaderProgram.hpp" #include "../../../include/RenderBackend/OpenGL/Shader.hpp" #include "../../../include/RenderBackend/OpenGL/opengl.hpp" using namespace std; namespace amalgine { ShaderProgram::ShaderProgram(u32 shader_program_id) : program_id(shader_program_id) { } ShaderProgram::~ShaderProgram() { GLint numAttachedShaders; glGetProgramiv(program_id, GL_ATTACHED_SHADERS, &numAttachedShaders); GLuint *attachedShaders = new GLuint[numAttachedShaders]; glGetAttachedShaders(program_id, numAttachedShaders, nullptr, attachedShaders); for(int i = 0; i < numAttachedShaders; ++i) { GLuint attachedShaderId = attachedShaders[i]; glDetachShader(program_id, attachedShaderId); } glDeleteProgram(program_id); delete []attachedShaders; } #if 0 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; } #endif // static Result> ShaderProgram::build(const std::vector &shaders) { u32 shader_program_id = glCreateProgram(); if(shader_program_id == 0) return Result>::Err("Failed to create shader program"); for(Shader *shader : shaders) { glAttachShader(shader_program_id, shader->id); } glLinkProgram(shader_program_id); std::unique_ptr shader_program; shader_program.reset(new ShaderProgram(shader_program_id)); return Result>::Ok(std::move(shader_program)); } Result ShaderProgram::get_uniform_by_name(const char *name) { GLint uniform_id = glGetUniformLocation(program_id, name); if(uniform_id == -1) return Result::Err(std::string("Uniform with name ") + name + " was not found"); Uniform uniform(uniform_id, program_id); return Result::Ok(std::move(uniform)); } int ShaderProgram::set_input_data(const char *name, const DeviceMemory &data) { GLint attrib_location = glGetAttribLocation(program_id, name); if(attrib_location == -1) { fprintf(stderr, "No such attribute in shader: %s\n", name); return -1; } data.use(); glEnableVertexAttribArray(attrib_location); switch(data.get_type()) { case DeviceMemoryType::NONE: return -1; case DeviceMemoryType::VEC2: { glVertexAttribPointer(attrib_location, 2, GL_FLOAT, GL_FALSE, 0, 0); break; } case DeviceMemoryType::VEC3: { glVertexAttribPointer(attrib_location, 3, GL_FLOAT, GL_FALSE, 0, 0); break; } } return 0; } void ShaderProgram::use() { glUseProgram(program_id); } }