added attributes, some small fixes
This commit is contained in:
parent
d6f76e8886
commit
9bf9d74b12
1 changed files with 38 additions and 25 deletions
63
J/shader.h
63
J/shader.h
|
@ -13,6 +13,7 @@
|
|||
#include <fstream>
|
||||
#include <stdexcept>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <iterator>
|
||||
|
||||
#import "basic.h"
|
||||
|
@ -21,28 +22,25 @@
|
|||
// TODO: add error checking at set_uniforms?
|
||||
// TODO: use an uniform map? (benchmark first!)
|
||||
// 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 {
|
||||
|
||||
enum {
|
||||
ATTRIB_VERTEX,
|
||||
ATTRIB_COLOR,
|
||||
NUM_ATTRIBUTES
|
||||
};
|
||||
|
||||
class shader {
|
||||
// NOTE: it could be hardcoded to use vertex_shader and fragment_shader.
|
||||
typedef std::map<GLenum, GLuint> ShaderMap;
|
||||
// NOTE: it could be hardcoded to use vertex_shader and fragment_shader, for ShaderMap.
|
||||
typedef std::map<GLenum, GLuint> ShaderMap; // shader_type -> shader_name
|
||||
typedef std::map<std::string, GLuint> AttributeMap; // attribute_name -> attribute_index
|
||||
|
||||
GLuint program;
|
||||
ShaderMap shaders;
|
||||
AttributeMap attributes;
|
||||
|
||||
public:
|
||||
|
||||
// ***********
|
||||
// constructor
|
||||
shader(std::string vertex_shader_filename, std::string fragment_shader_filename) :
|
||||
program(0), shaders() {
|
||||
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(), attributes() {
|
||||
program = glCreateProgram();
|
||||
if(program == 0) {
|
||||
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");
|
||||
compile_shader(fragment_shader, GL_FRAGMENT_SHADER);
|
||||
}
|
||||
{ // TODO: think of a nice way to implement this
|
||||
// Bind attribute locations.
|
||||
// This needs to be done prior to linking.
|
||||
glBindAttribLocation(program, ATTRIB_VERTEX, "position");
|
||||
glBindAttribLocation(program, ATTRIB_COLOR, "color");
|
||||
for (unsigned int i = 0; i < attributes_to_use.size(); ++i) {
|
||||
glBindAttribLocation(program, i, attributes_to_use[i].c_str());
|
||||
attributes[attributes_to_use[i]] = i;
|
||||
}
|
||||
|
||||
link_program();
|
||||
|
@ -95,6 +91,14 @@ public:
|
|||
void end() {
|
||||
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
|
||||
|
@ -168,15 +172,15 @@ public:
|
|||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -198,7 +202,7 @@ public:
|
|||
glGetProgramiv(program, GL_VALIDATE_STATUS, &status);
|
||||
if(status == GL_FALSE){
|
||||
std::cerr << "validator reports:" << std::endl;
|
||||
show_log();
|
||||
show_program_log();
|
||||
throw std::runtime_error("Program not valid");
|
||||
}
|
||||
#endif
|
||||
|
@ -248,7 +252,7 @@ private:
|
|||
if(status == GL_FALSE || shader == 0) {
|
||||
std::cerr << "source:\n" << source << std::endl;
|
||||
std::cerr << "shader reports:" << std::endl;
|
||||
show_log();
|
||||
show_shader_log(shader);
|
||||
throw std::runtime_error("Shader failed to compile");
|
||||
}
|
||||
#endif
|
||||
|
@ -260,17 +264,26 @@ private:
|
|||
glGetProgramiv(program, GL_LINK_STATUS, &status);
|
||||
if(status == GL_FALSE) {
|
||||
std::cerr << "linker reports:" << std::endl;
|
||||
show_log();
|
||||
show_program_log();
|
||||
throw std::runtime_error("Shader failed to link");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void show_log(std::ostream& out = std::cerr) {
|
||||
GLsizei infoLength = 0;
|
||||
void show_program_log(std::ostream& out = std::cerr) {
|
||||
GLint infoLength = 0;
|
||||
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLength);
|
||||
char* infoBuffer = new GLchar[infoLength];
|
||||
glGetProgramInfoLog(program, infoLength, &infoLength, infoBuffer);
|
||||
char* infoBuffer = new GLchar[infoLength+10];
|
||||
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;
|
||||
delete [] infoBuffer;
|
||||
}
|
||||
|
|
Reference in a new issue