add GLProgram::uniform()

This commit is contained in:
Josh Holtrop 2012-09-15 20:35:48 -04:00
parent 24a08e6017
commit a1a81d66e1
3 changed files with 55 additions and 57 deletions

View File

@ -11,27 +11,10 @@
using namespace std; using namespace std;
#define LEN(arr) (sizeof(arr)/sizeof(arr[0]))
#define OPENGL_CONTEXT_MAJOR 3 #define OPENGL_CONTEXT_MAJOR 3
#define OPENGL_CONTEXT_MINOR 0 #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 */ /* points of a horizontal hexagon 1.0 units high */
static const float overlay_hex_attributes[][2] = { static const float overlay_hex_attributes[][2] = {
{0.0, 0.0}, {0.0, 0.0},
@ -92,8 +75,16 @@ bool Client::initgl()
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
GLProgram::AttributeBinding obj_attrib_bindings[] = { GLProgram::AttributeBinding obj_attrib_bindings[] = {
{0, "pos"}, {0, "pos"},
{1, "normal"}, {1, "normal"}
{0, NULL} };
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 *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); 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; cerr << "Error loading shader sources" << endl;
return false; 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; cerr << "Error creating obj program" << endl;
return false; return false;
@ -129,8 +122,6 @@ bool Client::initgl()
cerr << "Error creating overlay hex indices buffer" << endl; cerr << "Error creating overlay hex indices buffer" << endl;
return false; return false;
} }
m_obj_program.get_uniform_locations(obj_uniform_names, NUM_OBJ_UNIFORMS,
obj_uniform_locations);
m_obj_program.use(); m_obj_program.use();
return true; return true;
} }
@ -178,9 +169,9 @@ void Client::draw_players()
stride, (GLvoid *) m_tank_obj.getVertexOffset()); stride, (GLvoid *) m_tank_obj.getVertexOffset());
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE,
stride, (GLvoid *) m_tank_obj.getNormalOffset()); stride, (GLvoid *) m_tank_obj.getNormalOffset());
glUniform1f(OBJ_SCALE, 2.0f); glUniform1f(m_obj_program.uniform("scale"), 2.0f);
m_projection.to_uniform(OBJ_PROJECTION); m_projection.to_uniform(m_obj_program.uniform("projection"));
m_modelview.to_uniform(OBJ_MODELVIEW); m_modelview.to_uniform(m_obj_program.uniform("modelview"));
for (map<string, WFObj::Material>::iterator it = for (map<string, WFObj::Material>::iterator it =
m_tank_obj.getMaterials().begin(); m_tank_obj.getMaterials().begin();
it != m_tank_obj.getMaterials().end(); it != m_tank_obj.getMaterials().end();
@ -189,19 +180,19 @@ void Client::draw_players()
WFObj::Material & m = it->second; WFObj::Material & m = it->second;
if (m.flags & WFObj::Material::SHININESS_BIT) 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) 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) 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) 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, glDrawElements(GL_TRIANGLES, m.num_vertices,
GL_UNSIGNED_SHORT, GL_UNSIGNED_SHORT,
@ -216,7 +207,7 @@ void Client::draw_map()
{ {
const int width = m_map.get_width(); const int width = m_map.get_width();
const int height = m_map.get_height(); 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(); m_tile_obj.bindBuffers();
glEnableVertexAttribArray(0); glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1); glEnableVertexAttribArray(1);
@ -236,8 +227,8 @@ void Client::draw_map()
float cy = tile->get_y(); float cy = tile->get_y();
m_modelview.push(); m_modelview.push();
m_modelview.translate(cx, cy, 0); m_modelview.translate(cx, cy, 0);
m_modelview.to_uniform(OBJ_MODELVIEW); m_modelview.to_uniform(m_obj_program.uniform("modelview"));
glUniform1f(OBJ_SCALE, tile->get_size()); glUniform1f(m_obj_program.uniform("scale"), tile->get_size());
for (map<string, WFObj::Material>::iterator it = for (map<string, WFObj::Material>::iterator it =
m_tile_obj.getMaterials().begin(); m_tile_obj.getMaterials().begin();
it != m_tile_obj.getMaterials().end(); it != m_tile_obj.getMaterials().end();
@ -246,19 +237,19 @@ void Client::draw_map()
WFObj::Material & m = it->second; WFObj::Material & m = it->second;
if (m.flags & WFObj::Material::SHININESS_BIT) 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) 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) 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) 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, glDrawElements(GL_TRIANGLES, m.num_vertices,
GL_UNSIGNED_SHORT, GL_UNSIGNED_SHORT,

View File

@ -7,6 +7,7 @@ using namespace std;
GLProgram::GLProgram() GLProgram::GLProgram()
{ {
m_id = 0; m_id = 0;
m_uniform_locations = NULL;
} }
GLProgram::~GLProgram() GLProgram::~GLProgram()
@ -15,10 +16,15 @@ GLProgram::~GLProgram()
{ {
glDeleteProgram(m_id); glDeleteProgram(m_id);
} }
if (m_uniform_locations != NULL)
{
delete[] m_uniform_locations;
}
} }
bool GLProgram::create(const char *v_source, const char *f_source, 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)) if (!m_v_shader.create(GL_VERTEX_SHADER, v_source))
return false; 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_v_shader.get_id());
glAttachShader(m_id, m_f_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); glLinkProgram(m_id);
@ -56,18 +59,15 @@ bool GLProgram::create(const char *v_source, const char *f_source,
return false; 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; 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]);
}
}

View File

@ -3,6 +3,8 @@
#define GLPROGRAM_H #define GLPROGRAM_H
#include "GLShader.h" #include "GLShader.h"
#include <map>
#include <string>
class GLProgram class GLProgram
{ {
@ -15,15 +17,20 @@ class GLProgram
GLProgram(); GLProgram();
~GLProgram(); ~GLProgram();
bool create(const char *v_source, const char *f_source, 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; } GLuint get_id() { return m_id; }
GLint get_uniform_location(const char *name); GLint get_uniform_location(const char *name);
void get_uniform_locations(const char **names, int num, GLint *locs); void get_uniform_locations(const char **names, int num, GLint *locs);
void use() { glUseProgram(m_id); } 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: protected:
GLuint m_id; GLuint m_id;
GLShader m_v_shader; GLShader m_v_shader;
GLShader m_f_shader; GLShader m_f_shader;
GLint * m_uniform_locations;
std::map<std::string, GLint> m_uniform_location_names;
}; };
#endif #endif