simplify GLProgram creation with stdarg

This commit is contained in:
Josh Holtrop 2012-09-24 22:11:29 -04:00
parent 889ba4735a
commit 7df681082a
3 changed files with 70 additions and 115 deletions

View File

@ -93,100 +93,37 @@ bool Client::initgl()
return false; return false;
} }
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
GLProgram::AttributeBinding obj_attrib_bindings[] = { if (!m_obj_program.create(
{0, "pos"}, CFS.get_file("shaders/obj.v.glsl"),
{1, "normal"} CFS.get_file("shaders/obj.f.glsl"),
}; "pos", 0, "normal", 1, NULL,
GLProgram::AttributeBinding sky_attrib_bindings[] = { "ambient", "diffuse", "specular", "shininess",
{0, "pos"}, "projection", "modelview", NULL))
{1, "color"}
};
GLProgram::AttributeBinding lava_attrib_bindings[] = {
{0, "pos"},
{1, "tex_coord"}
};
const char *obj_uniforms[] = {
"ambient",
"diffuse",
"specular",
"shininess",
"projection",
"modelview"
};
const char *overlay_uniforms[] = {
"projection",
"modelview",
"color"
};
const char *sky_uniforms[] = {
"projection",
"modelview"
};
const char *lava_uniforms[] = {
"projection",
"modelview",
"tex",
"shift"
};
const char *obj_v_source =
(const char *) CFS.get_file("shaders/obj.v.glsl", NULL);
const char *obj_f_source =
(const char *) CFS.get_file("shaders/obj.f.glsl", NULL);
const char *overlay_f_source =
(const char *) CFS.get_file("shaders/overlay.f.glsl", NULL);
const char *sky_v_source =
(const char *) CFS.get_file("shaders/sky.v.glsl", NULL);
const char *sky_f_source =
(const char *) CFS.get_file("shaders/sky.f.glsl", NULL);
const char *lava_v_source =
(const char *) CFS.get_file("shaders/lava.v.glsl", NULL);
const char *lava_f_source =
(const char *) CFS.get_file("shaders/lava.f.glsl", NULL);
const char *overlay_hover_f_source =
(const char *) CFS.get_file("shaders/overlay_hover.f.glsl", NULL);
if (obj_v_source == NULL || obj_f_source == NULL ||
overlay_f_source == NULL || overlay_hover_f_source == NULL ||
sky_v_source == NULL || sky_f_source == NULL ||
lava_v_source == NULL || lava_f_source == NULL)
{
cerr << "Error loading shader sources" << endl;
return false; return false;
} if (!m_overlay_program.create(
if (!m_obj_program.create(obj_v_source, obj_f_source, CFS.get_file("shaders/obj.v.glsl"),
obj_attrib_bindings, LEN(obj_attrib_bindings), CFS.get_file("shaders/overlay.f.glsl"),
obj_uniforms, LEN(obj_uniforms))) "pos", 0, "normal", 1, NULL,
{ "projection", "modelview", "color", NULL))
cerr << "Error creating obj program" << endl;
return false; return false;
} if (!m_overlay_hover_program.create(
if (!m_overlay_program.create(obj_v_source, overlay_f_source, CFS.get_file("shaders/obj.v.glsl"),
obj_attrib_bindings, LEN(obj_attrib_bindings), CFS.get_file("shaders/overlay_hover.f.glsl"),
overlay_uniforms, LEN(overlay_uniforms))) "pos", 0, "normal", 1, NULL,
{ "projection", "modelview", NULL))
cerr << "Error creating overlay program" << endl;
return false; return false;
} if (!m_sky_program.create(
if (!m_overlay_hover_program.create(obj_v_source, overlay_hover_f_source, CFS.get_file("shaders/sky.v.glsl"),
obj_attrib_bindings, LEN(obj_attrib_bindings), CFS.get_file("shaders/sky.f.glsl"),
sky_uniforms, LEN(sky_uniforms))) "pos", 0, "color", 1, NULL,
{ "projection", "modelview", NULL))
cerr << "Error creating overlay hover program" << endl;
return false; return false;
} if (!m_lava_program.create(
if (!m_sky_program.create(sky_v_source, sky_f_source, CFS.get_file("shaders/lava.v.glsl"),
sky_attrib_bindings, LEN(sky_attrib_bindings), CFS.get_file("shaders/lava.f.glsl"),
sky_uniforms, LEN(sky_uniforms))) "pos", 0, "tex_coord", 1, NULL,
{ "projection", "modelview", "tex", "shift", NULL))
cerr << "Error creating sky program" << endl;
return false; return false;
}
if (!m_lava_program.create(lava_v_source, lava_f_source,
lava_attrib_bindings, LEN(lava_attrib_bindings),
lava_uniforms, LEN(lava_uniforms)))
{
cerr << "Error creating lava program" << endl;
return false;
}
if (!m_tank_obj.load("models/tank.obj", load_file)) if (!m_tank_obj.load("models/tank.obj", load_file))
{ {
cerr << "Error loading tank model" << endl; cerr << "Error loading tank model" << endl;

View File

@ -1,5 +1,6 @@
#include "GLProgram.h" #include "GLProgram.h"
#include <stdint.h>
#include <iostream> #include <iostream>
using namespace std; using namespace std;
@ -7,7 +8,6 @@ using namespace std;
GLProgram::GLProgram() GLProgram::GLProgram()
{ {
m_id = 0; m_id = 0;
m_uniform_locations = NULL;
} }
GLProgram::~GLProgram() GLProgram::~GLProgram()
@ -16,29 +16,50 @@ 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, int n_bindings,
const char **uniforms, int n_uniforms)
{ {
va_list va;
va_start(va, f_source);
bool rv = createv(v_source, f_source, va);
va_end(va);
return rv;
}
bool GLProgram::create(const uint8_t *v_source, const uint8_t *f_source, ...)
{
va_list va;
va_start(va, f_source);
bool rv = createv((const char *) v_source, (const char *) f_source, va);
va_end(va);
return rv;
}
bool GLProgram::createv(const char *v_source, const char *f_source, va_list va)
{
if (v_source == NULL || f_source == NULL)
return false;
if (!m_v_shader.create(GL_VERTEX_SHADER, v_source)) if (!m_v_shader.create(GL_VERTEX_SHADER, v_source))
return false; return false;
if (!m_f_shader.create(GL_FRAGMENT_SHADER, f_source)) if (!m_f_shader.create(GL_FRAGMENT_SHADER, f_source))
return false; return false;
m_id = glCreateProgram(); m_id = glCreateProgram();
if (m_id <= 0) if (m_id <= 0)
{
cerr << "Error allocating GL program object" << endl;
return false; return false;
}
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());
for (int i = 0; i < n_bindings; i++) for (;;)
{ {
glBindAttribLocation(m_id, bindings[i].index, bindings[i].name); const char *attribute_name = va_arg(va, const char *);
if (attribute_name == NULL)
break;
GLuint attribute_index = va_arg(va, uint32_t);
glBindAttribLocation(m_id, attribute_index, attribute_name);
} }
glLinkProgram(m_id); glLinkProgram(m_id);
@ -59,14 +80,14 @@ bool GLProgram::create(const char *v_source, const char *f_source,
return false; return false;
} }
if (n_uniforms > 0) for (;;)
{ {
m_uniform_locations = new GLint[n_uniforms]; const char *uniform_name = va_arg(va, const char *);
for (int i = 0; i < n_uniforms; i++) if (uniform_name == NULL)
{ break;
m_uniform_locations[i] = glGetUniformLocation(m_id, uniforms[i]); GLint loc = glGetUniformLocation(m_id, uniform_name);
m_uniform_location_names[uniforms[i]] = m_uniform_locations[i]; m_uniform_locations.push_back(loc);
} m_uniform_location_names[uniform_name] = loc;
} }
return true; return true;

View File

@ -2,23 +2,20 @@
#ifndef GLPROGRAM_H #ifndef GLPROGRAM_H
#define GLPROGRAM_H #define GLPROGRAM_H
#include <stdarg.h>
#include "GLShader.h" #include "GLShader.h"
#include <map> #include <map>
#include <string> #include <string>
#include <vector>
class GLProgram class GLProgram
{ {
public: public:
typedef struct
{
GLuint index;
const char *name;
} AttributeBinding;
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, int n_bindings = 0, bool create(const uint8_t *v_source, const uint8_t *f_source, ...);
const char **uniforms = NULL, int n_uniforms = 0); bool createv(const char *v_source, const char *f_source, va_list va);
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);
@ -29,7 +26,7 @@ class GLProgram
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::vector<GLint> m_uniform_locations;
std::map<std::string, GLint> m_uniform_location_names; std::map<std::string, GLint> m_uniform_location_names;
}; };