4 changed files with 449 additions and 0 deletions
@ -0,0 +1,224 @@ |
|||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||
|
/// @file FBO.cpp
|
||||
|
/// @author Olivier Dionne
|
||||
|
/// @brief Définit la classe FBO implémentant un Frame Buffer Object simple
|
||||
|
/// pour openGL
|
||||
|
/// @date 2008-10-19
|
||||
|
/// @version 1.0
|
||||
|
///
|
||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||
|
#include "FBO.h" |
||||
|
|
||||
|
using namespace std; |
||||
|
|
||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||
|
/// public overloaded constructor FBO \n
|
||||
|
///
|
||||
|
/// Crée un FBO très simple où tous les membres privés sont à 0.
|
||||
|
///
|
||||
|
/// @return Aucune
|
||||
|
///
|
||||
|
/// @author Olivier Dionne
|
||||
|
/// @date 2008-10-19
|
||||
|
///
|
||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||
|
FBO::FBO() : |
||||
|
m_FBO( 0 ), |
||||
|
m_Texture( 0 ), |
||||
|
m_InternalFormat( 0 ), |
||||
|
m_Target( GL_TEXTURE_2D ), |
||||
|
m_TextureW( 0 ), |
||||
|
m_TextureH( 0 ) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||
|
/// public destructor ~FBO \n
|
||||
|
///
|
||||
|
/// Détruit un objet FBO
|
||||
|
///
|
||||
|
/// @return Aucune
|
||||
|
///
|
||||
|
/// @author Olivier Dionne
|
||||
|
/// @date 2008-10-19
|
||||
|
///
|
||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||
|
FBO::~FBO() |
||||
|
{ |
||||
|
Liberer(); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||
|
/// public Init \n
|
||||
|
///
|
||||
|
/// Cette méthode initialise le FBO en créant les noms de texture à l'interne.
|
||||
|
/// Pour une mise à jour du FBO à chaque image, cette fonction NE DEVRAIT PAS
|
||||
|
/// être appelée constamment, parce qu'elle consomme de la mémoire et est
|
||||
|
/// relativement lente. On conseille donc d'appeler Init() une seule fois au début
|
||||
|
/// de l'application, puis simplement d'utiliser la paire CommencerCapture() et
|
||||
|
/// TerminerCapture() afin de mettre à jour le contenu interne du FBO en tout temps.
|
||||
|
/// Évidemment, parce qu'il est important que la taille du FBO soit la même que le
|
||||
|
/// viewport courant, si la taille du viewport change en cours d'exécution, il est
|
||||
|
/// impératif d'appeler Init() à nouveau (avec les nouvelles valeurs de w et de h), mais
|
||||
|
/// en ayant pris soin au préalable de LIBERER la mémoire du FBO.
|
||||
|
///
|
||||
|
/// @param [in] w int La largeur du viewport / de la texture interne
|
||||
|
/// @param [in] h int La hauteur du viewport / de la texture interne
|
||||
|
/// @param [in] format int Le format interne de la texture du FBO (communément GL_RGB)
|
||||
|
///
|
||||
|
/// @return Aucune
|
||||
|
///
|
||||
|
/// @author Olivier Dionne
|
||||
|
/// @date 2008-10-19
|
||||
|
///
|
||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||
|
void FBO::Init( int w, int h ) |
||||
|
{ |
||||
|
// Dimensions
|
||||
|
m_TextureW = w; |
||||
|
m_TextureH = h; |
||||
|
|
||||
|
// TODO: Remplir la fonction d'initialisation d'un FBO:
|
||||
|
|
||||
|
// Créer et lier un nouveau frame buffer avec l'ID m_fbo:
|
||||
|
glGenFramebuffers(1, &m_FBO); |
||||
|
glBindFramebuffer(GL_FRAMEBUFFER, m_FBO); |
||||
|
|
||||
|
// Créer une texture RGB pour les couleurs avec L'ID m_Texture:
|
||||
|
// Pour échantillionner plus tard des valeurs exactes
|
||||
|
// on veut des filtres de mignification et magnification de tpe NEAREST!
|
||||
|
glGenTextures(1, &m_Texture); |
||||
|
glBindTexture(m_Target, m_Texture); |
||||
|
glTexParameteri(m_Target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
||||
|
glTexParameteri(m_Target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
||||
|
glTexImage2D(m_Target, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); |
||||
|
|
||||
|
// Créer une texture de profondeurs pour les couleurs avec L'ID m_Profondeur:
|
||||
|
glGenTextures(1, &m_Profondeur); |
||||
|
glBindTexture(m_Target, m_Profondeur); |
||||
|
glTexParameteri(m_Target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
||||
|
glTexParameteri(m_Target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
||||
|
glTexImage2D(m_Target, 0, GL_DEPTH_COMPONENT, w, h, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL); |
||||
|
|
||||
|
|
||||
|
// Attacher nos deux textures au frame buffer à des fin d'affichage (DRAW):
|
||||
|
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_Target, m_Texture, 0); |
||||
|
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, m_Target, m_Profondeur, 0); |
||||
|
|
||||
|
// Vérification des erreurs FBO
|
||||
|
// Nous vous fournissons cette vérification d'erreurs
|
||||
|
// pour que vous arriviez plus aisément à déboguer votre code.
|
||||
|
GLenum status = glCheckFramebufferStatus( GL_FRAMEBUFFER ); |
||||
|
glBindFramebuffer(GL_FRAMEBUFFER, 0); |
||||
|
|
||||
|
// On vérifie les erreurs à la suite de la création du FBO
|
||||
|
switch( status ) |
||||
|
{ |
||||
|
case GL_FRAMEBUFFER_COMPLETE_EXT: |
||||
|
break; |
||||
|
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: |
||||
|
cerr << "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT" << endl; |
||||
|
break; |
||||
|
case GL_FRAMEBUFFER_UNSUPPORTED_EXT: |
||||
|
cerr << "GL_FRAMEBUFFER_UNSUPPORTED_EXT" << endl; |
||||
|
break; |
||||
|
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: |
||||
|
cerr << "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT" << endl; |
||||
|
break; |
||||
|
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: |
||||
|
cerr << "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT" << endl; |
||||
|
break; |
||||
|
case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT: |
||||
|
cerr << "GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT" << endl; |
||||
|
break; |
||||
|
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: |
||||
|
cerr << "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT" << endl; |
||||
|
break; |
||||
|
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: |
||||
|
cerr << "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT" << endl; |
||||
|
break; |
||||
|
default: |
||||
|
cerr << "ERREUR INCONNUE" << endl; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||
|
/// public Liberer \n
|
||||
|
///
|
||||
|
/// Cette fonction libère l'espace mémoire interne du FBO
|
||||
|
///
|
||||
|
/// @return Aucune
|
||||
|
///
|
||||
|
/// @author Olivier Dionne
|
||||
|
/// @date 2008-10-19
|
||||
|
///
|
||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||
|
void FBO::Liberer() |
||||
|
{ |
||||
|
if ( m_Texture ) |
||||
|
{ |
||||
|
glDeleteTextures( 1, &m_Texture ); |
||||
|
m_Texture = 0; |
||||
|
} |
||||
|
|
||||
|
if ( m_FBO ) |
||||
|
{ |
||||
|
glDeleteFramebuffers( 1, &m_FBO ); |
||||
|
m_FBO = 0; |
||||
|
} |
||||
|
if(m_Profondeur) |
||||
|
{ |
||||
|
glDeleteTextures( 1, &m_Profondeur ); |
||||
|
m_Profondeur = 0; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||
|
/// public CommencerCapture \n
|
||||
|
///
|
||||
|
/// Cette fonction débute la définition du contenu du FBO. Son utilisation est
|
||||
|
/// très simple et intuitive. Une fois le FBO construit et initialiser avec new ()
|
||||
|
/// et Init(), on n'a qu'à insérer les commandes openGL produisant le rendu externe
|
||||
|
/// voulu (qui sera enregistré dans le FBO) entre les commandes CommencerCapture() et
|
||||
|
/// TerminerCapture();
|
||||
|
///
|
||||
|
/// @return Aucune
|
||||
|
///
|
||||
|
/// @author Olivier Dionne, Frédéric Plourde
|
||||
|
/// @date 2008-10-19
|
||||
|
///
|
||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||
|
void FBO::CommencerCapture() |
||||
|
{ |
||||
|
// TODO:
|
||||
|
// Activer l'utilisation du FBO
|
||||
|
// Attention à la résolution avec laquelle on veut afficher!
|
||||
|
glBindFramebuffer(GL_FRAMEBUFFER, m_FBO); |
||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
||||
|
glPushAttrib(GL_VIEWPORT_BIT); |
||||
|
glViewport(0,0,m_TextureW, m_TextureH); |
||||
|
} |
||||
|
|
||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||
|
/// public TerminerCapture \n
|
||||
|
///
|
||||
|
/// Cette fonction termine la définition du contenu du FBO. Son utilisation est
|
||||
|
/// très simple et intuitive. Une fois le FBO construit et initialiser avec new ()
|
||||
|
/// et Init(), on n'a qu'à insérer les commandes openGL produisant le rendu externe
|
||||
|
/// voulu (qui sera enregistré dans le FBO) entre les commandes CommencerCapture() et
|
||||
|
/// TerminerCapture();
|
||||
|
///
|
||||
|
/// @return Aucune
|
||||
|
///
|
||||
|
/// @author Olivier Dionne
|
||||
|
/// @date 2008-10-19
|
||||
|
///
|
||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||
|
void FBO::TerminerCapture() |
||||
|
{ |
||||
|
// TODO:
|
||||
|
// Remettre OpenGL dans l'état par défaut
|
||||
|
glBindFramebuffer(GL_FRAMEBUFFER, 0); |
||||
|
glPopAttrib(); |
||||
|
} |
||||
@ -0,0 +1,66 @@ |
|||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||
|
/// @file FBO.h
|
||||
|
/// @author Olivier Dionne
|
||||
|
/// @brief Déclare une classe implémentant un "frame buffer object"
|
||||
|
/// @date 2008-10-19
|
||||
|
/// @version 1.0
|
||||
|
///
|
||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||
|
#pragma once |
||||
|
|
||||
|
#include <iostream> |
||||
|
#include <GL/glew.h> |
||||
|
|
||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||
|
/// @class FBO
|
||||
|
/// @brief Cette classe encapsule un FBO (Frame Buffer Object) openGL
|
||||
|
///
|
||||
|
/// @author Olivier Dionne
|
||||
|
/// @date 2008-10-19
|
||||
|
///
|
||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||
|
class FBO |
||||
|
{ |
||||
|
public: |
||||
|
/// Constructeur par défaut
|
||||
|
FBO(); |
||||
|
/// destructeur par défaut
|
||||
|
~FBO(); |
||||
|
|
||||
|
/// Initialise le FBO et crée une texture de rendu pour RGB et pour DepthBuffer
|
||||
|
void Init( int w, int h ); |
||||
|
|
||||
|
/// Libère la mémoire openGL
|
||||
|
void Liberer(); |
||||
|
/// Commencement de la capture des instruction openGL réalisant le contenu du FBO
|
||||
|
void CommencerCapture(); |
||||
|
/// fin de la description du contenu du FBO
|
||||
|
void TerminerCapture(); |
||||
|
/// Retourne la largeur de la texture
|
||||
|
inline int GetWidth() const { return m_TextureW; } |
||||
|
/// Retourne la hauteur de la texture
|
||||
|
inline int GetHeight() const { return m_TextureH; } |
||||
|
/// Retourne l'ID de texture de couleur
|
||||
|
inline GLuint GetRGBTex() const { return m_Texture; } |
||||
|
/// Retourne la hauteur de la texture
|
||||
|
inline GLuint GetDepthTex() const { return m_Profondeur; } |
||||
|
|
||||
|
private: |
||||
|
|
||||
|
/// l'ID du FBO
|
||||
|
GLuint m_FBO; |
||||
|
/// l'ID de la texture RGB
|
||||
|
GLuint m_Texture; |
||||
|
/// l'ID de la texture profondeur
|
||||
|
GLuint m_Profondeur; |
||||
|
/// le format interne (communément GL_RGB)
|
||||
|
GLint m_InternalFormat; |
||||
|
/// la cible de la texture (communément GL_TEXTURE2D)
|
||||
|
GLenum m_Target; |
||||
|
|
||||
|
/// la largeur de la texture
|
||||
|
int m_TextureW; |
||||
|
/// la hauteur de la texture
|
||||
|
int m_TextureH; |
||||
|
}; |
||||
|
|
||||
@ -0,0 +1,141 @@ |
|||||
|
/* See LICENSE file for copyright and license details. */ |
||||
|
#include <GL/glew.h> |
||||
|
#include <SDL2/SDL.h> |
||||
|
#include <stdarg.h> |
||||
|
#include <stdio.h> |
||||
|
#include <stdlib.h> |
||||
|
#include <string.h> |
||||
|
|
||||
|
#include "util.h" |
||||
|
|
||||
|
void * |
||||
|
ecalloc(size_t nmemb, size_t size) |
||||
|
{ |
||||
|
void *p; |
||||
|
|
||||
|
if (!(p = calloc(nmemb, size))) |
||||
|
die("calloc:"); |
||||
|
return p; |
||||
|
} |
||||
|
|
||||
|
void |
||||
|
die(const char *fmt, ...) { |
||||
|
va_list ap; |
||||
|
|
||||
|
va_start(ap, fmt); |
||||
|
vfprintf(stderr, fmt, ap); |
||||
|
va_end(ap); |
||||
|
|
||||
|
if (fmt[0] && fmt[strlen(fmt)-1] == ':') { |
||||
|
fputc(' ', stderr); |
||||
|
perror(NULL); |
||||
|
} else { |
||||
|
fputc('\n', stderr); |
||||
|
} |
||||
|
|
||||
|
exit(1); |
||||
|
} |
||||
|
|
||||
|
void |
||||
|
infogl(const int verbose) |
||||
|
{ |
||||
|
#define PBYTE(CHAINE) ( (CHAINE) != NULL ? (CHAINE) : (const GLubyte *) "????" ) |
||||
|
#define PCHAR(CHAINE) ( (CHAINE) != NULL ? (CHAINE) : (const char *) "????" ) |
||||
|
SDL_version linked; |
||||
|
SDL_GetVersion( &linked ); |
||||
|
printf("// SDL %u.%u.%u\n", linked.major, linked.minor, linked.patch); |
||||
|
|
||||
|
printf("// OpenGL %s%s\n", PBYTE(glGetString(GL_VERSION)), PBYTE(glGetString(GL_VENDOR))); |
||||
|
printf("// GPU %s\n", PBYTE(glGetString(GL_RENDERER))); |
||||
|
printf("// GLSL %s\n", PBYTE(glGetString(GL_SHADING_LANGUAGE_VERSION))); |
||||
|
|
||||
|
if (verbose) |
||||
|
printf("// extensions = %s\n", PBYTE(glGetString(GL_EXTENSIONS))); |
||||
|
#undef PBYTE |
||||
|
#undef PCHAR |
||||
|
} |
||||
|
|
||||
|
void |
||||
|
sdldie(const char *msg) |
||||
|
{ |
||||
|
fprintf(stderr, "sdldie: %s: %s\n",msg, SDL_GetError()); |
||||
|
SDL_Quit(); |
||||
|
exit(1); |
||||
|
} |
||||
|
|
||||
|
void |
||||
|
sdlerrcheck(int line) |
||||
|
{ |
||||
|
const char *sdlerror = SDL_GetError(); |
||||
|
if ( *sdlerror != '\0' ) |
||||
|
{ |
||||
|
fprintf(stderr,"SDL Error: l.%d: %s\n",line, sdlerror); |
||||
|
SDL_ClearError(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
int |
||||
|
checkglerr(const char *msg, const int line) |
||||
|
{ |
||||
|
const char *errors[7] = { |
||||
|
"GL_INVALID_ENUM", |
||||
|
"GL_INVALID_VALUE", |
||||
|
"GL_INVALID_OPERATION", |
||||
|
"GL_STACK_OVERFLOW", |
||||
|
"GL_STACK_UNDERFLOW", |
||||
|
"GL_OUT_OF_MEMORY", |
||||
|
"GL_INVALID_FRAMEBUFFER_OPERATION", |
||||
|
}; |
||||
|
int rc = 0; |
||||
|
GLenum err; |
||||
|
while ((err = glGetError()) != GL_NO_ERROR) |
||||
|
{ |
||||
|
if (err >= GL_INVALID_ENUM && err <= GL_INVALID_FRAMEBUFFER_OPERATION) |
||||
|
fprintf(stderr, "%s l.%d\n", errors[err - GL_INVALID_ENUM], line); |
||||
|
else |
||||
|
fprintf(stderr, "Unknown error l.%d\n", line); |
||||
|
++rc; |
||||
|
} |
||||
|
return rc; |
||||
|
} |
||||
|
|
||||
|
void |
||||
|
printcomplog(GLuint shaderobj) |
||||
|
{ |
||||
|
int logl; |
||||
|
char *log; |
||||
|
|
||||
|
glGetShaderiv(shaderobj, GL_INFO_LOG_LENGTH, &logl); |
||||
|
if (logl > 0) { |
||||
|
log = (char*)malloc(sizeof(char) * logl); |
||||
|
if (!log) |
||||
|
die("Cannot allocate %d bytes for shader log\n", logl); |
||||
|
glGetShaderInfoLog(shaderobj, logl, NULL, log); |
||||
|
fprintf(stderr, "\n%s\n", log); |
||||
|
free(log); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void |
||||
|
printprogramlog(GLuint prog) |
||||
|
{ |
||||
|
int logl; |
||||
|
char *log; |
||||
|
|
||||
|
glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logl); |
||||
|
if (logl > 0) { |
||||
|
log = (char*)malloc(sizeof(char) * logl); |
||||
|
if (!log) |
||||
|
die("Cannot allocate %d bytes for program log\n", logl); |
||||
|
glGetProgramInfoLog(prog, logl, NULL, log); |
||||
|
fprintf(stderr, "\n%s\n", log); |
||||
|
free(log); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void |
||||
|
debugcallback(GLenum source, GLenum type, GLuint id, |
||||
|
GLenum severity, GLsizei length, const GLchar* message, const void* userParam) |
||||
|
{ |
||||
|
printf("%s\n", message); |
||||
|
} |
||||
@ -0,0 +1,18 @@ |
|||||
|
#include <GL/glew.h> |
||||
|
/* See LICENSE file for copyright and license details. */ |
||||
|
|
||||
|
#define MAX(A, B) ((A) > (B) ? (A) : (B)) |
||||
|
#define MIN(A, B) ((A) < (B) ? (A) : (B)) |
||||
|
#define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B)) |
||||
|
#define LENGTH(X) (sizeof X / sizeof X[0]) |
||||
|
|
||||
|
int checkglerr(const char *msg, const int line); |
||||
|
void die(const char *fmt, ...); |
||||
|
void *ecalloc(size_t nmemb, size_t size); |
||||
|
void infogl(const int verbose); |
||||
|
void sdldie(const char *msg); |
||||
|
void sdlerrcheck(int line); |
||||
|
void printcomplog(GLuint shaderobj); |
||||
|
void printprogramlog(GLuint prog); |
||||
|
void debugcallback(GLenum source, GLenum type, GLuint id, |
||||
|
GLenum severity, GLsizei length, const GLchar* message, const void* userParam); |
||||
Loading…
Reference in new issue