]> git.localhorst.tv Git - blank.git/blob - src/shader.cpp
add SDL2_image library
[blank.git] / src / shader.cpp
1 #include "shader.hpp"
2
3 #include <algorithm>
4 #include <iostream>
5 #include <memory>
6 #include <ostream>
7 #include <stdexcept>
8 #include <string>
9
10
11 namespace {
12
13 void gl_error(std::string msg) {
14         const GLubyte *errBegin = gluErrorString(glGetError());
15         if (errBegin && *errBegin != '\0') {
16                 const GLubyte *errEnd = errBegin;
17                 while (*errEnd != '\0') {
18                         ++errEnd;
19                 }
20                 msg += ": ";
21                 msg.append(errBegin, errEnd);
22         }
23         throw std::runtime_error(msg);
24 }
25
26 }
27
28 namespace blank {
29
30 Shader::Shader(GLenum type)
31 : handle(glCreateShader(type)) {
32         if (handle == 0) {
33                 gl_error("glCreateShader");
34         }
35 }
36
37 Shader::~Shader() {
38         if (handle != 0) {
39                 glDeleteShader(handle);
40         }
41 }
42
43 Shader::Shader(Shader &&other)
44 : handle(other.handle) {
45         other.handle = 0;
46 }
47
48 Shader &Shader::operator =(Shader &&other) {
49         std::swap(handle, other.handle);
50         return *this;
51 }
52
53
54 void Shader::Source(const GLchar *src) {
55         const GLchar* src_arr[] = { src };
56         glShaderSource(handle, 1, src_arr, nullptr);
57 }
58
59 void Shader::Compile() {
60         glCompileShader(handle);
61 }
62
63 bool Shader::Compiled() const {
64         GLint compiled = GL_FALSE;
65         glGetShaderiv(handle, GL_COMPILE_STATUS, &compiled);
66         return compiled == GL_TRUE;
67 }
68
69 void Shader::Log(std::ostream &out) const {
70         int log_len = 0, max_len = 0;
71         glGetShaderiv(handle, GL_INFO_LOG_LENGTH, &max_len);
72         std::unique_ptr<char[]> log(new char[max_len]);
73         glGetShaderInfoLog(handle, max_len, &log_len, log.get());
74         out.write(log.get(), log_len);
75 }
76
77
78 void Shader::AttachToProgram(GLuint id) const {
79         glAttachShader(id, handle);
80 }
81
82
83 Program::Program()
84 : handle(glCreateProgram()) {
85         if (handle == 0) {
86                 gl_error("glCreateProgram");
87         }
88 }
89
90 Program::~Program() {
91         if (handle != 0) {
92                 glDeleteProgram(handle);
93         }
94 }
95
96
97 const Shader &Program::LoadShader(GLenum type, const GLchar *src) {
98         shaders.emplace_back(type);
99         Shader &shader = shaders.back();
100         shader.Source(src);
101         shader.Compile();
102         if (!shader.Compiled()) {
103                 shader.Log(std::cerr);
104                 throw std::runtime_error("compile shader");
105         }
106         Attach(shader);
107         return shader;
108 }
109
110 void Program::Attach(Shader &shader) {
111         shader.AttachToProgram(handle);
112 }
113
114 void Program::Link() {
115         glLinkProgram(handle);
116 }
117
118 bool Program::Linked() const {
119         GLint linked = GL_FALSE;
120         glGetProgramiv(handle, GL_LINK_STATUS, &linked);
121         return linked == GL_TRUE;
122 }
123
124 void Program::Log(std::ostream &out) const {
125         int log_len = 0, max_len = 0;
126         glGetProgramiv(handle, GL_INFO_LOG_LENGTH, &max_len);
127         std::unique_ptr<char[]> log(new char[max_len]);
128         glGetProgramInfoLog(handle, max_len, &log_len, log.get());
129         out.write(log.get(), log_len);
130 }
131
132
133 GLint Program::UniformLocation(const GLchar *name) const {
134         return glGetUniformLocation(handle, name);
135 }
136
137 }