00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #ifndef VCGLIB_GL_SURFACE_H
00036 #define VCGLIB_GL_SURFACE_H
00037
00038 #include <vector>
00039 #include <GL/glew.h>
00040
00041 namespace vcg
00042 {
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140 class gl_surface
00141 {
00142 public:
00143
00144 typedef gl_surface this_type;
00145
00146 gl_surface(void) : width(0), height(0), depth_tex(0), fb(0)
00147 {
00148 ;
00149 }
00150
00151 ~gl_surface(void)
00152 {
00153 this->clear();
00154 }
00155
00156 bool set(int width, int height, const std::vector<GLenum> & color_formats, GLenum depth_format)
00157 {
00158 this->clear();
00159
00160 this->width = width;
00161 this->height = height;
00162
00163 this->color_formats = color_formats;
00164
00165 this->color_texs.resize(color_formats.size());
00166
00167 for (size_t i=0; i<this->color_texs.size(); ++i)
00168 {
00169 glGenTextures (1, &(this->color_texs[i]));
00170 glBindTexture (GL_TEXTURE_2D, this->color_texs[i]);
00171 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00172 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
00173 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
00174 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
00175 glTexImage2D (GL_TEXTURE_2D, 0, this->color_formats[i], this->width, this->height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, 0);
00176 }
00177
00178 this->depth_format = depth_format;
00179 if (this->depth_format != GL_NONE)
00180 {
00181 glGenTextures (1, &(this->depth_tex));
00182 glBindTexture (GL_TEXTURE_2D, this->depth_tex);
00183 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00184 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
00185 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
00186 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
00187 glTexParameteri (GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
00188 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
00189 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
00190 glTexImage2D (GL_TEXTURE_2D, 0, this->depth_format, this->width, this->height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0);
00191 }
00192
00193 glGenFramebuffersEXT(1, &(this->fb));
00194 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, this->fb);
00195
00196 std::vector<GLenum> sites(this->color_texs.size());
00197 for (size_t i=0; i<this->color_texs.size(); ++i)
00198 {
00199 sites[i] = GL_COLOR_ATTACHMENT0_EXT + ((GLenum)i);
00200 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, sites[i], GL_TEXTURE_2D, this->color_texs[i], 0);
00201 }
00202
00203 if (this->depth_format != GL_NONE)
00204 {
00205 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, this->depth_tex, 0);
00206 }
00207
00208 if (!sites.empty())
00209 {
00210 glDrawBuffers((GLsizei)(sites.size()), &(sites[0]));
00211 }
00212
00213 const GLenum s = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
00214 const bool res = (s == GL_FRAMEBUFFER_COMPLETE_EXT);
00215
00216 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
00217
00218 if (!res)
00219 {
00220 glDeleteFramebuffersEXT(1, &(this->fb));
00221 this->fb = 0;
00222
00223 for (size_t i=0; i<this->color_texs.size(); ++i)
00224 {
00225 glDeleteTextures(1, &(this->color_texs[i]));
00226 }
00227 this->color_texs.clear();
00228
00229 this->color_formats.clear();
00230
00231 if (this->depth_tex != 0)
00232 {
00233 glDeleteTextures(1, &(this->depth_tex));
00234 this->depth_tex = 0;
00235 }
00236
00237 this->width = 0;
00238 this->height = 0;
00239
00240 return false;
00241 }
00242
00243 return true;
00244 }
00245
00246 bool set_simple(int width, int height)
00247 {
00248 std::vector<GLenum> c_formats;
00249 c_formats.push_back(GL_RGBA8);
00250
00251 return this->set(width, height, c_formats, GL_DEPTH_COMPONENT);
00252 }
00253
00254 bool set_color_only(int width, int height, GLenum color_format)
00255 {
00256 std::vector<GLenum> c_formats;
00257 c_formats.push_back(color_format);
00258
00259 return this->set(width, height, c_formats, GL_NONE);
00260 }
00261
00262 bool set_color_only(int width, int height, const std::vector<GLenum> & color_formats)
00263 {
00264 return this->set(width, height, color_formats, GL_NONE);
00265 }
00266
00267 bool set_depth_only(int width, int height, GLenum depth_format)
00268 {
00269 std::vector<GLenum> c_formats;
00270
00271 return this->set(width, height, c_formats, depth_format);
00272 }
00273
00274 bool clear(void)
00275 {
00276 if (!this->is_valid()) return false;
00277
00278 glDeleteFramebuffersEXT(1, &(this->fb));
00279 this->fb = 0;
00280
00281 for (size_t i=0; i<this->color_texs.size(); ++i)
00282 {
00283 glDeleteTextures(1, &(this->color_texs[i]));
00284 }
00285 this->color_texs.clear();
00286
00287 this->color_formats.clear();
00288
00289 if (this->depth_tex != 0)
00290 {
00291 glDeleteTextures(1, &(this->depth_tex));
00292 this->depth_tex = 0;
00293 }
00294
00295 this->width = 0;
00296 this->height = 0;
00297
00298 return true;
00299 }
00300
00301 bool is_valid(void) const
00302 {
00303 return (this->fb != 0);
00304 }
00305
00306 int get_width(void) const
00307 {
00308 return this->width;
00309 }
00310
00311 int get_height(void) const
00312 {
00313 return this->height;
00314 }
00315
00316 int color_attachments_count(void) const
00317 {
00318 return ((int)(this->color_texs.size()));
00319 }
00320
00321 GLenum get_color_attachment_format(int attachment) const
00322 {
00323 if (!this->is_valid()) return GL_NONE;
00324 if ((attachment < 0) || (attachment >= this->color_attachments_count())) return GL_NONE;
00325
00326 return this->color_formats[attachment];
00327 }
00328
00329 bool has_depth_attachment(void) const
00330 {
00331 return (this->depth_tex != 0);
00332 }
00333
00334 GLenum get_depth_attachment_format(void) const
00335 {
00336 if (!this->is_valid()) return GL_NONE;
00337 if (!this->has_depth_attachment()) return GL_NONE;
00338
00339 return this->depth_format;
00340 }
00341
00342 bool set_color_pixels(int attachment, GLenum format, GLenum type, const void * pixels)
00343 {
00344 if (!this->begin_read_color(attachment)) return false;
00345
00346 glTexImage2D(GL_TEXTURE_2D, 0, this->color_formats[attachment], this->width, this->height, 0, format, type, pixels);
00347
00348 this->end_read_color(attachment);
00349
00350 return true;
00351 }
00352
00353 bool get_color_pixels(int attachment, GLenum format, GLenum type, void * pixels)
00354 {
00355 if (!this->begin_read_color(attachment)) return false;
00356
00357 glGetTexImage(GL_TEXTURE_2D, 0, format, type, pixels);
00358
00359 this->end_read_color(attachment);
00360
00361 return true;
00362 }
00363
00364 bool set_depth_pixels(GLenum format, GLenum type, const void * pixels)
00365 {
00366 if (!this->is_valid()) return false;
00367 if (!this->has_depth_attachment()) return false;
00368
00369 glTexImage2D(GL_TEXTURE_2D, 0, this->depth_format, this->width, this->height, 0, format, type, pixels);
00370
00371 return true;
00372 }
00373
00374 bool get_depth_pixels(GLenum format, GLenum type, void * pixels)
00375 {
00376 if (!this->begin_read_depth()) return false;
00377
00378 glGetTexImage(GL_TEXTURE_2D, 0, format, type, pixels);
00379
00380 this->end_read_depth();
00381
00382 return true;
00383 }
00384
00385 bool begin_read_color(int attachment)
00386 {
00387 if (!this->is_valid()) return false;
00388 if ((attachment < 0) || (attachment >= this->color_attachments_count())) return false;
00389
00390 glBindTexture(GL_TEXTURE_2D, this->color_texs[attachment]);
00391
00392 return true;
00393 }
00394
00395 bool end_read_color(int attachment)
00396 {
00397 if (!this->is_valid()) return false;
00398 if ((attachment < 0) || (attachment >= this->color_attachments_count())) return false;
00399
00400 glBindTexture(GL_TEXTURE_2D, 0);
00401
00402 return true;
00403 }
00404
00405 bool begin_read_depth(void)
00406 {
00407 if (!this->is_valid()) return false;
00408 if (!this->has_depth_attachment()) return false;
00409
00410 glBindTexture(GL_TEXTURE_2D, this->depth_tex);
00411
00412 return true;
00413 }
00414
00415 bool end_read_depth(void)
00416 {
00417 if (!this->is_valid()) return false;
00418 if (!this->has_depth_attachment()) return false;
00419
00420 glBindTexture(GL_TEXTURE_2D, 0);
00421
00422 return true;
00423 }
00424
00425 bool begin_write(void)
00426 {
00427 if (!this->is_valid()) return false;
00428
00429 glPushAttrib(GL_VIEWPORT_BIT);
00430
00431 glViewport(0, 0, this->width, this->height);
00432
00433 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, this->fb);
00434
00435 return true;
00436 }
00437
00438 bool end_write(void)
00439 {
00440 if (!this->is_valid()) return false;
00441
00442 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
00443
00444 glPopAttrib();
00445
00446 return true;
00447 }
00448
00449 bool draw_color_attachment(int x, int y, int width, int height, int attachment)
00450 {
00451 if (!this->is_valid()) return false;
00452 if ((attachment < 0) || (attachment >= this->color_attachments_count())) return false;
00453
00454 glPushAttrib(GL_ALL_ATTRIB_BITS);
00455
00456 glViewport(x, y, width, height);
00457
00458 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
00459
00460 glMatrixMode(GL_PROJECTION);
00461 glPushMatrix();
00462 glLoadIdentity();
00463
00464 glMatrixMode(GL_MODELVIEW);
00465 glPushMatrix();
00466 glLoadIdentity();
00467
00468 this->begin_read_color(attachment);
00469 glBegin(GL_QUADS);
00470 glTexCoord2f(0.0f, 0.0f); glVertex2f(-1.0f, -1.0f);
00471 glTexCoord2f(1.0f, 0.0f); glVertex2f( 1.0f, -1.0f);
00472 glTexCoord2f(1.0f, 1.0f); glVertex2f( 1.0f, 1.0f);
00473 glTexCoord2f(0.0f, 1.0f); glVertex2f(-1.0f, 1.0f);
00474 glEnd();
00475 this->end_read_color(attachment);
00476
00477 glMatrixMode(GL_PROJECTION);
00478 glPopMatrix();
00479
00480 glMatrixMode(GL_MODELVIEW);
00481 glPopMatrix();
00482
00483 glPopAttrib();
00484 }
00485
00486 bool draw_depth_attachment(int x, int y, int width, int height)
00487 {
00488 if (!this->is_valid()) return false;
00489 if (!this->has_depth_attachment()) return false;
00490
00491 glPushAttrib(GL_ALL_ATTRIB_BITS);
00492
00493 glViewport(x, y, width, height);
00494
00495 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
00496
00497 glMatrixMode(GL_PROJECTION);
00498 glPushMatrix();
00499 glLoadIdentity();
00500
00501 glMatrixMode(GL_MODELVIEW);
00502 glPushMatrix();
00503 glLoadIdentity();
00504
00505 this->begin_read_depth();
00506 glBegin(GL_QUADS);
00507 glTexCoord2f(0.0f, 0.0f); glVertex2f(-1.0f, -1.0f);
00508 glTexCoord2f(1.0f, 0.0f); glVertex2f( 1.0f, -1.0f);
00509 glTexCoord2f(1.0f, 1.0f); glVertex2f( 1.0f, 1.0f);
00510 glTexCoord2f(0.0f, 1.0f); glVertex2f(-1.0f, 1.0f);
00511 glEnd();
00512 this->end_read_depth();
00513
00514 glMatrixMode(GL_PROJECTION);
00515 glPopMatrix();
00516
00517 glMatrixMode(GL_MODELVIEW);
00518 glPopMatrix();
00519
00520 glPopAttrib();
00521 }
00522
00523 protected:
00524
00525 int width;
00526 int height;
00527 std::vector<GLenum> color_formats;
00528 std::vector<GLuint> color_texs;
00529 GLenum depth_format;
00530 GLuint depth_tex;
00531 GLuint fb;
00532 };
00533
00534 }
00535
00536 #endif // VCGLIB_GL_SURFACE_H