5 unsigned int RenderTarget::default_fbo = 0;
7 RenderTarget::RenderTarget()
17 RenderTarget::~RenderTarget()
22 bool RenderTarget::create(unsigned int fmt)
24 return create(win_width, win_height, fmt);
27 bool RenderTarget::create(int width, int height, unsigned int fmt)
29 fprintf(stderr, "RenderTarget::create(%d, %d)\n", width, height);
32 tex_targ = GL_TEXTURE_2D;
34 this->height = height;
35 int tex_width = next_pow2(width);
36 int tex_height = next_pow2(height);
38 tex_matrix.scaling((float)width / (float)tex_width, (float)height / (float)tex_height, 1.0);
40 color_tex = new Texture2D;
41 color_tex->create(tex_width, tex_height, fmt);
44 glGenFramebuffers(1, &fbo);
45 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
47 glBindTexture(GL_TEXTURE_2D, color_tex->get_id());
48 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color_tex->get_id(), 0);
49 glBindTexture(GL_TEXTURE_2D, 0);
51 glGenRenderbuffers(1, &rbuf_zstencil);
52 glBindRenderbuffer(GL_RENDERBUFFER, rbuf_zstencil);
53 #ifdef GL_ES_VERSION_2_0
54 // XXX really? 16bit zbuffer attachment is the best we can do on ES2?
55 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, tex_width, tex_height);
57 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, tex_width, tex_height);
59 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbuf_zstencil);
60 #ifndef GL_ES_VERSION_2_0
61 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbuf_zstencil);
64 glBindFramebuffer(GL_FRAMEBUFFER, RenderTarget::default_fbo);
68 bool RenderTarget::create(Texture *tex, int face)
70 fprintf(stderr, "RenderTarget::create(tex{%d, %d}, face:%d)\n", tex->get_size(0),
71 tex->get_size(1), face);
73 tex_targ = GL_TEXTURE_2D;
74 if(dynamic_cast<TextureCube*>(tex)) {
75 if(face >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z) {
77 } else if(face >= 0 && face < 6) {
78 tex_targ = GL_TEXTURE_CUBE_MAP_POSITIVE_X + face;
80 fprintf(stderr, "invalid face (%d) passed to RenderTarget::create(TextureCube*, int)\n", face);
87 width = tex->get_size(0);
88 height = tex->get_size(1);
90 tex_matrix = Mat4::identity;
94 glGenFramebuffers(1, &fbo);
95 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
97 glBindTexture(tex_targ, color_tex->get_id());
98 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex_targ, color_tex->get_id(), 0);
99 glBindTexture(tex_targ, 0);
101 glGenRenderbuffers(1, &rbuf_zstencil);
102 glBindRenderbuffer(GL_RENDERBUFFER, rbuf_zstencil);
103 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
104 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbuf_zstencil);
105 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbuf_zstencil);
107 glBindFramebuffer(GL_FRAMEBUFFER, RenderTarget::default_fbo);
111 void RenderTarget::cleanup()
117 glDeleteFramebuffers(1, &fbo);
120 glDeleteRenderbuffers(1, &rbuf_zstencil);
123 fbo = rbuf_zstencil = 0;
129 bool RenderTarget::resize(int width, int height)
131 if(width == this->width && height == this->height) {
135 int tex_width = next_pow2(width);
136 int tex_height = next_pow2(height);
138 this->height = height;
140 if(tex_width != color_tex->get_size(0) || tex_height != color_tex->get_size(1)) {
141 printf("resizing render target (fbo %u): %dx%d [%dx%d]\n", fbo, width, height, tex_width, tex_height);
143 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
145 color_tex->create(tex_width, tex_height, color_tex->get_format());
147 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex_targ, color_tex->get_id(), 0);
148 glBindTexture(tex_targ, 0);
150 glBindRenderbuffer(GL_RENDERBUFFER, rbuf_zstencil);
152 unsigned int depth_format;
153 #ifndef GL_ES_VERSION_2_0
154 // desktop OpenGL, use typical depth24-stencil8 format
155 depth_format = GL_DEPTH24_STENCIL8;
157 // OpenGL ES provides combined depth/stencil formats as an extension
158 #ifdef GL_OES_packed_depth_stencil
159 if(have_ext_packed_depth_stencil) {
160 depth_format = GL_DEPTH24_STENCIL8_OES;
162 #endif // GL_OES_packed_depth_stencil
164 depth_format = GL_DEPTH_COMPONENT16; // no compile-time or runtime support for packed d/s
166 #endif // GL_ES_VERSION_2_0
167 glRenderbufferStorage(GL_RENDERBUFFER, depth_format, tex_width, tex_height);
169 glBindFramebuffer(GL_FRAMEBUFFER, RenderTarget::default_fbo);
172 tex_matrix.scaling((float)width / (float)tex_width, (float)height / (float)tex_height, 1.0);
176 int RenderTarget::get_width() const
181 int RenderTarget::get_height() const
186 Texture *RenderTarget::get_texture() const
191 const Mat4 &RenderTarget::get_texture_matrix() const
197 static const char *fbstname[] = {
198 "GL_FRAMEBUFFER_COMPLETE",
199 "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT",
200 "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT",
202 "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS",
203 "GL_FRAMEBUFFER_INCOMPLETE_FORMATS",
204 "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER",
205 "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER",
206 "GL_FRAMEBUFFER_UNSUPPORTED"
209 bool RenderTarget::check() const
213 #ifndef GL_ES_VERSION_2_0
215 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &prev_fb);
218 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
220 int status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
221 if(status != GL_FRAMEBUFFER_COMPLETE) {
222 fprintf(stderr, "RenderTarget::check: incomplete FBO %u: %s\n", fbo,
223 fbstname[status - GL_FRAMEBUFFER_COMPLETE]);
229 #ifndef GL_ES_VERSION_2_0
230 glBindFramebuffer(GL_FRAMEBUFFER, prev_fb);
235 void RenderTarget::bind() const
237 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
239 glViewport(0, 0, width, height);
242 void set_render_target(const RenderTarget *rtarg)
247 glBindFramebuffer(GL_FRAMEBUFFER, RenderTarget::default_fbo);
248 glViewport(0, 0, win_width, win_height);