/* * ShaderProgram.cpp * * Created on: 31 janv. 2020 * Author: simon */ #include "render/shaders/ShaderProgram.h" #include "misc/Log.h" #include "misc/Format.h" #include #include #include #include #ifdef __ANDROID__ #include #endif namespace td { namespace shader { ShaderProgram::ShaderProgram() : m_ProgramID(0), m_VertexShaderID(0), m_FragmentShaderID(0) { } ShaderProgram::~ShaderProgram() { CleanUp(); } void ShaderProgram::Start() const { glUseProgram(m_ProgramID); } void ShaderProgram::Stop() const { glUseProgram(0); } int ShaderProgram::GetUniformLocation(const std::string& uniformName) const { const int location = glGetUniformLocation(m_ProgramID, uniformName.c_str()); if (location == -1) { utils::LOGD(utils::format("Warning ! Uniform variable %s not found !", uniformName.c_str())); } return location; } void ShaderProgram::LoadFloat(unsigned int location, float value) const { glUniform1f(static_cast(location), value); } void ShaderProgram::LoadInt(unsigned int location, int value) const { glUniform1i(static_cast(location), value); } void ShaderProgram::LoadVector(unsigned int location, const Vec2f& vector) const { glUniform2f(static_cast(location), vector.x, vector.y); } void ShaderProgram::LoadVector(unsigned int location, const Vec3f& vector) const { glUniform3f(static_cast(location), vector.x, vector.y, vector.z); } void ShaderProgram::LoadBoolean(unsigned int location, bool value) const { glUniform1i(static_cast(location), value); } void ShaderProgram::LoadMat4(unsigned int location, const Mat4f& mat) const { glUniformMatrix4fv(static_cast(location), 1, false, reinterpret_cast(&mat)); } void ShaderProgram::CleanUp() const { Stop(); glDetachShader(m_ProgramID, m_VertexShaderID); glDetachShader(m_ProgramID, m_FragmentShaderID); glDeleteShader(m_VertexShaderID); glDeleteShader(m_FragmentShaderID); glDeleteProgram(m_ProgramID); } void ShaderProgram::LoadProgramFile(const std::string& vertexFile, const std::string& fragmentFile) { m_VertexShaderID = static_cast(LoadShaderFromFile(vertexFile, GL_VERTEX_SHADER)); m_FragmentShaderID = static_cast(LoadShaderFromFile(fragmentFile, GL_FRAGMENT_SHADER)); m_ProgramID = glCreateProgram(); glAttachShader(m_ProgramID, m_VertexShaderID); glAttachShader(m_ProgramID, m_FragmentShaderID); glLinkProgram(m_ProgramID); glValidateProgram(m_ProgramID); GetAllUniformLocation(); } void ShaderProgram::LoadProgram(const std::string& vertexSource, const std::string& fragmentSource) { m_VertexShaderID = static_cast(LoadShader(vertexSource, GL_VERTEX_SHADER)); m_FragmentShaderID = static_cast(LoadShader(fragmentSource, GL_FRAGMENT_SHADER)); m_ProgramID = glCreateProgram(); glAttachShader(m_ProgramID, m_VertexShaderID); glAttachShader(m_ProgramID, m_FragmentShaderID); glLinkProgram(m_ProgramID); glValidateProgram(m_ProgramID); GetAllUniformLocation(); } unsigned int ShaderProgram::LoadShader(const std::string& source, GLenum type) { unsigned int shaderID = glCreateShader(type); const char* c_str = source.c_str(); int* null = 0; glShaderSource(shaderID, 1, &c_str, null); // @suppress("Function cannot be resolved") glCompileShader(shaderID); GLint compilesuccessful; glGetShaderiv(shaderID, GL_COMPILE_STATUS, &compilesuccessful); if (compilesuccessful == false) { GLsizei size; glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &size); std::vector shaderError(static_cast(size)); glGetShaderInfoLog(shaderID, size, &size, shaderError.data()); utils::LOGE("Could not compile shader !"); utils::LOGE(shaderError.data()); utils::LOGD(utils::format("\nShader source : \n" "------------------------------------------------------------------------------------------------------------------------------------\n" "%s\n" "------------------------------------------------------------------------------------------------------------------------------------\n" , source.c_str())); } return shaderID; } unsigned int ShaderProgram::LoadShaderFromFile(const std::string& file, GLenum type) { std::stringstream stream; std::ifstream fileStream(file); if (fileStream) { stream << fileStream.rdbuf(); } else { return 0; } return LoadShader(stream.str(), type); } } // namespace shader } // namespace td