1 #include "PlanetSurface.hpp"
5 #include "ArrayTexture.hpp"
6 #include "../app/init.hpp"
14 #include <glm/gtc/type_ptr.hpp>
19 void gl_error(std::string msg) {
20 const GLubyte *errBegin = gluErrorString(glGetError());
21 if (errBegin && *errBegin != '\0') {
22 const GLubyte *errEnd = errBegin;
23 while (*errEnd != '\0') {
27 msg.append(errBegin, errEnd);
29 throw std::runtime_error(msg);
37 Shader::Shader(GLenum type)
38 : handle(glCreateShader(type)) {
40 gl_error("glCreateShader");
46 glDeleteShader(handle);
50 Shader::Shader(Shader &&other) noexcept
51 : handle(other.handle) {
55 Shader &Shader::operator =(Shader &&other) noexcept {
56 std::swap(handle, other.handle);
61 void Shader::Source(const GLchar *src) noexcept {
62 const GLchar* src_arr[] = { src };
63 glShaderSource(handle, 1, src_arr, nullptr);
66 void Shader::Compile() noexcept {
67 glCompileShader(handle);
70 bool Shader::Compiled() const noexcept {
71 GLint compiled = GL_FALSE;
72 glGetShaderiv(handle, GL_COMPILE_STATUS, &compiled);
73 return compiled == GL_TRUE;
76 void Shader::Log(std::ostream &out) const {
77 int log_len = 0, max_len = 0;
78 glGetShaderiv(handle, GL_INFO_LOG_LENGTH, &max_len);
79 std::unique_ptr<char[]> log(new char[max_len]);
80 glGetShaderInfoLog(handle, max_len, &log_len, log.get());
81 out.write(log.get(), log_len);
85 void Shader::AttachToProgram(GLuint id) const noexcept {
86 glAttachShader(id, handle);
91 : handle(glCreateProgram()) {
93 gl_error("glCreateProgram");
99 glDeleteProgram(handle);
104 const Shader &Program::LoadShader(GLenum type, const GLchar *src) {
105 shaders.emplace_back(type);
106 Shader &shader = shaders.back();
109 if (!shader.Compiled()) {
110 shader.Log(std::cerr);
111 throw std::runtime_error("compile shader");
117 void Program::Attach(Shader &shader) noexcept {
118 shader.AttachToProgram(handle);
121 void Program::Link() noexcept {
122 glLinkProgram(handle);
125 bool Program::Linked() const noexcept {
126 GLint linked = GL_FALSE;
127 glGetProgramiv(handle, GL_LINK_STATUS, &linked);
128 return linked == GL_TRUE;
131 void Program::Log(std::ostream &out) const {
132 int log_len = 0, max_len = 0;
133 glGetProgramiv(handle, GL_INFO_LOG_LENGTH, &max_len);
134 std::unique_ptr<char[]> log(new char[max_len]);
135 glGetProgramInfoLog(handle, max_len, &log_len, log.get());
136 out.write(log.get(), log_len);
140 GLint Program::AttributeLocation(const GLchar *name) const noexcept {
141 return glGetAttribLocation(handle, name);
144 GLint Program::UniformLocation(const GLchar *name) const noexcept {
145 return glGetUniformLocation(handle, name);
149 void Program::Uniform(GLint loc, GLint val) noexcept {
150 glUniform1i(loc, val);
153 void Program::Uniform(GLint loc, float val) noexcept {
154 glUniform1f(loc, val);
157 void Program::Uniform(GLint loc, const glm::vec3 &val) noexcept {
158 glUniform3fv(loc, 1, glm::value_ptr(val));
161 void Program::Uniform(GLint loc, const glm::vec4 &val) noexcept {
162 glUniform4fv(loc, 1, glm::value_ptr(val));
165 void Program::Uniform(GLint loc, const glm::mat4 &val) noexcept {
166 glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(val));
170 PlanetSurface::PlanetSurface()
174 "#version 330 core\n"
176 "layout(location = 0) in vec3 vtx_position;\n"
177 "layout(location = 1) in vec3 vtx_tex_uv;\n"
181 "uniform mat4 MVP;\n"
183 "out vec3 frag_tex_uv;\n"
184 "out vec3 vtx_viewspace;\n"
187 "gl_Position = MVP * vec4(vtx_position, 1);\n"
188 "vtx_viewspace = (MV * vec4(vtx_position, 1)).xyz;\n"
189 "frag_tex_uv = vtx_tex_uv;\n"
194 "#version 330 core\n"
196 "in vec3 vtx_viewspace;\n"
197 "in vec3 frag_tex_uv;\n"
199 "uniform sampler2DArray tex_sampler;\n"
200 "uniform vec3 normal;\n"
205 "vec3 tex_color = texture(tex_sampler, frag_tex_uv).rgb;\n"
207 "color = tex_color;\n"
211 if (!prog.Linked()) {
213 throw std::runtime_error("link program");
215 m_handle = prog.UniformLocation("M");
216 mv_handle = prog.UniformLocation("MV");
217 mvp_handle = prog.UniformLocation("MVP");
218 sampler_handle = prog.UniformLocation("tex_sampler");
219 normal_handle = prog.UniformLocation("normal");
222 PlanetSurface::~PlanetSurface() {
225 void PlanetSurface::Activate() noexcept {
227 glEnable(GL_DEPTH_TEST);
228 glDepthFunc(GL_LESS);
229 glDisable(GL_CULL_FACE);
233 void PlanetSurface::SetMVP(const glm::mat4 &m, const glm::mat4 &v, const glm::mat4 &p) noexcept {
234 prog.Uniform(m_handle, m);
236 prog.Uniform(mv_handle, mv);
237 prog.Uniform(mvp_handle, p * mv);
240 void PlanetSurface::SetNormal(const glm::vec3 &n) noexcept {
241 prog.Uniform(normal_handle, n);
244 void PlanetSurface::SetTexture(ArrayTexture &tex) noexcept {
245 glActiveTexture(GL_TEXTURE0);
247 prog.Uniform(sampler_handle, GLint(0));