Very small OpenGL wrapper (before moggle was there)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.
 
 
 
 

148 lines
3.9 KiB

//
// fbo.h
// J
//
// Created by Joshua Moerman on 7/01/11.
// Copyright 2011 Vadovas. All rights reserved.
//
#ifndef FBO_H
#define FBO_H
#include <map>
#include <iostream>
#include <stdexcept>
#include "to_string.h"
#include "basic.h"
@class EAGLContext;
@class CAEAGLLayer;
// 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 {
class fbo {
public:
typedef std::map<GLenum, GLuint> RenderbuffersMap;
int width, height;
GLuint fbo_number;
RenderbuffersMap renderbuffers;
GLuint texture_id;
public:
// standard ctor, makes use of textures
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);
glBindTexture(GL_TEXTURE_2D, texture_id);
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_COMPONENT16, GL_DEPTH_ATTACHMENT);
check_error();
check_status();
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
unbind();
}
// ctor from EAGLContext, not using texture, so you cannot use it as lookup, only as renderer.
fbo(EAGLContext* context, CAEAGLLayer* layer);
~fbo() {
end();
glDeleteFramebuffers(1, &fbo_number);
for(RenderbuffersMap::const_iterator i = renderbuffers.begin(); i != renderbuffers.end(); ++i){
RenderbuffersMap::value_type const & it = *i;
glDeleteRenderbuffers(1, &it.second);
}
glDeleteTextures(1, &texture_id);
// NOTE: glDeleteTextures silently ignores 0's and names that do not correspond to existing textures.
}
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. See begin()
//glPopAttrib();
}
void bind(){
glBindFramebuffer(GL_FRAMEBUFFER, fbo_number);
check_error();
}
void unbind(){
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
private:
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() {
#if defined(DEBUG)
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..");
#endif
}
};
} // namespace J
#endif // FBO_H