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: 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(){
|
||||||
|
|
174
J/shader.h
174
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.
|
||||||
|
@ -69,12 +73,13 @@ public:
|
||||||
glDeleteShader(shader);
|
glDeleteShader(shader);
|
||||||
// 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);
|
||||||
}
|
}
|
||||||
|
@ -114,32 +124,79 @@ public:
|
||||||
void set_uniform(char const* name, int x, int y, int z, int w) const {
|
void set_uniform(char const* name, int x, int y, int z, int w) const {
|
||||||
glUniform4i(glGetUniformLocation(program, name), x, y, z, w);
|
glUniform4i(glGetUniformLocation(program, name), x, y, z, w);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: add support for other matrices (not only 4x4), in ES2 only square matrices
|
// matrices (in ES2 only square matrices)
|
||||||
void set_matrix(char const* name, bool trans, const GLfloat* value) const {
|
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);
|
}
|
||||||
}
|
|
||||||
|
void set_uniform(char const* name, const GLfloat (&value)[4], GLboolean trans = GL_FALSE) const {
|
||||||
// TODO: add support for other vectors (not only length 4)
|
glUniformMatrix2fv(glGetUniformLocation(program, name), 1, trans, value);
|
||||||
void set_uniform(char const* name, const GLint* value, GLsizei count = 1) const {
|
|
||||||
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) {
|
||||||
// Validate program before drawing. This is a good check, but only really necessary in a debug build.
|
GLsizei infoLength = 0;
|
||||||
- (BOOL)validateProgram:(GLuint)prog
|
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLength);
|
||||||
{
|
char* infoBuffer = new GLchar[infoLength];
|
||||||
GLint logLength, status;
|
glGetProgramInfoLog(program, infoLength, &infoLength, infoBuffer);
|
||||||
|
out << infoBuffer << std::endl;
|
||||||
glValidateProgram(prog);
|
delete [] infoBuffer;
|
||||||
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
|
||||||
|
|
Reference in a new issue