aboutsummaryrefslogtreecommitdiff
path: root/shader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'shader.cpp')
-rw-r--r--shader.cpp137
1 files changed, 137 insertions, 0 deletions
diff --git a/shader.cpp b/shader.cpp
new file mode 100644
index 0000000..0a1268e
--- /dev/null
+++ b/shader.cpp
@@ -0,0 +1,137 @@
+#include "shader.h"
+
+#include <iostream>
+
+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);
+}