#include "shader.h" #include static int setupShader(GLenum shaderType, const char *src) { GLuint shader = glCreateShader(shaderType); glShaderSource(shader, 1, &src, nullptr); glCompileShader(shader); int status; glGetShaderiv(shader, GL_COMPILE_STATUS, &status); if (status == GL_FALSE) { char buf[1024]; glGetShaderInfoLog(shader, sizeof buf, nullptr, buf); std::cerr << "Error: " << (shaderType == GL_VERTEX_SHADER ? "vertex" : "fragment") << " shader: compilation failed: " << buf << std::endl; } return shader; } Shader::Shader(const char *vertexSrc, const char *fragmentSrc, const char *geometrySrc) { GLuint vertex = setupShader(GL_VERTEX_SHADER, vertexSrc); GLuint fragment = setupShader(GL_FRAGMENT_SHADER, fragmentSrc); GLuint geometry; if (geometrySrc != nullptr) { geometry = setupShader(GL_GEOMETRY_SHADER, geometrySrc); } int status; m_program = glCreateProgram(); glAttachShader(m_program, vertex); glAttachShader(m_program, fragment); if (geometrySrc != nullptr) { glAttachShader(m_program, geometry); } glLinkProgram(m_program); glGetProgramiv(m_program, GL_LINK_STATUS, &status); if (status == GL_FALSE) { char buf[1024]; glGetProgramInfoLog(m_program, sizeof buf, nullptr, buf); std::cerr << "Error: shader linking failed: " << buf << std::endl; } if (geometrySrc != nullptr) { glDeleteShader(geometry); } glDeleteShader(fragment); glDeleteShader(vertex); } Shader::~Shader() { glDeleteProgram(m_program); } void Shader::use() const { glUseProgram(m_program); } void Shader::release() const { glUseProgram(0); } GLint Shader::uniformLocation(const char *name) const { return glGetUniformLocation(m_program, name); } void Shader::setUniform(GLint location, GLint value) const { glUniform1i(location, value); } void Shader::setUniform(GLint location, GLfloat value) const { glUniform1f(location, value); } void Shader::setUniform(GLint location, GLfloat mat[4][4]) const { // GL_FALSE for column-major glUniformMatrix4fv(location, 1, GL_FALSE, &mat[0][0]); } void Shader::setUniform1dArray(GLint location, const GLfloat *values, int count) const { glUniform1fv(location, count, values); } void Shader::setUniform2dArray(GLint location, const GLfloat *values, int count) const { glUniform2fv(location, count, values); } void Shader::setUniform3dArray(GLint location, const GLfloat *values, int count) const { glUniform3fv(location, count, values); } void Shader::setUniform(const char *name, GLint value) const { setUniform(uniformLocation(name), value); } void Shader::setUniform(const char *name, GLfloat value) const { setUniform(uniformLocation(name), value); } void Shader::setUniform1dArray(const char *name, const GLfloat *values, int count) const { setUniform1dArray(uniformLocation(name), values, count); } void Shader::setUniform2dArray(const char *name, const GLfloat *values, int count) const { setUniform2dArray(uniformLocation(name), values, count); } void Shader::setUniform3dArray(const char *name, const GLfloat *values, int count) const { setUniform3dArray(uniformLocation(name), values, count); } void Shader::setUniform(const char *name, GLfloat mat[4][4]) const { setUniform(uniformLocation(name), mat); }