]> git.localhorst.tv Git - tacos.git/blobdiff - src/graphics/shader.cpp
the usual suspects
[tacos.git] / src / graphics / shader.cpp
diff --git a/src/graphics/shader.cpp b/src/graphics/shader.cpp
new file mode 100644 (file)
index 0000000..b82a6c8
--- /dev/null
@@ -0,0 +1,122 @@
+#include "shader.hpp"
+
+#include "../app/error.hpp"
+
+#include <algorithm>
+#include <memory>
+#include <GL/glew.h>
+#include <glm/gtc/type_ptr.hpp>
+
+
+namespace tacos {
+
+Shader Shader::Vertex(const GLchar *source) {
+       return Shader(GL_VERTEX_SHADER, source);
+}
+
+Shader Shader::Fragment(const GLchar *source) {
+       return Shader(GL_FRAGMENT_SHADER, source);
+}
+
+Shader::Shader(GLenum type, const GLchar *source)
+: shader(glCreateShader(type)) {
+       if (shader == 0) {
+               throw GLError("glCreateShader");
+       }
+       const GLchar *sources[] = { source };
+       glShaderSource(shader, 1, sources, nullptr);
+       glCompileShader(shader);
+       GLint compiled = GL_FALSE;
+       glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
+       if (compiled != GL_TRUE) {
+               int log_length = 0, max_length = 0;
+               glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &max_length);
+               ++max_length;
+               std::unique_ptr<char[]> log(new char[max_length]);
+               glGetShaderInfoLog(shader, max_length, &log_length, log.get());
+               log[log_length] = '\0';
+               glDeleteShader(shader);
+               throw GLCompileError("glCompileShader", log.get());
+       }
+}
+
+Shader::~Shader() noexcept {
+       if (shader != 0) {
+               glDeleteShader(shader);
+       }
+}
+
+Shader::Shader(Shader &&other) noexcept
+: shader(other.shader) {
+       other.shader = 0;
+}
+
+Shader &Shader::operator =(Shader &&other) noexcept {
+       std::swap(shader, other.shader);
+       return *this;
+}
+
+
+Program::Program()
+: program(glCreateProgram()) {
+       if (program == 0) {
+               throw GLError("glCreateProgram");
+       }
+}
+
+Program::~Program() noexcept {
+       glDeleteProgram(program);
+}
+
+void Program::Attach(const Shader &shader) noexcept {
+       glAttachShader(program, shader.shader);
+}
+
+void Program::Link() {
+       glLinkProgram(program);
+       GLint linked = GL_FALSE;
+       glGetProgramiv(program, GL_LINK_STATUS, &linked);
+       if (linked != GL_TRUE) {
+               int log_length = 0, max_length = 0;
+               glGetProgramiv(program, GL_INFO_LOG_LENGTH, &max_length);
+               ++max_length;
+               std::unique_ptr<char[]> log(new char[max_length]);
+               glGetProgramInfoLog(program, max_length, &log_length, log.get());
+               log[log_length] = '\0';
+               throw GLCompileError("glLinkProgram", log.get());
+       }
+}
+
+void Program::Use() noexcept {
+       glUseProgram(program);
+}
+
+GLint Program::AttributeLocation(const GLchar *name) const noexcept {
+       return glGetAttribLocation(program, name);
+}
+
+GLint Program::UniformLocation(const GLchar *name) const noexcept {
+       return glGetUniformLocation(program, name);
+}
+
+void Program::Uniform(GLint loc, GLint val) noexcept {
+       glUniform1i(loc, val);
+}
+
+void Program::Uniform(GLint loc, float val) noexcept {
+       glUniform1f(loc, val);
+}
+
+void Program::Uniform(GLint loc, const glm::vec3 &val) noexcept {
+       glUniform3fv(loc, 1, glm::value_ptr(val));
+}
+
+void Program::Uniform(GLint loc, const glm::vec4 &val) noexcept {
+       glUniform4fv(loc, 1, glm::value_ptr(val));
+}
+
+void Program::Uniform(GLint loc, const glm::mat4 &val) noexcept {
+       glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(val));
+}
+
+}