diff --git a/src/client/Client-gl.cc b/src/client/Client-gl.cc index d49452d..42e2a49 100644 --- a/src/client/Client-gl.cc +++ b/src/client/Client-gl.cc @@ -11,27 +11,10 @@ using namespace std; +#define LEN(arr) (sizeof(arr)/sizeof(arr[0])) #define OPENGL_CONTEXT_MAJOR 3 #define OPENGL_CONTEXT_MINOR 0 -#define NUM_OBJ_UNIFORMS 7 -static GLint obj_uniform_locations[NUM_OBJ_UNIFORMS]; -static const char *obj_uniform_names[] = { -#define OBJ_AMBIENT obj_uniform_locations[0] - "ambient", -#define OBJ_DIFFUSE obj_uniform_locations[1] - "diffuse", -#define OBJ_SPECULAR obj_uniform_locations[2] - "specular", -#define OBJ_SHININESS obj_uniform_locations[3] - "shininess", -#define OBJ_SCALE obj_uniform_locations[4] - "scale", -#define OBJ_PROJECTION obj_uniform_locations[5] - "projection", -#define OBJ_MODELVIEW obj_uniform_locations[6] - "modelview" -}; /* points of a horizontal hexagon 1.0 units high */ static const float overlay_hex_attributes[][2] = { {0.0, 0.0}, @@ -92,8 +75,16 @@ bool Client::initgl() glEnable(GL_DEPTH_TEST); GLProgram::AttributeBinding obj_attrib_bindings[] = { {0, "pos"}, - {1, "normal"}, - {0, NULL} + {1, "normal"} + }; + const char *obj_uniforms[] = { + "ambient", + "diffuse", + "specular", + "shininess", + "scale", + "projection", + "modelview" }; const char *v_source = (const char *) CFS.get_file("shaders/obj.v.glsl", NULL); const char *f_source = (const char *) CFS.get_file("shaders/obj.f.glsl", NULL); @@ -102,7 +93,9 @@ bool Client::initgl() cerr << "Error loading shader sources" << endl; return false; } - else if (!m_obj_program.create(v_source, f_source, obj_attrib_bindings)) + else if (!m_obj_program.create(v_source, f_source, + obj_attrib_bindings, LEN(obj_attrib_bindings), + obj_uniforms, LEN(obj_uniforms))) { cerr << "Error creating obj program" << endl; return false; @@ -129,8 +122,6 @@ bool Client::initgl() cerr << "Error creating overlay hex indices buffer" << endl; return false; } - m_obj_program.get_uniform_locations(obj_uniform_names, NUM_OBJ_UNIFORMS, - obj_uniform_locations); m_obj_program.use(); return true; } @@ -178,9 +169,9 @@ void Client::draw_players() stride, (GLvoid *) m_tank_obj.getVertexOffset()); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, stride, (GLvoid *) m_tank_obj.getNormalOffset()); - glUniform1f(OBJ_SCALE, 2.0f); - m_projection.to_uniform(OBJ_PROJECTION); - m_modelview.to_uniform(OBJ_MODELVIEW); + glUniform1f(m_obj_program.uniform("scale"), 2.0f); + m_projection.to_uniform(m_obj_program.uniform("projection")); + m_modelview.to_uniform(m_obj_program.uniform("modelview")); for (map::iterator it = m_tank_obj.getMaterials().begin(); it != m_tank_obj.getMaterials().end(); @@ -189,19 +180,19 @@ void Client::draw_players() WFObj::Material & m = it->second; if (m.flags & WFObj::Material::SHININESS_BIT) { - glUniform1f(OBJ_SHININESS, m.shininess); + glUniform1f(m_obj_program.uniform("shininess"), m.shininess); } if (m.flags & WFObj::Material::AMBIENT_BIT) { - glUniform4fv(OBJ_AMBIENT, 1, &m.ambient[0]); + glUniform4fv(m_obj_program.uniform("ambient"), 1, &m.ambient[0]); } if (m.flags & WFObj::Material::DIFFUSE_BIT) { - glUniform4fv(OBJ_DIFFUSE, 1, &m.diffuse[0]); + glUniform4fv(m_obj_program.uniform("diffuse"), 1, &m.diffuse[0]); } if (m.flags & WFObj::Material::SPECULAR_BIT) { - glUniform4fv(OBJ_SPECULAR, 1, &m.specular[0]); + glUniform4fv(m_obj_program.uniform("specular"), 1, &m.specular[0]); } glDrawElements(GL_TRIANGLES, m.num_vertices, GL_UNSIGNED_SHORT, @@ -216,7 +207,7 @@ void Client::draw_map() { const int width = m_map.get_width(); const int height = m_map.get_height(); - m_projection.to_uniform(OBJ_PROJECTION); + m_projection.to_uniform(m_obj_program.uniform("projection")); m_tile_obj.bindBuffers(); glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); @@ -236,8 +227,8 @@ void Client::draw_map() float cy = tile->get_y(); m_modelview.push(); m_modelview.translate(cx, cy, 0); - m_modelview.to_uniform(OBJ_MODELVIEW); - glUniform1f(OBJ_SCALE, tile->get_size()); + m_modelview.to_uniform(m_obj_program.uniform("modelview")); + glUniform1f(m_obj_program.uniform("scale"), tile->get_size()); for (map::iterator it = m_tile_obj.getMaterials().begin(); it != m_tile_obj.getMaterials().end(); @@ -246,19 +237,19 @@ void Client::draw_map() WFObj::Material & m = it->second; if (m.flags & WFObj::Material::SHININESS_BIT) { - glUniform1f(OBJ_SHININESS, m.shininess); + glUniform1f(m_obj_program.uniform("shininess"), m.shininess); } if (m.flags & WFObj::Material::AMBIENT_BIT) { - glUniform4fv(OBJ_AMBIENT, 1, &m.ambient[0]); + glUniform4fv(m_obj_program.uniform("ambient"), 1, &m.ambient[0]); } if (m.flags & WFObj::Material::DIFFUSE_BIT) { - glUniform4fv(OBJ_DIFFUSE, 1, &m.diffuse[0]); + glUniform4fv(m_obj_program.uniform("diffuse"), 1, &m.diffuse[0]); } if (m.flags & WFObj::Material::SPECULAR_BIT) { - glUniform4fv(OBJ_SPECULAR, 1, &m.specular[0]); + glUniform4fv(m_obj_program.uniform("specular"), 1, &m.specular[0]); } glDrawElements(GL_TRIANGLES, m.num_vertices, GL_UNSIGNED_SHORT, diff --git a/src/client/GL/GLProgram.cc b/src/client/GL/GLProgram.cc index 9a10a68..238546a 100644 --- a/src/client/GL/GLProgram.cc +++ b/src/client/GL/GLProgram.cc @@ -7,6 +7,7 @@ using namespace std; GLProgram::GLProgram() { m_id = 0; + m_uniform_locations = NULL; } GLProgram::~GLProgram() @@ -15,10 +16,15 @@ GLProgram::~GLProgram() { glDeleteProgram(m_id); } + if (m_uniform_locations != NULL) + { + delete[] m_uniform_locations; + } } bool GLProgram::create(const char *v_source, const char *f_source, - GLProgram::AttributeBinding *bindings) + GLProgram::AttributeBinding *bindings, int n_bindings, + const char **uniforms, int n_uniforms) { if (!m_v_shader.create(GL_VERTEX_SHADER, v_source)) return false; @@ -30,12 +36,9 @@ bool GLProgram::create(const char *v_source, const char *f_source, glAttachShader(m_id, m_v_shader.get_id()); glAttachShader(m_id, m_f_shader.get_id()); - if (bindings != NULL) + for (int i = 0; i < n_bindings; i++) { - for (int i = 0; bindings[i].name != NULL; i++) - { - glBindAttribLocation(m_id, bindings[i].index, bindings[i].name); - } + glBindAttribLocation(m_id, bindings[i].index, bindings[i].name); } glLinkProgram(m_id); @@ -56,18 +59,15 @@ bool GLProgram::create(const char *v_source, const char *f_source, return false; } + if (n_uniforms > 0) + { + m_uniform_locations = new GLint[n_uniforms]; + for (int i = 0; i < n_uniforms; i++) + { + m_uniform_locations[i] = glGetUniformLocation(m_id, uniforms[i]); + m_uniform_location_names[uniforms[i]] = m_uniform_locations[i]; + } + } + return true; } - -GLint GLProgram::get_uniform_location(const char *name) -{ - return glGetUniformLocation(m_id, name); -} - -void GLProgram::get_uniform_locations(const char **names, int num, GLint *locs) -{ - for (int i = 0; i < num; i++) - { - locs[i] = get_uniform_location(names[i]); - } -} diff --git a/src/client/GL/GLProgram.h b/src/client/GL/GLProgram.h index 9375369..3ab5b12 100644 --- a/src/client/GL/GLProgram.h +++ b/src/client/GL/GLProgram.h @@ -3,6 +3,8 @@ #define GLPROGRAM_H #include "GLShader.h" +#include +#include class GLProgram { @@ -15,15 +17,20 @@ class GLProgram GLProgram(); ~GLProgram(); bool create(const char *v_source, const char *f_source, - AttributeBinding *bindings = NULL); + AttributeBinding *bindings = NULL, int n_bindings = 0, + const char **uniforms = NULL, int n_uniforms = 0); GLuint get_id() { return m_id; } GLint get_uniform_location(const char *name); void get_uniform_locations(const char **names, int num, GLint *locs); void use() { glUseProgram(m_id); } + GLint uniform(int i) { return m_uniform_locations[i]; } + GLint uniform(const std::string & s) { return m_uniform_location_names[s]; } protected: GLuint m_id; GLShader m_v_shader; GLShader m_f_shader; + GLint * m_uniform_locations; + std::map m_uniform_location_names; }; #endif