1 #include "PlanetSurface.hpp"
4 #include "SunSurface.hpp"
6 #include "ArrayTexture.hpp"
7 #include "../app/init.hpp"
15 #include <glm/gtc/type_ptr.hpp>
20 void gl_error(std::string msg) {
21 const GLubyte *errBegin = gluErrorString(glGetError());
22 if (errBegin && *errBegin != '\0') {
23 const GLubyte *errEnd = errBegin;
24 while (*errEnd != '\0') {
28 msg.append(errBegin, errEnd);
30 throw std::runtime_error(msg);
38 Shader::Shader(GLenum type)
39 : handle(glCreateShader(type)) {
41 gl_error("glCreateShader");
47 glDeleteShader(handle);
51 Shader::Shader(Shader &&other) noexcept
52 : handle(other.handle) {
56 Shader &Shader::operator =(Shader &&other) noexcept {
57 std::swap(handle, other.handle);
62 void Shader::Source(const GLchar *src) noexcept {
63 const GLchar* src_arr[] = { src };
64 glShaderSource(handle, 1, src_arr, nullptr);
67 void Shader::Compile() noexcept {
68 glCompileShader(handle);
71 bool Shader::Compiled() const noexcept {
72 GLint compiled = GL_FALSE;
73 glGetShaderiv(handle, GL_COMPILE_STATUS, &compiled);
74 return compiled == GL_TRUE;
77 void Shader::Log(std::ostream &out) const {
78 int log_len = 0, max_len = 0;
79 glGetShaderiv(handle, GL_INFO_LOG_LENGTH, &max_len);
80 std::unique_ptr<char[]> log(new char[max_len]);
81 glGetShaderInfoLog(handle, max_len, &log_len, log.get());
82 out.write(log.get(), log_len);
86 void Shader::AttachToProgram(GLuint id) const noexcept {
87 glAttachShader(id, handle);
92 : handle(glCreateProgram()) {
94 gl_error("glCreateProgram");
100 glDeleteProgram(handle);
105 const Shader &Program::LoadShader(GLenum type, const GLchar *src) {
106 shaders.emplace_back(type);
107 Shader &shader = shaders.back();
110 if (!shader.Compiled()) {
111 shader.Log(std::cerr);
112 throw std::runtime_error("compile shader");
118 void Program::Attach(Shader &shader) noexcept {
119 shader.AttachToProgram(handle);
122 void Program::Link() noexcept {
123 glLinkProgram(handle);
126 bool Program::Linked() const noexcept {
127 GLint linked = GL_FALSE;
128 glGetProgramiv(handle, GL_LINK_STATUS, &linked);
129 return linked == GL_TRUE;
132 void Program::Log(std::ostream &out) const {
133 int log_len = 0, max_len = 0;
134 glGetProgramiv(handle, GL_INFO_LOG_LENGTH, &max_len);
135 std::unique_ptr<char[]> log(new char[max_len]);
136 glGetProgramInfoLog(handle, max_len, &log_len, log.get());
137 out.write(log.get(), log_len);
141 GLint Program::AttributeLocation(const GLchar *name) const noexcept {
142 return glGetAttribLocation(handle, name);
145 GLint Program::UniformLocation(const GLchar *name) const noexcept {
146 return glGetUniformLocation(handle, name);
150 void Program::Uniform(GLint loc, GLint val) noexcept {
151 glUniform1i(loc, val);
154 void Program::Uniform(GLint loc, float val) noexcept {
155 glUniform1f(loc, val);
158 void Program::Uniform(GLint loc, const glm::vec3 &val) noexcept {
159 glUniform3fv(loc, 1, glm::value_ptr(val));
162 void Program::Uniform(GLint loc, const glm::vec4 &val) noexcept {
163 glUniform4fv(loc, 1, glm::value_ptr(val));
166 void Program::Uniform(GLint loc, const glm::mat4 &val) noexcept {
167 glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(val));
171 PlanetSurface::PlanetSurface()
175 "#version 330 core\n"
177 "layout(location = 0) in vec3 vtx_position;\n"
178 "layout(location = 1) in vec3 vtx_tex_uv;\n"
182 "uniform mat4 MVP;\n"
184 "out vec3 frag_tex_uv;\n"
185 "out vec3 vtx_viewspace;\n"
188 "gl_Position = MVP * vec4(vtx_position, 1);\n"
189 "vtx_viewspace = (MV * vec4(vtx_position, 1)).xyz;\n"
190 "frag_tex_uv = vtx_tex_uv;\n"
195 "#version 330 core\n"
197 "struct LightSource {\n"
203 "in vec3 vtx_viewspace;\n"
204 "in vec3 frag_tex_uv;\n"
206 "uniform sampler2DArray tex_sampler;\n"
207 "uniform vec3 normal;\n"
208 "uniform LightSource light;\n"
213 "vec3 tex_color = texture(tex_sampler, frag_tex_uv).rgb;\n"
214 "vec3 to_light = light.position - vtx_viewspace;\n"
215 "float distance = length(to_light);\n"
216 "vec3 light_dir = normalize(to_light);\n"
217 "float attenuation = light.strength / (distance * distance);\n"
218 "vec3 ambient = tex_color * vec3(0.01, 0.01, 0.01);\n"
219 "vec3 diffuse = attenuation * max(0.0, dot(normal, light_dir)) * light.color * tex_color;\n"
220 "vec3 view_dir = vec3(0.0, 0.0, 1.0);\n"
221 "vec3 specular = vec3(0.0, 0.0, 0.0);\n"
222 "if (dot(normal, light_dir) >= 0.0) {\n"
223 "attenuation * light.color * pow(max(0.0, dot(reflect(-light_dir, normal), view_dir)), 25.0);\n"
225 "color = ambient + diffuse + specular;\n"
229 if (!prog.Linked()) {
231 throw std::runtime_error("link program");
233 m_handle = prog.UniformLocation("M");
234 mv_handle = prog.UniformLocation("MV");
235 mvp_handle = prog.UniformLocation("MVP");
236 sampler_handle = prog.UniformLocation("tex_sampler");
237 normal_handle = prog.UniformLocation("normal");
238 light_position_handle = prog.UniformLocation("light.position");
239 light_color_handle = prog.UniformLocation("light.color");
240 light_strength_handle = prog.UniformLocation("light.strength");
243 PlanetSurface::~PlanetSurface() {
246 void PlanetSurface::Activate() noexcept {
248 glEnable(GL_DEPTH_TEST);
249 glDepthFunc(GL_LESS);
250 glEnable(GL_CULL_FACE);
254 void PlanetSurface::SetMVP(const glm::mat4 &mm, const glm::mat4 &vv, const glm::mat4 &pp) noexcept {
260 prog.Uniform(m_handle, m);
261 prog.Uniform(mv_handle, mv);
262 prog.Uniform(mvp_handle, mvp);
265 void PlanetSurface::SetNormal(const glm::vec3 &n) noexcept {
266 prog.Uniform(normal_handle, n);
269 void PlanetSurface::SetTexture(ArrayTexture &tex) noexcept {
270 glActiveTexture(GL_TEXTURE0);
272 prog.Uniform(sampler_handle, GLint(0));
275 void PlanetSurface::SetLight(const glm::vec3 &pos, const glm::vec3 &color, float strength) noexcept {
276 prog.Uniform(light_position_handle, pos);
277 prog.Uniform(light_color_handle, color);
278 prog.Uniform(light_strength_handle, strength);
282 SunSurface::SunSurface()
286 "#version 330 core\n"
288 "layout(location = 0) in vec3 vtx_position;\n"
292 "uniform mat4 MVP;\n"
294 "out vec3 vtx_viewspace;\n"
297 "gl_Position = MVP * vec4(vtx_position, 1);\n"
298 "vtx_viewspace = (MV * vec4(vtx_position, 1)).xyz;\n"
303 "#version 330 core\n"
305 "in vec3 vtx_viewspace;\n"
307 "uniform vec3 light_color;\n"
308 "uniform float light_strength;\n"
313 "vec3 to_light = -vtx_viewspace;\n"
314 "float distance = length(to_light);\n"
315 //"vec3 light_dir = normalize(to_light);\n"
316 "float attenuation = light_strength / (distance * distance);\n"
317 "color = attenuation * light_color;\n"
321 if (!prog.Linked()) {
323 throw std::runtime_error("link program");
325 m_handle = prog.UniformLocation("M");
326 mv_handle = prog.UniformLocation("MV");
327 mvp_handle = prog.UniformLocation("MVP");
328 light_color_handle = prog.UniformLocation("light_color");
329 light_strength_handle = prog.UniformLocation("light_strength");
332 vao.BindAttributes();
333 vao.EnableAttribute(0);
334 vao.AttributePointer<glm::vec3>(0, false, offsetof(Attributes, position));
335 vao.ReserveAttributes(8, GL_STATIC_DRAW);
337 auto attrib = vao.MapAttributes(GL_WRITE_ONLY);
338 attrib[0].position = glm::vec3(-1.0f, -1.0f, -1.0f);
339 attrib[1].position = glm::vec3(-1.0f, -1.0f, 1.0f);
340 attrib[2].position = glm::vec3(-1.0f, 1.0f, -1.0f);
341 attrib[3].position = glm::vec3(-1.0f, 1.0f, 1.0f);
342 attrib[4].position = glm::vec3( 1.0f, -1.0f, -1.0f);
343 attrib[5].position = glm::vec3( 1.0f, -1.0f, 1.0f);
344 attrib[6].position = glm::vec3( 1.0f, 1.0f, -1.0f);
345 attrib[7].position = glm::vec3( 1.0f, 1.0f, 1.0f);
348 vao.ReserveElements(36, GL_STATIC_DRAW);
350 auto element = vao.MapElements(GL_WRITE_ONLY);
397 SunSurface::~SunSurface() {
400 void SunSurface::Activate() noexcept {
402 glEnable(GL_DEPTH_TEST);
403 glDepthFunc(GL_LESS);
404 glEnable(GL_CULL_FACE);
408 void SunSurface::SetMVP(const glm::mat4 &mm, const glm::mat4 &vv, const glm::mat4 &pp) noexcept {
414 prog.Uniform(m_handle, m);
415 prog.Uniform(mv_handle, mv);
416 prog.Uniform(mvp_handle, mvp);
419 void SunSurface::SetLight(const glm::vec3 &color, float strength) noexcept {
420 prog.Uniform(light_color_handle, color);
421 prog.Uniform(light_strength_handle, strength);
424 void SunSurface::Draw() const noexcept {
426 vao.DrawTriangles(36);