15 void gl_error(std::string msg) {
16 const GLubyte *errBegin = gluErrorString(glGetError());
17 if (errBegin && *errBegin != '\0') {
18 const GLubyte *errEnd = errBegin;
19 while (*errEnd != '\0') {
23 msg.append(errBegin, errEnd);
25 throw std::runtime_error(msg);
32 Shader::Shader(GLenum type)
33 : handle(glCreateShader(type)) {
35 gl_error("glCreateShader");
41 glDeleteShader(handle);
45 Shader::Shader(Shader &&other)
46 : handle(other.handle) {
50 Shader &Shader::operator =(Shader &&other) {
51 std::swap(handle, other.handle);
56 void Shader::Source(const GLchar *src) {
57 const GLchar* src_arr[] = { src };
58 glShaderSource(handle, 1, src_arr, nullptr);
61 void Shader::Compile() {
62 glCompileShader(handle);
65 bool Shader::Compiled() const {
66 GLint compiled = GL_FALSE;
67 glGetShaderiv(handle, GL_COMPILE_STATUS, &compiled);
68 return compiled == GL_TRUE;
71 void Shader::Log(std::ostream &out) const {
72 int log_len = 0, max_len = 0;
73 glGetShaderiv(handle, GL_INFO_LOG_LENGTH, &max_len);
74 std::unique_ptr<char[]> log(new char[max_len]);
75 glGetShaderInfoLog(handle, max_len, &log_len, log.get());
76 out.write(log.get(), log_len);
80 void Shader::AttachToProgram(GLuint id) const {
81 glAttachShader(id, handle);
86 : handle(glCreateProgram()) {
88 gl_error("glCreateProgram");
94 glDeleteProgram(handle);
99 const Shader &Program::LoadShader(GLenum type, const GLchar *src) {
100 shaders.emplace_back(type);
101 Shader &shader = shaders.back();
104 if (!shader.Compiled()) {
105 shader.Log(std::cerr);
106 throw std::runtime_error("compile shader");
112 void Program::Attach(Shader &shader) {
113 shader.AttachToProgram(handle);
116 void Program::Link() {
117 glLinkProgram(handle);
120 bool Program::Linked() const {
121 GLint linked = GL_FALSE;
122 glGetProgramiv(handle, GL_LINK_STATUS, &linked);
123 return linked == GL_TRUE;
126 void Program::Log(std::ostream &out) const {
127 int log_len = 0, max_len = 0;
128 glGetProgramiv(handle, GL_INFO_LOG_LENGTH, &max_len);
129 std::unique_ptr<char[]> log(new char[max_len]);
130 glGetProgramInfoLog(handle, max_len, &log_len, log.get());
131 out.write(log.get(), log_len);
135 GLint Program::AttributeLocation(const GLchar *name) const {
136 return glGetAttribLocation(handle, name);
139 GLint Program::UniformLocation(const GLchar *name) const {
140 return glGetUniformLocation(handle, name);
144 DirectionalLighting::DirectionalLighting()
146 , light_direction(1.0f, 3.0f, 2.0f)
147 , light_color(0.9f, 0.9f, 0.9f)
152 , light_direction_handle(0)
153 , light_color_handle(0)
154 , fog_density_handle(0) {
157 "#version 330 core\n"
158 "layout(location = 0) in vec3 vtx_position;\n"
159 "layout(location = 1) in vec3 vtx_color;\n"
160 "layout(location = 2) in vec3 vtx_normal;\n"
163 "uniform mat4 MVP;\n"
164 "out vec3 frag_color;\n"
165 "out vec3 vtx_viewspace;\n"
168 "gl_Position = MVP * vec4(vtx_position, 1);\n"
169 "vtx_viewspace = (MV * vec4(vtx_position, 1)).xyz;\n"
170 "normal = (M * vec4(vtx_normal, 0)).xyz;\n"
171 "frag_color = vtx_color;\n"
176 "#version 330 core\n"
177 "in vec3 frag_color;\n"
178 "in vec3 vtx_viewspace;\n"
180 "uniform vec3 light_direction;\n"
181 "uniform vec3 light_color;\n"
182 "uniform float fog_density;\n"
185 "vec3 ambient = vec3(0.1, 0.1, 0.1) * frag_color;\n"
186 // this should be the same as the clear color, otherwise looks really weird
187 "vec3 fog_color = vec3(0, 0, 0);\n"
188 "float e = 2.718281828;\n"
189 "vec3 n = normalize(normal);\n"
190 "vec3 l = normalize(light_direction);\n"
191 "float cos_theta = clamp(dot(n, l), 0, 1);\n"
192 "vec3 reflect_color = ambient + frag_color * light_color * cos_theta;\n"
193 "float value = pow(e, -pow(fog_density * length(vtx_viewspace), 5));"
194 "color = mix(fog_color, reflect_color, value);\n"
198 if (!program.Linked()) {
199 program.Log(std::cerr);
200 throw std::runtime_error("link program");
203 m_handle = program.UniformLocation("M");
204 mv_handle = program.UniformLocation("MV");
205 mvp_handle = program.UniformLocation("MVP");
206 light_direction_handle = program.UniformLocation("light_direction");
207 light_color_handle = program.UniformLocation("light_color");
208 fog_density_handle = program.UniformLocation("fog_density");
212 void DirectionalLighting::Activate() {
213 GLContext::EnableDepthTest();
214 GLContext::EnableBackfaceCulling();
217 glUniform3f(light_direction_handle, light_direction.x, light_direction.y, light_direction.z);
218 glUniform3f(light_color_handle, light_color.x, light_color.y, light_color.z);
221 void DirectionalLighting::SetM(const glm::mat4 &m) {
222 glm::mat4 mv(view * m);
223 glm::mat4 mvp(vp * m);
224 glUniformMatrix4fv(m_handle, 1, GL_FALSE, &m[0][0]);
225 glUniformMatrix4fv(mv_handle, 1, GL_FALSE, &mv[0][0]);
226 glUniformMatrix4fv(mvp_handle, 1, GL_FALSE, &mvp[0][0]);
229 void DirectionalLighting::SetLightDirection(const glm::vec3 &dir) {
230 light_direction = -dir;
231 glUniform3f(light_direction_handle, light_direction.x, light_direction.y, light_direction.z);
234 void DirectionalLighting::SetFogDensity(float f) {
236 glUniform1f(fog_density_handle, fog_density);
239 void DirectionalLighting::SetProjection(const glm::mat4 &p) {
244 void DirectionalLighting::SetView(const glm::mat4 &v) {
249 void DirectionalLighting::SetVP(const glm::mat4 &v, const glm::mat4 &p) {
255 void DirectionalLighting::SetMVP(const glm::mat4 &m, const glm::mat4 &v, const glm::mat4 &p) {
261 BlockLighting::BlockLighting()
266 , fog_density_handle(0) {
269 "#version 330 core\n"
270 "layout(location = 0) in vec3 vtx_position;\n"
271 "layout(location = 1) in vec3 vtx_color;\n"
272 "layout(location = 2) in float vtx_light;\n"
274 "uniform mat4 MVP;\n"
275 "out vec3 frag_color;\n"
276 "out vec3 vtx_viewspace;\n"
277 "out float frag_light;\n"
279 "gl_Position = MVP * vec4(vtx_position, 1);\n"
280 "frag_color = vtx_color;\n"
281 "vtx_viewspace = (MV * vec4(vtx_position, 1)).xyz;\n"
282 "frag_light = vtx_light;\n"
287 "#version 330 core\n"
288 "in vec3 frag_color;\n"
289 "in vec3 vtx_viewspace;\n"
290 "in float frag_light;\n"
291 "uniform float fog_density;\n"
294 "vec3 ambient = vec3(0.1, 0.1, 0.1) * frag_color;\n"
295 "float light_power = clamp(pow(0.8, 15 - frag_light), 0, 1);\n"
296 "vec3 fog_color = vec3(0, 0, 0);\n"
297 "float e = 2.718281828;\n"
298 //"vec3 reflect_color = ambient + frag_color * light_power;\n"
299 "vec3 reflect_color = frag_color * light_power;\n"
300 "float value = pow(e, -pow(fog_density * length(vtx_viewspace), 5));"
301 "color = mix(fog_color, reflect_color, value);\n"
305 if (!program.Linked()) {
306 program.Log(std::cerr);
307 throw std::runtime_error("link program");
310 mv_handle = program.UniformLocation("MV");
311 mvp_handle = program.UniformLocation("MVP");
312 fog_density_handle = program.UniformLocation("fog_density");
316 void BlockLighting::Activate() {
317 GLContext::EnableDepthTest();
318 GLContext::EnableBackfaceCulling();
322 void BlockLighting::SetM(const glm::mat4 &m) {
323 glm::mat4 mv(view * m);
324 glm::mat4 mvp(vp * m);
325 glUniformMatrix4fv(mv_handle, 1, GL_FALSE, &mv[0][0]);
326 glUniformMatrix4fv(mvp_handle, 1, GL_FALSE, &mvp[0][0]);
329 void BlockLighting::SetFogDensity(float f) {
331 glUniform1f(fog_density_handle, fog_density);
334 void BlockLighting::SetProjection(const glm::mat4 &p) {
339 void BlockLighting::SetView(const glm::mat4 &v) {
344 void BlockLighting::SetVP(const glm::mat4 &v, const glm::mat4 &p) {
350 void BlockLighting::SetMVP(const glm::mat4 &m, const glm::mat4 &v, const glm::mat4 &p) {