cleaned up shader/fbo.
added more uniform setters (shader) added validate (shader) made fob working
This commit is contained in:
parent
6dfc673420
commit
5d49a8f525
2 changed files with 112 additions and 77 deletions
15
J/fbo.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
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
|
||||
|
|
Reference in a new issue