First Commit.
This commit is contained in:
parent
3019fb9177
commit
29febfdf25
|
@ -0,0 +1,533 @@
|
|||
/****************************************************************************
|
||||
* VCGLib o o *
|
||||
* Visual and Computer Graphics Library o o *
|
||||
* _ O _ *
|
||||
* Copyright(C) 2004 \/)\/ *
|
||||
* 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 $
|
||||
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
#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 + 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();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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
|
Loading…
Reference in New Issue