Joshua Moerman
14 years ago
6 changed files with 396 additions and 6 deletions
@ -0,0 +1,23 @@ |
|||||
|
// |
||||
|
// J.m |
||||
|
// J |
||||
|
// |
||||
|
// Created by Joshua Moerman on 8/28/11. |
||||
|
// Copyright 2011 Vadovas. All rights reserved. |
||||
|
// |
||||
|
|
||||
|
#import "J.h" |
||||
|
|
||||
|
@implementation J |
||||
|
|
||||
|
- (id)init |
||||
|
{ |
||||
|
self = [super init]; |
||||
|
if (self) { |
||||
|
// Initialization code here. |
||||
|
} |
||||
|
|
||||
|
return self; |
||||
|
} |
||||
|
|
||||
|
@end |
@ -0,0 +1,138 @@ |
|||||
|
#ifndef FBO_H |
||||
|
#define FBO_H |
||||
|
|
||||
|
#include <map> |
||||
|
#include <iostream> |
||||
|
#include <stdexcept> |
||||
|
|
||||
|
#include "to_string.h" |
||||
|
|
||||
|
#import <OpenGLES/ES2/gl.h> |
||||
|
#import <OpenGLES/ES2/glext.h> |
||||
|
|
||||
|
// TODO: more error checking in debug build.
|
||||
|
// TODO: make texture class? for easier switching between linear/nearest interpolation for example
|
||||
|
|
||||
|
class fbo { |
||||
|
public: |
||||
|
typedef std::map<GLenum, GLuint> RenderbuffersMap; |
||||
|
|
||||
|
int width, height; |
||||
|
GLuint fbo_number; |
||||
|
RenderbuffersMap renderbuffers; |
||||
|
GLuint texture_id; |
||||
|
|
||||
|
public: |
||||
|
fbo(int width, int height) : width(width), height(height), fbo_number(0), renderbuffers(), texture_id(0) { |
||||
|
glGenFramebuffers(1, &fbo_number); |
||||
|
bind(); |
||||
|
|
||||
|
// 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); |
||||
|
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);
|
||||
|
|
||||
|
check_status(); |
||||
|
|
||||
|
glClearColor(0.0, 0.0, 0.0, 0.0); |
||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
||||
|
|
||||
|
unbind(); |
||||
|
} |
||||
|
~fbo() { |
||||
|
end(); |
||||
|
|
||||
|
glDeleteFramebuffers(1, &fbo_number); |
||||
|
|
||||
|
for(RenderbuffersMap::const_iterator i = renderbuffers.begin(); i != renderbuffers.end(); ++i){ |
||||
|
RenderbuffersMap::value_type const & it = *i; |
||||
|
glDeleteFramebuffers(1, &it.second); |
||||
|
} |
||||
|
|
||||
|
glDeleteTextures(1, &texture_id); |
||||
|
} |
||||
|
|
||||
|
void begin(){ |
||||
|
bind(); |
||||
|
// FIXME: this should be done, but also switching back should be done...
|
||||
|
//glPushAttrib(GL_VIEWPORT);
|
||||
|
//glViewport(0, 0, width, height);
|
||||
|
|
||||
|
// NOTE: commented out, because we don't want fbo's to nest.
|
||||
|
/*GLint savedFramebuffer = -1;
|
||||
|
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &savedFramebuffer); |
||||
|
std::cout << "sfb: " << savedFramebuffer << ", fbo: " << fbo_number << std::endl;*/ |
||||
|
} |
||||
|
|
||||
|
void end(){ |
||||
|
unbind(); |
||||
|
// FIXME: switch back to previous viewport.
|
||||
|
//glPopAttrib();
|
||||
|
} |
||||
|
|
||||
|
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)); |
||||
|
} |
||||
|
|
||||
|
void unbind(){ |
||||
|
glBindFramebuffer(GL_FRAMEBUFFER, 0); |
||||
|
} |
||||
|
|
||||
|
void create_attach_renderbuffer(GLenum format, GLenum attachment_point) { |
||||
|
GLuint buffer; |
||||
|
glGenRenderbuffers(1, &buffer); |
||||
|
glBindRenderbuffer(GL_RENDERBUFFER, buffer); |
||||
|
glRenderbufferStorage(GL_RENDERBUFFER, format, width, height); |
||||
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment_point, GL_RENDERBUFFER, buffer); |
||||
|
|
||||
|
renderbuffers[format] = buffer; |
||||
|
} |
||||
|
|
||||
|
void check_status() { |
||||
|
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); |
||||
|
switch(status) { |
||||
|
case GL_FRAMEBUFFER_COMPLETE: |
||||
|
std::cout << "FRAMEBUFFER_COMPLETE - OK" << std::endl; |
||||
|
return; |
||||
|
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: |
||||
|
std::cout << "FRAMEBUFFER_INCOMPLETE_ATTACHMENT" << std::endl; |
||||
|
break; |
||||
|
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: |
||||
|
std::cout << "FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT" << std::endl; |
||||
|
break; |
||||
|
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: |
||||
|
std::cout << "FRAMEBUFFER_INCOMPLETE_DIMENSIONS" << std::endl; |
||||
|
break; |
||||
|
case GL_FRAMEBUFFER_UNSUPPORTED: |
||||
|
std::cout << "FRAMEBUFFER_UNSUPPORTED" << std::endl; |
||||
|
break; |
||||
|
default: |
||||
|
std::cout << "UNKNOWN FRAMEBUFFER ERROR" << std::endl; |
||||
|
break; |
||||
|
} |
||||
|
//throw std::runtime_error("I will not continu..");
|
||||
|
} |
||||
|
|
||||
|
void check_error(){ |
||||
|
GLenum status = glGetError(); |
||||
|
if(status != GL_NO_ERROR){ |
||||
|
throw std::runtime_error("GL Error: " + std::to_string(status)); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
}; |
||||
|
|
||||
|
#endif // FBO_H
|
@ -0,0 +1,186 @@ |
|||||
|
#ifndef SHADER_H |
||||
|
#define SHADER_H |
||||
|
|
||||
|
#include <iostream> |
||||
|
#include <fstream> |
||||
|
#include <stdexcept> |
||||
|
#include <map> |
||||
|
#include <iterator> |
||||
|
|
||||
|
#import <OpenGLES/ES2/gl.h> |
||||
|
#import <OpenGLES/ES2/glext.h> |
||||
|
|
||||
|
// TODO: do glValidateProgram, like in the OpenGL template
|
||||
|
// TODO: add error checking at set_uniforms?
|
||||
|
|
||||
|
class shader { |
||||
|
typedef std::map<GLenum, GLuint> ShaderMap; |
||||
|
|
||||
|
GLuint program; |
||||
|
ShaderMap shaders; |
||||
|
|
||||
|
public: |
||||
|
|
||||
|
shader(std::string vertex_shader_filename, std::string fragment_shader_filename) : |
||||
|
program(0), shaders() { |
||||
|
program = glCreateProgram(); |
||||
|
if(program == 0) { |
||||
|
throw std::runtime_error("Program couldn't be created"); |
||||
|
} |
||||
|
|
||||
|
{ // vertex shader
|
||||
|
// NOTE: C++03 mandates .c_str(), ugly, nothing to do about it...
|
||||
|
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); |
||||
|
} |
||||
|
{ // 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); |
||||
|
} |
||||
|
|
||||
|
link_program(); |
||||
|
} |
||||
|
|
||||
|
~shader(){ |
||||
|
begin(); |
||||
|
for(ShaderMap::const_iterator i = shaders.begin(); i != shaders.end(); ++i){ |
||||
|
ShaderMap::value_type const & it = *i; |
||||
|
GLuint shader = it.second; |
||||
|
glDetachShader(program, shader); |
||||
|
glDeleteShader(shader); |
||||
|
} |
||||
|
|
||||
|
glDeleteProgram(program); |
||||
|
|
||||
|
end(); |
||||
|
} |
||||
|
|
||||
|
void begin() { |
||||
|
glUseProgram(program); |
||||
|
} |
||||
|
|
||||
|
void end() { |
||||
|
glUseProgram(0); |
||||
|
} |
||||
|
|
||||
|
void set_uniform(char const* name, float x) const { |
||||
|
glUniform1f(glGetUniformLocation(program, name), x); |
||||
|
} |
||||
|
|
||||
|
void set_uniform(char const* name, float x, float y) const { |
||||
|
glUniform2f(glGetUniformLocation(program, name), x, y); |
||||
|
} |
||||
|
|
||||
|
void set_uniform(char const* name, float x, float y, float z) const { |
||||
|
glUniform3f(glGetUniformLocation(program, name), x, y, z); |
||||
|
} |
||||
|
|
||||
|
void set_uniform(char const* name, float x, float y, float z, float w) const { |
||||
|
glUniform4f(glGetUniformLocation(program, name), x, y, z, w); |
||||
|
} |
||||
|
|
||||
|
void set_uniform(char const* name, int x) const { |
||||
|
glUniform1i(glGetUniformLocation(program, name), x); |
||||
|
} |
||||
|
|
||||
|
void set_uniform(char const* name, int x, int y) const { |
||||
|
glUniform2i(glGetUniformLocation(program, name), x, y); |
||||
|
} |
||||
|
|
||||
|
void set_uniform(char const* name, int x, int y, int z) const { |
||||
|
glUniform3i(glGetUniformLocation(program, name), x, y, z); |
||||
|
} |
||||
|
|
||||
|
void set_uniform(char const* name, int x, int y, int z, int w) const { |
||||
|
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 { |
||||
|
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); |
||||
|
} |
||||
|
|
||||
|
// 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_texture(const char* name, GLenum target, GLuint tex, int textureLocation) const { |
||||
|
glActiveTexture(GL_TEXTURE0 + textureLocation); |
||||
|
glBindTexture(target, tex); |
||||
|
set_uniform(name, textureLocation); |
||||
|
} |
||||
|
|
||||
|
private: |
||||
|
|
||||
|
// FIXME: this also compiles, bad name
|
||||
|
void read_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(); |
||||
|
int ssize = buffer.size(); |
||||
|
|
||||
|
// create and compile shader
|
||||
|
GLuint shader = glCreateShader(type); |
||||
|
glShaderSource(shader, 1, &sptr, &ssize); |
||||
|
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"); |
||||
|
} |
||||
|
#endif |
||||
|
|
||||
|
// put it in tha map
|
||||
|
shaders[type] = shader; |
||||
|
} |
||||
|
|
||||
|
void link_program() { |
||||
|
// attach all shaders
|
||||
|
for(ShaderMap::const_iterator i = shaders.begin(); i != shaders.end(); ++i){ |
||||
|
ShaderMap::value_type const & it = *i; |
||||
|
GLuint shader = it.second; |
||||
|
glAttachShader(program, shader); |
||||
|
} |
||||
|
|
||||
|
// link
|
||||
|
glLinkProgram(program); |
||||
|
|
||||
|
#if defined(DEBUG) |
||||
|
// check link status
|
||||
|
GLint status; |
||||
|
glGetProgramiv(program, GL_LINK_STATUS, &status); |
||||
|
if(status == GL_FALSE) { |
||||
|
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; |
||||
|
delete [] infoBuffer; |
||||
|
throw std::runtime_error("Shader failed to link"); |
||||
|
} |
||||
|
#endif |
||||
|
} |
||||
|
|
||||
|
}; |
||||
|
|
||||
|
#endif // SHADER_H
|
@ -0,0 +1,27 @@ |
|||||
|
//
|
||||
|
// to_string.h
|
||||
|
// OpenGLTemplate
|
||||
|
//
|
||||
|
// Created by Joshua Moerman on 8/18/11.
|
||||
|
// Copyright 2011 Vadovas. All rights reserved.
|
||||
|
//
|
||||
|
|
||||
|
#ifndef OpenGLTemplate_to_string_h |
||||
|
#define OpenGLTemplate_to_string_h |
||||
|
|
||||
|
#include <iostream> |
||||
|
#include <sstream> |
||||
|
|
||||
|
// NOTE: workaround for the std::to_string in C++11
|
||||
|
namespace std { |
||||
|
|
||||
|
template <typename T> |
||||
|
std::string to_string(T const & x){ |
||||
|
std::stringstream ss; |
||||
|
ss << x; |
||||
|
return ss.str(); |
||||
|
} |
||||
|
|
||||
|
} // end namespace std
|
||||
|
|
||||
|
#endif // OpenGLTemplate_to_string_h
|
Reference in new issue