Browse Source

added attributes, some small fixes

master
Joshua Moerman 14 years ago
parent
commit
9bf9d74b12
  1. 63
      J/shader.h

63
J/shader.h

@ -13,6 +13,7 @@
#include <fstream> #include <fstream>
#include <stdexcept> #include <stdexcept>
#include <map> #include <map>
#include <vector>
#include <iterator> #include <iterator>
#import "basic.h" #import "basic.h"
@ -21,28 +22,25 @@
// TODO: add error checking at set_uniforms? // TODO: add error checking at set_uniforms?
// TODO: use an uniform map? (benchmark first!) // TODO: use an uniform map? (benchmark first!)
// TODO: allow arrays is uniforms (now all counts are 1) // TODO: allow arrays is uniforms (now all counts are 1)
// TODO: matrix attributes are not handled well (they take up 4 indices in the attributes)
namespace J { namespace J {
enum {
ATTRIB_VERTEX,
ATTRIB_COLOR,
NUM_ATTRIBUTES
};
class shader { class shader {
// NOTE: it could be hardcoded to use vertex_shader and fragment_shader. // NOTE: it could be hardcoded to use vertex_shader and fragment_shader, for ShaderMap.
typedef std::map<GLenum, GLuint> ShaderMap; typedef std::map<GLenum, GLuint> ShaderMap; // shader_type -> shader_name
typedef std::map<std::string, GLuint> AttributeMap; // attribute_name -> attribute_index
GLuint program; GLuint program;
ShaderMap shaders; ShaderMap shaders;
AttributeMap attributes;
public: public:
// *********** // ***********
// constructor // constructor
shader(std::string vertex_shader_filename, std::string fragment_shader_filename) : shader(const std::string& vertex_shader_filename, const std::string& fragment_shader_filename, const std::vector<std::string>& attributes_to_use = std::vector<std::string>()) :
program(0), shaders() { program(0), shaders(), attributes() {
program = glCreateProgram(); program = glCreateProgram();
if(program == 0) { if(program == 0) {
throw std::runtime_error("Program couldn't be created"); throw std::runtime_error("Program couldn't be created");
@ -61,11 +59,9 @@ public:
throw std::runtime_error(fragment_shader_filename + " couldn't be opened"); throw std::runtime_error(fragment_shader_filename + " couldn't be opened");
compile_shader(fragment_shader, GL_FRAGMENT_SHADER); compile_shader(fragment_shader, GL_FRAGMENT_SHADER);
} }
{ // TODO: think of a nice way to implement this for (unsigned int i = 0; i < attributes_to_use.size(); ++i) {
// Bind attribute locations. glBindAttribLocation(program, i, attributes_to_use[i].c_str());
// This needs to be done prior to linking. attributes[attributes_to_use[i]] = i;
glBindAttribLocation(program, ATTRIB_VERTEX, "position");
glBindAttribLocation(program, ATTRIB_COLOR, "color");
} }
link_program(); link_program();
@ -96,6 +92,14 @@ public:
glUseProgram(0); glUseProgram(0);
} }
// *****************
// attribute setters
void set_attribute(const std::string& name, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr){
const GLuint index = attributes[name];
glVertexAttribPointer(index, size, type, normalized, stride, ptr);
glEnableVertexAttribArray(index);
}
// *************** // ***************
// uniform setters // uniform setters
@ -168,15 +172,15 @@ public:
} }
// matrices (in ES2 only square matrices) // matrices (in ES2 only square matrices)
void set_uniform(char const* name, const GLfloat (&value)[16], GLboolean trans = GL_FALSE) const { void set_uniform(char const* name, const GLfloat (&value)[16], GLboolean trans) const {
glUniformMatrix4fv(glGetUniformLocation(program, name), 1, trans, value); glUniformMatrix4fv(glGetUniformLocation(program, name), 1, trans, value);
} }
void set_uniform(char const* name, const GLfloat (&value)[9], GLboolean trans = GL_FALSE) const { void set_uniform(char const* name, const GLfloat (&value)[9], GLboolean trans) const {
glUniformMatrix3fv(glGetUniformLocation(program, name), 1, trans, value); glUniformMatrix3fv(glGetUniformLocation(program, name), 1, trans, value);
} }
void set_uniform(char const* name, const GLfloat (&value)[4], GLboolean trans = GL_FALSE) const { void set_uniform(char const* name, const GLfloat (&value)[4], GLboolean trans) const {
glUniformMatrix2fv(glGetUniformLocation(program, name), 1, trans, value); glUniformMatrix2fv(glGetUniformLocation(program, name), 1, trans, value);
} }
@ -198,7 +202,7 @@ public:
glGetProgramiv(program, GL_VALIDATE_STATUS, &status); glGetProgramiv(program, GL_VALIDATE_STATUS, &status);
if(status == GL_FALSE){ if(status == GL_FALSE){
std::cerr << "validator reports:" << std::endl; std::cerr << "validator reports:" << std::endl;
show_log(); show_program_log();
throw std::runtime_error("Program not valid"); throw std::runtime_error("Program not valid");
} }
#endif #endif
@ -248,7 +252,7 @@ private:
if(status == GL_FALSE || shader == 0) { if(status == GL_FALSE || shader == 0) {
std::cerr << "source:\n" << source << std::endl; std::cerr << "source:\n" << source << std::endl;
std::cerr << "shader reports:" << std::endl; std::cerr << "shader reports:" << std::endl;
show_log(); show_shader_log(shader);
throw std::runtime_error("Shader failed to compile"); throw std::runtime_error("Shader failed to compile");
} }
#endif #endif
@ -260,17 +264,26 @@ private:
glGetProgramiv(program, GL_LINK_STATUS, &status); glGetProgramiv(program, GL_LINK_STATUS, &status);
if(status == GL_FALSE) { if(status == GL_FALSE) {
std::cerr << "linker reports:" << std::endl; std::cerr << "linker reports:" << std::endl;
show_log(); show_program_log();
throw std::runtime_error("Shader failed to link"); throw std::runtime_error("Shader failed to link");
} }
#endif #endif
} }
void show_log(std::ostream& out = std::cerr) { void show_program_log(std::ostream& out = std::cerr) {
GLsizei infoLength = 0; GLint infoLength = 0;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLength); glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLength);
char* infoBuffer = new GLchar[infoLength]; char* infoBuffer = new GLchar[infoLength+10];
glGetProgramInfoLog(program, infoLength, &infoLength, infoBuffer); glGetProgramInfoLog(program, infoLength+10, &infoLength, infoBuffer);
out << infoBuffer << std::endl;
delete [] infoBuffer;
}
void show_shader_log(GLuint shader, std::ostream& out = std::cerr) {
GLint infoLength = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLength);
char* infoBuffer = new GLchar[infoLength+10];
glGetShaderInfoLog(shader, infoLength+10, &infoLength, infoBuffer);
out << infoBuffer << std::endl; out << infoBuffer << std::endl;
delete [] infoBuffer; delete [] infoBuffer;
} }