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. 156
      J/shader.h

15
J/fbo.h

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

156
J/shader.h

@ -13,6 +13,7 @@
// TODO: do glValidateProgram, like in the OpenGL template (see bottom)
// TODO: add error checking at set_uniforms?
// TODO: use an uniform map? (benchmark first!)
// TODO: allow arrays is uniforms (now all counts are 1)
namespace J {
@ -23,6 +24,7 @@ enum {
};
class shader {
// NOTE: it could be hardcoded to use vertex_shader and fragment_shader.
typedef std::map<GLenum, GLuint> ShaderMap;
GLuint program;
@ -30,6 +32,8 @@ class shader {
public:
// ***********
// constructor
shader(std::string vertex_shader_filename, std::string fragment_shader_filename) :
program(0), shaders() {
program = glCreateProgram();
@ -42,13 +46,13 @@ public:
std::ifstream vertex_shader(vertex_shader_filename.c_str());
if(!vertex_shader)
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
std::ifstream fragment_shader(fragment_shader_filename.c_str());
if(!fragment_shader)
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
// 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
}
glDeleteProgram(program);
end();
glDeleteProgram(program);
}
// *****
// usage
void begin() {
glUseProgram(program);
}
@ -83,6 +88,10 @@ public:
glUseProgram(0);
}
// ***************
// uniform setters
// float vectors (multiple values)
void set_uniform(char const* name, float x) const {
glUniform1f(glGetUniformLocation(program, name), x);
}
@ -99,6 +108,7 @@ public:
glUniform4f(glGetUniformLocation(program, name), x, y, z, w);
}
// integer vectors (multiple values)
void set_uniform(char const* name, int x) const {
glUniform1i(glGetUniformLocation(program, name), x);
}
@ -115,31 +125,78 @@ public:
glUniform4i(glGetUniformLocation(program, name), x, y, z, w);
}
// TODO: add support for other matrices (not only 4x4), in ES2 only square matrices
void set_matrix(char const* name, bool trans, const GLfloat* value) const {
// Float vectors (array)
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);
}
// TODO: add support for other vectors (not only length 4)
void set_uniform(char const* name, const GLfloat* value, GLsizei count = 1) const {
glUniform4fv(glGetUniformLocation(program, name), count, value);
void set_uniform(char const* name, const GLfloat (&value)[9], GLboolean trans = GL_FALSE) const {
glUniformMatrix3fv(glGetUniformLocation(program, name), 1, trans, value);
}
// TODO: add support for other vectors (not only length 4)
void set_uniform(char const* name, const GLint* value, GLsizei count = 1) const {
glUniform4iv(glGetUniformLocation(program, name), count, value);
void set_uniform(char const* name, const GLfloat (&value)[4], GLboolean trans = GL_FALSE) const {
glUniformMatrix2fv(glGetUniformLocation(program, name), 1, trans, value);
}
// textures (see todo above)
void set_texture(const char* name, GLenum target, GLuint tex, int textureLocation) const {
glActiveTexture(GL_TEXTURE0 + textureLocation);
glBindTexture(target, tex);
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:
// 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)
std::string buffer((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
const char* sptr = buffer.c_str();
@ -151,19 +208,7 @@ private:
glCompileShader(shader);
#if defined(DEBUG)
// check compile status
GLint status = GL_FALSE;
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");
}
check_compile_status(shader, buffer);
#endif
// put it in tha map
@ -182,46 +227,41 @@ private:
glLinkProgram(program);
#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;
glGetProgramiv(program, GL_LINK_STATUS, &status);
if(status == GL_FALSE) {
std::cerr << "linker reports:" << std::endl;
show_log();
throw std::runtime_error("Shader failed to link");
}
}
void show_log(std::ostream& out = std::cerr) {
GLsizei infoLength = 0;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLength);
char* infoBuffer = new GLchar[infoLength];
glGetProgramInfoLog(program, infoLength, &infoLength, infoBuffer);
std::cerr << "linker reports:\n" << infoBuffer << std::endl;
out << infoBuffer << std::endl;
delete [] infoBuffer;
throw std::runtime_error("Shader failed to link");
}
#endif
}
/*
// Validate program before drawing. This is a good check, but only really necessary in a debug build.
- (BOOL)validateProgram:(GLuint)prog
{
GLint logLength, status;
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