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.
538 lines
14 KiB
538 lines
14 KiB
/**************************************************************************** |
|
* VCGLib o o * |
|
* Visual and Computer Graphics Library o o * |
|
* _ O _ * |
|
* Copyright(C) 2004-2016 \/)\/ * |
|
* Visual Computing Lab /\/| * |
|
* ISTI - Italian National Research Council | * |
|
* \ * |
|
* All rights reserved. * |
|
* * |
|
* This program is free software; you can redistribute it and/or modify * |
|
* it under the terms of the GNU General Public License as published by * |
|
* the Free Software Foundation; either version 2 of the License, or * |
|
* (at your option) any later version. * |
|
* * |
|
* This program is distributed in the hope that it will be useful, * |
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of * |
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
|
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * |
|
* for more details. * |
|
* * |
|
****************************************************************************/ |
|
|
|
/**************************************************************************** |
|
History |
|
|
|
$Log: not supported by cvs2svn $ |
|
Revision 1.1 2007/07/26 16:22:47 m_di_benedetto |
|
First Commit. |
|
|
|
|
|
|
|
****************************************************************************/ |
|
|
|
#ifndef VCGLIB_GL_SURFACE_H |
|
#define VCGLIB_GL_SURFACE_H |
|
|
|
#include <vector> |
|
#include <GL/glew.h> |
|
|
|
namespace vcg |
|
{ |
|
|
|
/**************************************************************************** |
|
The gl_surface class simplify the render-to-texture OpenGL functionality. |
|
|
|
It provides a framebuffer composed of single or multiple color buffers and |
|
a depth buffer; color-only and depth-only framebuffers can also be created. |
|
|
|
Sample usage: |
|
|
|
**************************************************************** |
|
// *** declaration |
|
|
|
gl_surface my_srf; |
|
|
|
|
|
*********************** |
|
// *** initialization: single color render target, with depth buffer |
|
{ |
|
std::vector<GLenum> color_formats; |
|
color_formats.push_back(GL_RGBA8); |
|
|
|
my_srf.set(width, height, color_formats, GL_DEPTH_COMPONENT); |
|
} |
|
*********************** |
|
|
|
|
|
*********************** |
|
// *** initialization: two color render targets, without depth buffer |
|
// NOTE: the maximum number of color targets is implementation dependent. |
|
// NOTE: DX10 class hardware allows different formats for each color target. |
|
{ |
|
std::vector<GLenum> color_formats; |
|
color_formats.push_back(GL_RGBA8); |
|
color_formats.push_back(GL_RGBA8); |
|
|
|
my_srf.set(width, height, color_formats, GL_NONE); |
|
} |
|
*********************** |
|
|
|
|
|
*********************** |
|
// *** usage: render-to-targets |
|
{ |
|
my_srf.begin_write(); |
|
application_draw_code(); |
|
my_srf.end_write(); |
|
} |
|
*********************** |
|
|
|
|
|
*********************** |
|
// *** usage: using rendered textures |
|
{ |
|
// 2 buffers |
|
|
|
// bind the second |
|
glActiveTexture(GL_TEXTURE1); |
|
my_srf.begin_read_color(1); // actually does a glBindTexture(); |
|
|
|
// bind the first |
|
glActiveTexture(GL_TEXTURE0); |
|
my_srf.begin_read_color(0); |
|
|
|
application_draw_code(); |
|
|
|
// unbind the second |
|
glActiveTexture(GL_TEXTURE1); |
|
my_srf.end_read_color(1); |
|
|
|
// unbind first |
|
glActiveTexture(GL_TEXTURE0); |
|
my_srf.end_read_color(0); |
|
} |
|
|
|
*********************** |
|
// *** usage: use depth map |
|
{ |
|
my_srf.begin_read_depth(); |
|
|
|
// use depth map here |
|
application_draw_code(); |
|
|
|
my_srf.end_read_depth(); |
|
} |
|
|
|
*********************** |
|
// *** usage: cleanup |
|
{ |
|
my_srf.clear(); |
|
// clear() is also safely called in the destructor. |
|
} |
|
*********************** |
|
|
|
Other commodity methods for getting/setting pixels are also provided. |
|
|
|
****************************************************************************/ |
|
|
|
class gl_surface |
|
{ |
|
public: |
|
|
|
typedef gl_surface this_type; |
|
|
|
gl_surface(void) : width(0), height(0), depth_tex(0), fb(0) |
|
{ |
|
; |
|
} |
|
|
|
~gl_surface(void) |
|
{ |
|
this->clear(); |
|
} |
|
|
|
bool set(int width, int height, const std::vector<GLenum> & color_formats, GLenum depth_format) |
|
{ |
|
this->clear(); |
|
|
|
this->width = width; |
|
this->height = height; |
|
|
|
this->color_formats = color_formats; |
|
|
|
this->color_texs.resize(color_formats.size()); |
|
|
|
for (size_t i=0; i<this->color_texs.size(); ++i) |
|
{ |
|
glGenTextures (1, &(this->color_texs[i])); |
|
glBindTexture (GL_TEXTURE_2D, this->color_texs[i]); |
|
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
|
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
|
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
|
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
|
glTexImage2D (GL_TEXTURE_2D, 0, this->color_formats[i], this->width, this->height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, 0); |
|
} |
|
|
|
this->depth_format = depth_format; |
|
if (this->depth_format != GL_NONE) |
|
{ |
|
glGenTextures (1, &(this->depth_tex)); |
|
glBindTexture (GL_TEXTURE_2D, this->depth_tex); |
|
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
|
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
|
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
|
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
|
glTexParameteri (GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE); |
|
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB); |
|
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL); |
|
glTexImage2D (GL_TEXTURE_2D, 0, this->depth_format, this->width, this->height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0); |
|
} |
|
|
|
glGenFramebuffersEXT(1, &(this->fb)); |
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, this->fb); |
|
|
|
std::vector<GLenum> sites(this->color_texs.size()); |
|
for (size_t i=0; i<this->color_texs.size(); ++i) |
|
{ |
|
sites[i] = GL_COLOR_ATTACHMENT0_EXT + ((GLenum)i); |
|
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, sites[i], GL_TEXTURE_2D, this->color_texs[i], 0); |
|
} |
|
|
|
if (this->depth_format != GL_NONE) |
|
{ |
|
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, this->depth_tex, 0); |
|
} |
|
|
|
if (!sites.empty()) |
|
{ |
|
glDrawBuffers((GLsizei)(sites.size()), &(sites[0])); |
|
} |
|
|
|
const GLenum s = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); |
|
const bool res = (s == GL_FRAMEBUFFER_COMPLETE_EXT); |
|
|
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); |
|
|
|
if (!res) |
|
{ |
|
glDeleteFramebuffersEXT(1, &(this->fb)); |
|
this->fb = 0; |
|
|
|
for (size_t i=0; i<this->color_texs.size(); ++i) |
|
{ |
|
glDeleteTextures(1, &(this->color_texs[i])); |
|
} |
|
this->color_texs.clear(); |
|
|
|
this->color_formats.clear(); |
|
|
|
if (this->depth_tex != 0) |
|
{ |
|
glDeleteTextures(1, &(this->depth_tex)); |
|
this->depth_tex = 0; |
|
} |
|
|
|
this->width = 0; |
|
this->height = 0; |
|
|
|
return false; |
|
} |
|
|
|
return true; |
|
} |
|
|
|
bool set_simple(int width, int height) |
|
{ |
|
std::vector<GLenum> c_formats; |
|
c_formats.push_back(GL_RGBA8); |
|
|
|
return this->set(width, height, c_formats, GL_DEPTH_COMPONENT); |
|
} |
|
|
|
bool set_color_only(int width, int height, GLenum color_format) |
|
{ |
|
std::vector<GLenum> c_formats; |
|
c_formats.push_back(color_format); |
|
|
|
return this->set(width, height, c_formats, GL_NONE); |
|
} |
|
|
|
bool set_color_only(int width, int height, const std::vector<GLenum> & color_formats) |
|
{ |
|
return this->set(width, height, color_formats, GL_NONE); |
|
} |
|
|
|
bool set_depth_only(int width, int height, GLenum depth_format) |
|
{ |
|
std::vector<GLenum> c_formats; |
|
|
|
return this->set(width, height, c_formats, depth_format); |
|
} |
|
|
|
bool clear(void) |
|
{ |
|
if (!this->is_valid()) return false; |
|
|
|
glDeleteFramebuffersEXT(1, &(this->fb)); |
|
this->fb = 0; |
|
|
|
for (size_t i=0; i<this->color_texs.size(); ++i) |
|
{ |
|
glDeleteTextures(1, &(this->color_texs[i])); |
|
} |
|
this->color_texs.clear(); |
|
|
|
this->color_formats.clear(); |
|
|
|
if (this->depth_tex != 0) |
|
{ |
|
glDeleteTextures(1, &(this->depth_tex)); |
|
this->depth_tex = 0; |
|
} |
|
|
|
this->width = 0; |
|
this->height = 0; |
|
|
|
return true; |
|
} |
|
|
|
bool is_valid(void) const |
|
{ |
|
return (this->fb != 0); |
|
} |
|
|
|
int get_width(void) const |
|
{ |
|
return this->width; |
|
} |
|
|
|
int get_height(void) const |
|
{ |
|
return this->height; |
|
} |
|
|
|
int color_attachments_count(void) const |
|
{ |
|
return ((int)(this->color_texs.size())); |
|
} |
|
|
|
GLenum get_color_attachment_format(int attachment) const |
|
{ |
|
if (!this->is_valid()) return GL_NONE; |
|
if ((attachment < 0) || (attachment >= this->color_attachments_count())) return GL_NONE; |
|
|
|
return this->color_formats[attachment]; |
|
} |
|
|
|
bool has_depth_attachment(void) const |
|
{ |
|
return (this->depth_tex != 0); |
|
} |
|
|
|
GLenum get_depth_attachment_format(void) const |
|
{ |
|
if (!this->is_valid()) return GL_NONE; |
|
if (!this->has_depth_attachment()) return GL_NONE; |
|
|
|
return this->depth_format; |
|
} |
|
|
|
bool set_color_pixels(int attachment, GLenum format, GLenum type, const void * pixels) |
|
{ |
|
if (!this->begin_read_color(attachment)) return false; |
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, this->color_formats[attachment], this->width, this->height, 0, format, type, pixels); |
|
|
|
this->end_read_color(attachment); |
|
|
|
return true; |
|
} |
|
|
|
bool get_color_pixels(int attachment, GLenum format, GLenum type, void * pixels) |
|
{ |
|
if (!this->begin_read_color(attachment)) return false; |
|
|
|
glGetTexImage(GL_TEXTURE_2D, 0, format, type, pixels); |
|
|
|
this->end_read_color(attachment); |
|
|
|
return true; |
|
} |
|
|
|
bool set_depth_pixels(GLenum format, GLenum type, const void * pixels) |
|
{ |
|
if (!this->is_valid()) return false; |
|
if (!this->has_depth_attachment()) return false; |
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, this->depth_format, this->width, this->height, 0, format, type, pixels); |
|
|
|
return true; |
|
} |
|
|
|
bool get_depth_pixels(GLenum format, GLenum type, void * pixels) |
|
{ |
|
if (!this->begin_read_depth()) return false; |
|
|
|
glGetTexImage(GL_TEXTURE_2D, 0, format, type, pixels); |
|
|
|
this->end_read_depth(); |
|
|
|
return true; |
|
} |
|
|
|
bool begin_read_color(int attachment) |
|
{ |
|
if (!this->is_valid()) return false; |
|
if ((attachment < 0) || (attachment >= this->color_attachments_count())) return false; |
|
|
|
glBindTexture(GL_TEXTURE_2D, this->color_texs[attachment]); |
|
|
|
return true; |
|
} |
|
|
|
bool end_read_color(int attachment) |
|
{ |
|
if (!this->is_valid()) return false; |
|
if ((attachment < 0) || (attachment >= this->color_attachments_count())) return false; |
|
|
|
glBindTexture(GL_TEXTURE_2D, 0); |
|
|
|
return true; |
|
} |
|
|
|
bool begin_read_depth(void) |
|
{ |
|
if (!this->is_valid()) return false; |
|
if (!this->has_depth_attachment()) return false; |
|
|
|
glBindTexture(GL_TEXTURE_2D, this->depth_tex); |
|
|
|
return true; |
|
} |
|
|
|
bool end_read_depth(void) |
|
{ |
|
if (!this->is_valid()) return false; |
|
if (!this->has_depth_attachment()) return false; |
|
|
|
glBindTexture(GL_TEXTURE_2D, 0); |
|
|
|
return true; |
|
} |
|
|
|
bool begin_write(void) |
|
{ |
|
if (!this->is_valid()) return false; |
|
|
|
glPushAttrib(GL_VIEWPORT_BIT); |
|
|
|
glViewport(0, 0, this->width, this->height); |
|
|
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, this->fb); |
|
|
|
return true; |
|
} |
|
|
|
bool end_write(void) |
|
{ |
|
if (!this->is_valid()) return false; |
|
|
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); |
|
|
|
glPopAttrib(); |
|
|
|
return true; |
|
} |
|
|
|
bool draw_color_attachment(int x, int y, int width, int height, int attachment) |
|
{ |
|
if (!this->is_valid()) return false; |
|
if ((attachment < 0) || (attachment >= this->color_attachments_count())) return false; |
|
|
|
glPushAttrib(GL_ALL_ATTRIB_BITS); |
|
|
|
glViewport(x, y, width, height); |
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); |
|
|
|
glMatrixMode(GL_PROJECTION); |
|
glPushMatrix(); |
|
glLoadIdentity(); |
|
|
|
glMatrixMode(GL_MODELVIEW); |
|
glPushMatrix(); |
|
glLoadIdentity(); |
|
|
|
this->begin_read_color(attachment); |
|
glBegin(GL_QUADS); |
|
glTexCoord2f(0.0f, 0.0f); glVertex2f(-1.0f, -1.0f); |
|
glTexCoord2f(1.0f, 0.0f); glVertex2f( 1.0f, -1.0f); |
|
glTexCoord2f(1.0f, 1.0f); glVertex2f( 1.0f, 1.0f); |
|
glTexCoord2f(0.0f, 1.0f); glVertex2f(-1.0f, 1.0f); |
|
glEnd(); |
|
this->end_read_color(attachment); |
|
|
|
glMatrixMode(GL_PROJECTION); |
|
glPopMatrix(); |
|
|
|
glMatrixMode(GL_MODELVIEW); |
|
glPopMatrix(); |
|
|
|
glPopAttrib(); |
|
return true; |
|
} |
|
|
|
bool draw_depth_attachment(int x, int y, int width, int height) |
|
{ |
|
if (!this->is_valid()) return false; |
|
if (!this->has_depth_attachment()) return false; |
|
|
|
glPushAttrib(GL_ALL_ATTRIB_BITS); |
|
|
|
glViewport(x, y, width, height); |
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); |
|
|
|
glMatrixMode(GL_PROJECTION); |
|
glPushMatrix(); |
|
glLoadIdentity(); |
|
|
|
glMatrixMode(GL_MODELVIEW); |
|
glPushMatrix(); |
|
glLoadIdentity(); |
|
|
|
this->begin_read_depth(); |
|
glBegin(GL_QUADS); |
|
glTexCoord2f(0.0f, 0.0f); glVertex2f(-1.0f, -1.0f); |
|
glTexCoord2f(1.0f, 0.0f); glVertex2f( 1.0f, -1.0f); |
|
glTexCoord2f(1.0f, 1.0f); glVertex2f( 1.0f, 1.0f); |
|
glTexCoord2f(0.0f, 1.0f); glVertex2f(-1.0f, 1.0f); |
|
glEnd(); |
|
this->end_read_depth(); |
|
|
|
glMatrixMode(GL_PROJECTION); |
|
glPopMatrix(); |
|
|
|
glMatrixMode(GL_MODELVIEW); |
|
glPopMatrix(); |
|
|
|
glPopAttrib(); |
|
return true; |
|
} |
|
|
|
protected: |
|
|
|
int width; |
|
int height; |
|
std::vector<GLenum> color_formats; |
|
std::vector<GLuint> color_texs; |
|
GLenum depth_format; |
|
GLuint depth_tex; |
|
GLuint fb; |
|
}; |
|
|
|
} // end namespace vcg |
|
|
|
#endif // VCGLIB_GL_SURFACE_H
|
|
|