goat3dgfx

view src/rtarg.cc @ 5:18879c956eb1

- skycube example - added fatal_log - changed the dataset to keep the whole path while searching for data files
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 17 Nov 2013 03:22:40 +0200
parents
children 7d6b667821cf
line source
1 #include <stack>
2 #include "rtarg.h"
3 #include "texture.h"
4 #include "logger.h"
6 RenderTarget::RenderTarget()
7 {
8 width = height = 0;
9 fbo = 0;
10 rbuf_zstencil = 0;
11 color_tex = 0;
12 tex_face = 0;
13 tex_targ = 0;
14 }
16 RenderTarget::~RenderTarget()
17 {
18 cleanup();
19 }
21 bool RenderTarget::create(unsigned int fmt)
22 {
23 int vp[4];
24 glGetIntegerv(GL_VIEWPORT, vp);
26 return create(vp[2] - vp[0], vp[3] - vp[1], fmt);
27 }
29 bool RenderTarget::create(int width, int height, unsigned int fmt)
30 {
31 debug_log("RenderTarget::create(%d, %d)\n", width, height);
32 cleanup();
34 tex_targ = GL_TEXTURE_2D;
35 this->width = width;
36 this->height = height;
37 int tex_width = next_pow2(width);
38 int tex_height = next_pow2(height);
40 CHECKGLERR;
41 color_tex = new Texture2D;
42 color_tex->create(tex_width, tex_height, fmt);
43 CHECKGLERR;
44 tex_face = 0;
46 glGenFramebuffers(1, &fbo);
47 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
49 glBindTexture(GL_TEXTURE_2D, color_tex->get_id());
50 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color_tex->get_id(), 0);
51 glBindTexture(GL_TEXTURE_2D, 0);
53 glGenRenderbuffers(1, &rbuf_zstencil);
54 glBindRenderbuffer(GL_RENDERBUFFER, rbuf_zstencil);
55 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, tex_width, tex_height);
56 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbuf_zstencil);
57 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbuf_zstencil);
59 glBindFramebuffer(GL_FRAMEBUFFER, 0);
60 CHECKGLERR;
61 return true;
62 }
64 bool RenderTarget::create(Texture *tex, int face)
65 {
66 debug_log("RenderTarget::create(tex{%d, %d}, face:%d)\n", tex->get_size(0),
67 tex->get_size(1), face);
69 tex_targ = GL_TEXTURE_2D;
70 if(dynamic_cast<TextureCube*>(tex)) {
71 if(face >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z) {
72 tex_targ = face;
73 } else if(face >= 0 && face < 6) {
74 tex_targ = GL_TEXTURE_CUBE_MAP_POSITIVE_X + face;
75 } else {
76 error_log("invalid face (%d) passed to RenderTarget::create(TextureCube*, int)\n", face);
77 return false;
78 }
79 }
81 cleanup();
83 width = tex->get_size(0);
84 height = tex->get_size(1);
86 color_tex = tex;
88 glGenFramebuffers(1, &fbo);
89 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
91 glBindTexture(tex_targ, color_tex->get_id());
92 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex_targ, color_tex->get_id(), 0);
93 glBindTexture(tex_targ, 0);
95 glGenRenderbuffers(1, &rbuf_zstencil);
96 glBindRenderbuffer(GL_RENDERBUFFER, rbuf_zstencil);
97 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
98 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbuf_zstencil);
99 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbuf_zstencil);
101 glBindFramebuffer(GL_FRAMEBUFFER, 0);
102 CHECKGLERR;
103 return true;
104 }
106 void RenderTarget::cleanup()
107 {
108 delete color_tex;
109 color_tex = 0;
111 if(fbo) {
112 glDeleteFramebuffers(1, &fbo);
113 }
114 if(rbuf_zstencil) {
115 glDeleteRenderbuffers(1, &rbuf_zstencil);
116 }
118 fbo = rbuf_zstencil = 0;
119 width = height = 0;
120 tex_face = 0;
121 tex_targ = 0;
122 }
124 bool RenderTarget::resize(int width, int height)
125 {
126 this->width = width;
127 this->height = height;
128 int tex_width = next_pow2(width);
129 int tex_height = next_pow2(height);
131 debug_log("resizing render target (fbo %u): %dx%d [%dx%d]\n", fbo, width, height, tex_width, tex_height);
133 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
135 color_tex->create(tex_width, tex_height, color_tex->get_format());
136 color_tex->bind();
137 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex_targ, color_tex->get_id(), 0);
138 glBindTexture(tex_targ, 0);
140 glBindRenderbuffer(GL_RENDERBUFFER, rbuf_zstencil);
141 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, tex_width, tex_height);
143 glBindFramebuffer(GL_FRAMEBUFFER, 0);
144 return true;
145 }
147 int RenderTarget::get_width() const
148 {
149 return width;
150 }
152 int RenderTarget::get_height() const
153 {
154 return height;
155 }
157 Texture *RenderTarget::get_texture() const
158 {
159 return color_tex;
160 }
162 Matrix4x4 RenderTarget::get_texture_matrix() const
163 {
164 float sx = (float)width / (float)color_tex->get_size(0);
165 float sy = (float)height / (float)color_tex->get_size(1);
167 // counting on RVO to optimize this away
168 return Matrix4x4(sx, 0, 0, 0,
169 0, sy, 0, 0,
170 0, 0, 1, 0,
171 0, 0, 0, 1);
172 }
175 static const char *fbstname[] = {
176 "GL_FRAMEBUFFER_COMPLETE",
177 "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT",
178 "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT",
179 "no such fbo error",
180 "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS",
181 "GL_FRAMEBUFFER_INCOMPLETE_FORMATS",
182 "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER",
183 "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER",
184 "GL_FRAMEBUFFER_UNSUPPORTED"
185 };
187 bool RenderTarget::check() const
188 {
189 bool res = true;
191 #ifndef GL_ES_VERSION_2_0
192 int prev_fb = 0;
193 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &prev_fb);
194 #endif
196 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
198 int status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
199 if(status != GL_FRAMEBUFFER_COMPLETE) {
200 error_log("RenderTarget::check: incomplete FBO %u: %s\n", fbo,
201 fbstname[status - GL_FRAMEBUFFER_COMPLETE]);
202 res = false;
203 goto end;
204 }
206 end:
207 #ifndef GL_ES_VERSION_2_0
208 glBindFramebuffer(GL_FRAMEBUFFER, prev_fb);
209 #endif
210 return res;
211 }
213 void RenderTarget::bind() const
214 {
215 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
217 glViewport(0, 0, width, height);
218 }
220 struct Viewport { int vp[4]; };
221 static std::stack<Viewport> vpstack;
223 void set_render_target(const RenderTarget *rtarg)
224 {
225 Viewport vp;
227 if(rtarg) {
228 glGetIntegerv(GL_VIEWPORT, vp.vp);
229 vpstack.push(vp);
231 rtarg->bind();
232 } else {
233 #ifdef GL_ES_VERSION_2_0
234 extern unsigned int default_fbo;
235 glBindFramebuffer(GL_FRAMEBUFFER, default_fbo);
236 #else
237 glBindFramebuffer(GL_FRAMEBUFFER, 0);
238 #endif
240 if(vpstack.empty()) {
241 return;
242 }
243 vp = vpstack.top();
244 vpstack.pop();
245 glViewport(vp.vp[0], vp.vp[1], vp.vp[2], vp.vp[3]);
246 }
247 }
249 int next_pow2(int x)
250 {
251 x--;
252 x = (x >> 1) | x;
253 x = (x >> 2) | x;
254 x = (x >> 4) | x;
255 x = (x >> 8) | x;
256 x = (x >> 16) | x;
257 return x + 1;
258 }