Browse Source

cleaned up shader/fbo.

added more uniform setters (shader)
added validate (shader)
made fob working
master
Joshua Moerman 14 years ago
parent
commit
5d49a8f525
  1. 15
      J/fbo.h
  2. 170
      J/shader.h

15
J/fbo.h

@ -12,6 +12,7 @@
// TODO: more error checking in debug build. // TODO: more error checking in debug build.
// TODO: make texture class? for easier switching between linear/nearest interpolation for example // TODO: make texture class? for easier switching between linear/nearest interpolation for example
// NOTE: stencil attachment is not supported
namespace J { namespace J {
@ -31,16 +32,12 @@ public:
// generate texture // generate texture
glGenTextures(1, &texture_id); glGenTextures(1, &texture_id);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture_id); glBindTexture(GL_TEXTURE_2D, texture_id);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_BYTE, 0); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_id, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_id, 0);
// attach depth // attach depth
create_attach_renderbuffer(GL_DEPTH_COMPONENT, GL_DEPTH_ATTACHMENT); create_attach_renderbuffer(GL_DEPTH_COMPONENT16, GL_DEPTH_ATTACHMENT);
// attach stencil
//create_attach_renderbuffer(GL_STENCIL_INDEX, GL_STENCIL_ATTACHMENT);
check_status(); check_status();
@ -84,9 +81,7 @@ private:
void bind(){ void bind(){
glBindFramebuffer(GL_FRAMEBUFFER, fbo_number); glBindFramebuffer(GL_FRAMEBUFFER, fbo_number);
GLenum status = glGetError(); check_error();
if(status != GL_NO_ERROR)
throw std::runtime_error("i has error" + std::to_string(status) + "with fbo: " + std::to_string(fbo_number));
} }
void unbind(){ void unbind(){
@ -125,7 +120,7 @@ private:
std::cout << "UNKNOWN FRAMEBUFFER ERROR" << std::endl; std::cout << "UNKNOWN FRAMEBUFFER ERROR" << std::endl;
break; break;
} }
//throw std::runtime_error("I will not continu.."); throw std::runtime_error("I will not continu..");
} }
void check_error(){ void check_error(){

170
J/shader.h

@ -13,6 +13,7 @@
// TODO: do glValidateProgram, like in the OpenGL template (see bottom) // TODO: do glValidateProgram, like in the OpenGL template (see bottom)
// 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)
namespace J { namespace J {
@ -23,6 +24,7 @@ enum {
}; };
class shader { class shader {
// NOTE: it could be hardcoded to use vertex_shader and fragment_shader.
typedef std::map<GLenum, GLuint> ShaderMap; typedef std::map<GLenum, GLuint> ShaderMap;
GLuint program; GLuint program;
@ -30,6 +32,8 @@ class shader {
public: public:
// ***********
// constructor
shader(std::string vertex_shader_filename, std::string fragment_shader_filename) : shader(std::string vertex_shader_filename, std::string fragment_shader_filename) :
program(0), shaders() { program(0), shaders() {
program = glCreateProgram(); program = glCreateProgram();
@ -42,13 +46,13 @@ public:
std::ifstream vertex_shader(vertex_shader_filename.c_str()); std::ifstream vertex_shader(vertex_shader_filename.c_str());
if(!vertex_shader) if(!vertex_shader)
throw std::runtime_error(vertex_shader_filename + " couldn't be opened"); throw std::runtime_error(vertex_shader_filename + " couldn't be opened");
read_shader(vertex_shader, GL_VERTEX_SHADER); compile_shader(vertex_shader, GL_VERTEX_SHADER);
} }
{ // fragment shader { // fragment shader
std::ifstream fragment_shader(fragment_shader_filename.c_str()); std::ifstream fragment_shader(fragment_shader_filename.c_str());
if(!fragment_shader) if(!fragment_shader)
throw std::runtime_error(fragment_shader_filename + " couldn't be opened"); throw std::runtime_error(fragment_shader_filename + " couldn't be opened");
read_shader(fragment_shader, GL_FRAGMENT_SHADER); compile_shader(fragment_shader, GL_FRAGMENT_SHADER);
} }
{ // TODO: think of a nice way to implement this { // TODO: think of a nice way to implement this
// Bind attribute locations. // Bind attribute locations.
@ -70,11 +74,12 @@ public:
// NOTE: If a shader object to be deleted is attached to a program object, it will be flagged for deletion, but it will not be deleted until it is no longer attached to any program object // NOTE: If a shader object to be deleted is attached to a program object, it will be flagged for deletion, but it will not be deleted until it is no longer attached to any program object
} }
glDeleteProgram(program);
end(); end();
glDeleteProgram(program);
} }
// *****
// usage
void begin() { void begin() {
glUseProgram(program); glUseProgram(program);
} }
@ -83,6 +88,10 @@ public:
glUseProgram(0); glUseProgram(0);
} }
// ***************
// uniform setters
// float vectors (multiple values)
void set_uniform(char const* name, float x) const { void set_uniform(char const* name, float x) const {
glUniform1f(glGetUniformLocation(program, name), x); glUniform1f(glGetUniformLocation(program, name), x);
} }
@ -99,6 +108,7 @@ public:
glUniform4f(glGetUniformLocation(program, name), x, y, z, w); glUniform4f(glGetUniformLocation(program, name), x, y, z, w);
} }
// integer vectors (multiple values)
void set_uniform(char const* name, int x) const { void set_uniform(char const* name, int x) const {
glUniform1i(glGetUniformLocation(program, name), x); glUniform1i(glGetUniformLocation(program, name), x);
} }
@ -115,31 +125,78 @@ public:
glUniform4i(glGetUniformLocation(program, name), x, y, z, w); glUniform4i(glGetUniformLocation(program, name), x, y, z, w);
} }
// TODO: add support for other matrices (not only 4x4), in ES2 only square matrices // Float vectors (array)
void set_matrix(char const* name, bool trans, const GLfloat* value) const { void set_uniform(char const* name, const GLfloat (&value)[4]) const {
glUniform4fv(glGetUniformLocation(program, name), 1, value);
}
void set_uniform(char const* name, const GLfloat (&value)[3]) const {
glUniform3fv(glGetUniformLocation(program, name), 1, value);
}
void set_uniform(char const* name, const GLfloat (&value)[2]) const {
glUniform2fv(glGetUniformLocation(program, name), 1, value);
}
void set_uniform(char const* name, const GLfloat (&value)[1]) const {
glUniform1fv(glGetUniformLocation(program, name), 1, value);
}
// Integer vectors (array)
void set_uniform(char const* name, const GLint (&value)[4]) const {
glUniform4iv(glGetUniformLocation(program, name), 1, value);
}
void set_uniform(char const* name, const GLint (&value)[3]) const {
glUniform3iv(glGetUniformLocation(program, name), 1, value);
}
void set_uniform(char const* name, const GLint (&value)[2]) const {
glUniform2iv(glGetUniformLocation(program, name), 1, value);
}
void set_uniform(char const* name, const GLint (&value)[1]) const {
glUniform1iv(glGetUniformLocation(program, name), 1, value);
}
// matrices (in ES2 only square matrices)
void set_uniform(char const* name, const GLfloat (&value)[16], GLboolean trans = GL_FALSE) const {
glUniformMatrix4fv(glGetUniformLocation(program, name), 1, trans, value); glUniformMatrix4fv(glGetUniformLocation(program, name), 1, trans, value);
} }
// TODO: add support for other vectors (not only length 4) void set_uniform(char const* name, const GLfloat (&value)[9], GLboolean trans = GL_FALSE) const {
void set_uniform(char const* name, const GLfloat* value, GLsizei count = 1) const { glUniformMatrix3fv(glGetUniformLocation(program, name), 1, trans, value);
glUniform4fv(glGetUniformLocation(program, name), count, value);
} }
// TODO: add support for other vectors (not only length 4) void set_uniform(char const* name, const GLfloat (&value)[4], GLboolean trans = GL_FALSE) const {
void set_uniform(char const* name, const GLint* value, GLsizei count = 1) const { glUniformMatrix2fv(glGetUniformLocation(program, name), 1, trans, value);
glUniform4iv(glGetUniformLocation(program, name), count, value);
} }
// textures (see todo above)
void set_texture(const char* name, GLenum target, GLuint tex, int textureLocation) const { void set_texture(const char* name, GLenum target, GLuint tex, int textureLocation) const {
glActiveTexture(GL_TEXTURE0 + textureLocation); glActiveTexture(GL_TEXTURE0 + textureLocation);
glBindTexture(target, tex); glBindTexture(target, tex);
set_uniform(name, textureLocation); set_uniform(name, textureLocation);
} }
// *********
// validator
void validate() {
GLint status;
glValidateProgram(program);
glGetProgramiv(program, GL_VALIDATE_STATUS, &status);
if(status == GL_FALSE){
std::cerr << "validator reports:" << std::endl;
show_log();
throw std::runtime_error("Program not valid");
}
}
private: private:
// FIXME: this also compiles, bad name // *******************
void read_shader(std::istream& file, GLenum type) { // compiling / linking
void compile_shader(std::istream& file, GLenum type) {
// get the c-string, the shortest way (not fastest) // get the c-string, the shortest way (not fastest)
std::string buffer((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>()); std::string buffer((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
const char* sptr = buffer.c_str(); const char* sptr = buffer.c_str();
@ -150,21 +207,9 @@ private:
glShaderSource(shader, 1, &sptr, &ssize); glShaderSource(shader, 1, &sptr, &ssize);
glCompileShader(shader); glCompileShader(shader);
#if defined(DEBUG) #if defined(DEBUG)
// check compile status check_compile_status(shader, buffer);
GLint status = GL_FALSE; #endif
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
if(status == GL_FALSE || shader == 0) {
GLsizei infoLength = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLength);
char* infoBuffer = new GLchar[infoLength];
glGetShaderInfoLog(shader, infoLength, &infoLength, infoBuffer);
std::cerr << "source:\n" << buffer << std::endl;
std::cerr << "shader reports:\n" << infoBuffer << std::endl;
delete [] infoBuffer;
throw std::runtime_error("Shader failed to compile");
}
#endif
// put it in tha map // put it in tha map
shaders[type] = shader; shaders[type] = shader;
@ -181,47 +226,42 @@ private:
// link // link
glLinkProgram(program); glLinkProgram(program);
#if defined(DEBUG) #if defined(DEBUG)
// check link status check_link_status();
#endif
}
// ***************
// status checking
void check_compile_status(GLint shader, std::string source = "") {
GLint status = GL_FALSE;
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
if(status == GL_FALSE || shader == 0) {
std::cerr << "source:\n" << source << std::endl;
std::cerr << "shader reports:" << std::endl;
show_log();
throw std::runtime_error("Shader failed to compile");
}
}
void check_link_status() {
GLint status; GLint status;
glGetProgramiv(program, GL_LINK_STATUS, &status); glGetProgramiv(program, GL_LINK_STATUS, &status);
if(status == GL_FALSE) { if(status == GL_FALSE) {
GLsizei infoLength = 0; std::cerr << "linker reports:" << std::endl;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLength); show_log();
char* infoBuffer = new GLchar[infoLength];
glGetProgramInfoLog(program, infoLength, &infoLength, infoBuffer);
std::cerr << "linker reports:\n" << infoBuffer << std::endl;
delete [] infoBuffer;
throw std::runtime_error("Shader failed to link"); throw std::runtime_error("Shader failed to link");
} }
#endif }
}
void show_log(std::ostream& out = std::cerr) {
/* GLsizei infoLength = 0;
// Validate program before drawing. This is a good check, but only really necessary in a debug build. glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLength);
- (BOOL)validateProgram:(GLuint)prog char* infoBuffer = new GLchar[infoLength];
{ glGetProgramInfoLog(program, infoLength, &infoLength, infoBuffer);
GLint logLength, status; out << infoBuffer << std::endl;
delete [] infoBuffer;
glValidateProgram(prog); }
glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0)
{
GLchar *log = (GLchar *)malloc(logLength);
glGetProgramInfoLog(prog, logLength, &logLength, log);
NSLog(@"Program validate log:\n%s", log);
free(log);
}
glGetProgramiv(prog, GL_VALIDATE_STATUS, &status);
if (status == 0)
return FALSE;
return TRUE;
}
*/
}; };
} // namespace J } // namespace J