295 lines
8.6 KiB
C++
295 lines
8.6 KiB
C++
#include "GPU_physics.h"
|
|
|
|
// #define FBO_USE_NVIDIA_FLOAT_TEXTURE_EXTENSION 1
|
|
#include "fboSupport.h"
|
|
|
|
#ifdef FBO_USE_NVIDIA_FLOAT_TEXTURE_EXTENSION
|
|
|
|
/* nVidia float texture extension */
|
|
#define FBO_R_HALFFLOAT GL_FLOAT_R16_NV
|
|
#define FBO_RG_HALFFLOAT GL_FLOAT_RG16_NV
|
|
#define FBO_RGB_HALFFLOAT GL_FLOAT_RGB16_NV
|
|
#define FBO_RGBA_HALFFLOAT GL_FLOAT_RGBA16_NV
|
|
|
|
#define FBO_R_FLOAT GL_FLOAT_R32_NV
|
|
#define FBO_RG_FLOAT GL_FLOAT_RG32_NV
|
|
#define FBO_RGB_FLOAT GL_FLOAT_RGB32_NV
|
|
#define FBO_RGBA_FLOAT GL_FLOAT_RGBA32_NV
|
|
|
|
#else
|
|
|
|
/* ATI float texture extension */
|
|
#define FBO_R_HALFFLOAT GL_LUMINANCE_FLOAT16_ATI
|
|
#define FBO_RG_HALFFLOAT GL_LUMINANCE_ALPHA_FLOAT16_ATI
|
|
#define FBO_RGB_HALFFLOAT GL_RGB_FLOAT16_ATI
|
|
#define FBO_RGBA_HALFFLOAT GL_RGBA_FLOAT16_ATI
|
|
|
|
#define FBO_R_FLOAT GL_LUMINANCE_FLOAT32_ATI
|
|
#define FBO_RG_FLOAT GL_LUMINANCE_ALPHA_FLOAT32_ATI
|
|
#define FBO_RGB_FLOAT GL_RGB_FLOAT32_ATI
|
|
#define FBO_RGBA_FLOAT GL_RGBA_FLOAT32_ATI
|
|
|
|
#endif
|
|
|
|
static void checkFrameBufferStatus ()
|
|
{
|
|
GLenum status ;
|
|
|
|
status = glCheckFramebufferStatusEXT ( GL_FRAMEBUFFER_EXT ) ;
|
|
|
|
switch ( status )
|
|
{
|
|
case GL_FRAMEBUFFER_COMPLETE_EXT :
|
|
break ;
|
|
|
|
case GL_FRAMEBUFFER_UNSUPPORTED_EXT :
|
|
fprintf ( stderr, "ERROR: Unsupported FBO setup.\n" ) ;
|
|
exit ( 1 ) ;
|
|
|
|
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT :
|
|
fprintf ( stderr, "WARNING: Incomplete FBO setup.\n" ) ;
|
|
break ;
|
|
|
|
default :
|
|
fprintf ( stderr, "WARNING: Unexpected FBO status : 0x%04x\n", status ) ;
|
|
break ;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
FrameBufferObject::FrameBufferObject ( int _width ,
|
|
int _height,
|
|
int _ncomps,
|
|
fboDataType _type )
|
|
{
|
|
if ( (_width & (_width-1)) == 0 )
|
|
width = _width ;
|
|
else
|
|
{
|
|
fprintf ( stderr, "FBO: Non-power of two width!\n" ) ;
|
|
width = 512 ;
|
|
}
|
|
|
|
if ( (_height & (_height-1)) == 0 )
|
|
height = _height ;
|
|
else
|
|
{
|
|
fprintf ( stderr, "FBO: Non-power of two height!\n" ) ;
|
|
width = 512 ;
|
|
}
|
|
|
|
ncomps = _ncomps ;
|
|
type = _type ;
|
|
|
|
switch ( ncomps )
|
|
{
|
|
case 1 : format = GL_LUMINANCE ; break ;
|
|
case 2 : format = GL_LUMINANCE_ALPHA ; break ;
|
|
case 3 : format = GL_RGB ; break ;
|
|
case 4 : format = GL_RGBA ; break ;
|
|
default: fprintf ( stderr, "Illegal number of components"
|
|
" in a FrameBufferObject.\n" ) ;
|
|
ncomps = 4 ; format = GL_RGBA ; break ;
|
|
}
|
|
|
|
|
|
switch ( type )
|
|
{
|
|
case FBO_BYTE :
|
|
case FBO_UNSIGNED_BYTE : iformat = format ; break ;
|
|
|
|
case FBO_INT :
|
|
case FBO_UNSIGNED_INT :
|
|
fprintf ( stderr, "FBO: GL_INT/GL_UINT textures are unsupported,"
|
|
" truncating to 16 bits per component" ) ;
|
|
/* FALL THROUGH */
|
|
case FBO_SHORT :
|
|
case FBO_UNSIGNED_SHORT :
|
|
switch ( ncomps )
|
|
{
|
|
case 1 : iformat = GL_LUMINANCE16 ; break ;
|
|
case 2 : iformat = GL_LUMINANCE16_ALPHA16 ; break ;
|
|
case 3 : iformat = GL_RGB16 ; break ;
|
|
case 4 : iformat = GL_RGBA16 ; break ;
|
|
}
|
|
break ;
|
|
|
|
case FBO_DOUBLE :
|
|
fprintf ( stderr, "FBO: GL_DOUBLE textures are unsupported,"
|
|
" truncating to GL_FLOAT per component" ) ;
|
|
/* FALL THROUGH */
|
|
case FBO_FLOAT :
|
|
switch ( ncomps )
|
|
{
|
|
case 1 : iformat = FBO_R_FLOAT ; break ;
|
|
case 2 : iformat = FBO_RG_FLOAT ; break ;
|
|
case 3 : iformat = FBO_RGB_FLOAT ; break ;
|
|
case 4 : iformat = FBO_RGBA_FLOAT ; break ;
|
|
}
|
|
break ;
|
|
|
|
case FBO_HALF :
|
|
switch ( ncomps )
|
|
{
|
|
case 1 : iformat = FBO_R_HALFFLOAT ; break ;
|
|
case 2 : iformat = FBO_RG_HALFFLOAT ; break ;
|
|
case 3 : iformat = FBO_RGB_HALFFLOAT ; break ;
|
|
case 4 : iformat = FBO_RGBA_HALFFLOAT ; break ;
|
|
}
|
|
break ;
|
|
|
|
default :
|
|
fprintf ( stderr, "FBO: Unsupported data type?!?" ) ;
|
|
break ;
|
|
}
|
|
|
|
glGenTextures ( 1, & textureHandle ) ;
|
|
|
|
glBindTexture ( GL_TEXTURE_2D, textureHandle ) ;
|
|
glTexParameterf ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ) ;
|
|
glTexParameterf ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ) ;
|
|
|
|
fillTexture ( (void *) NULL ) ;
|
|
|
|
glGenFramebuffersEXT ( 1, & fboHandle ) ;
|
|
glGenRenderbuffersEXT ( 1, & depth_rb ) ;
|
|
glBindFramebufferEXT ( GL_FRAMEBUFFER_EXT, fboHandle ) ;
|
|
|
|
glFramebufferTexture2DEXT ( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
|
|
GL_TEXTURE_2D, textureHandle, 0 ) ;
|
|
|
|
// initialize depth renderbuffer
|
|
|
|
glBindRenderbufferEXT ( GL_RENDERBUFFER_EXT, depth_rb ) ;
|
|
glRenderbufferStorageEXT ( GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24,
|
|
width, height ) ;
|
|
glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
|
|
GL_RENDERBUFFER_EXT, depth_rb ) ;
|
|
|
|
#ifdef NEED_STENCIL_BUFFER
|
|
static GLuint stencil_rb ;
|
|
glGenRenderbuffersEXT ( 1, & stencil_rb ) ;
|
|
// initialize stencil renderbuffer
|
|
glBindRenderbufferEXT ( GL_RENDERBUFFER_EXT, stencil_rb ) ;
|
|
glRenderbufferStorageEXT ( GL_RENDERBUFFER_EXT, GL_STENCIL_INDEX, width, height ) ;
|
|
glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
|
|
GL_RENDERBUFFER_EXT, stencil_rb ) ;
|
|
#else
|
|
glDisable ( GL_STENCIL_TEST ) ;
|
|
#endif
|
|
|
|
// Check framebuffer completeness at the end of initialization.
|
|
|
|
checkFrameBufferStatus () ;
|
|
restoreFrameBuffer () ;
|
|
}
|
|
|
|
|
|
|
|
void FrameBufferObject::fetchTexture ( void *data )
|
|
{
|
|
glBindTexture ( GL_TEXTURE_2D, textureHandle ) ;
|
|
glGetTexImage ( GL_TEXTURE_2D, 0, /* MIP level...zero */
|
|
format, /* External format */
|
|
type, /* Data type */
|
|
data /* Image data */ ) ;
|
|
}
|
|
|
|
|
|
|
|
void FrameBufferObject::fetchTexture ( unsigned char *data )
|
|
{
|
|
if ( type != FBO_UNSIGNED_BYTE )
|
|
{
|
|
fprintf ( stderr, "FBO: Data format mismatch!" ) ;
|
|
return ;
|
|
}
|
|
|
|
fetchTexture ( (void *)data ) ;
|
|
}
|
|
|
|
|
|
|
|
void FrameBufferObject::fetchTexture ( float *data )
|
|
{
|
|
if ( type != FBO_FLOAT )
|
|
{
|
|
fprintf ( stderr, "FBO: Data format mismatch!" ) ;
|
|
return ;
|
|
}
|
|
|
|
fetchTexture ( (void *)data ) ;
|
|
}
|
|
|
|
|
|
|
|
void FrameBufferObject::fillTexture ( void *data )
|
|
{
|
|
glBindTexture( GL_TEXTURE_2D, textureHandle ) ;
|
|
glTexImage2D ( GL_TEXTURE_2D, 0, /* MIP level...zero */
|
|
iformat, /* Internal format */
|
|
width, height, /* Size */
|
|
0, /* Border...false */
|
|
format, /* External format */
|
|
type, /* Data type */
|
|
data /* Image data */ ) ;
|
|
}
|
|
|
|
|
|
|
|
void FrameBufferObject::fillTexture ( unsigned char *data )
|
|
{
|
|
if ( type != FBO_UNSIGNED_BYTE )
|
|
{
|
|
fprintf ( stderr, "FBO: Data format mismatch!" ) ;
|
|
return ;
|
|
}
|
|
|
|
fillTexture ( (void *)data ) ;
|
|
}
|
|
|
|
void FrameBufferObject::fillTexture ( float *data )
|
|
{
|
|
if ( type != FBO_FLOAT )
|
|
{
|
|
fprintf ( stderr, "FBO: Data format mismatch!" ) ;
|
|
return ;
|
|
}
|
|
|
|
fillTexture ( (void *)data ) ;
|
|
}
|
|
|
|
|
|
void FrameBufferObject::paint ()
|
|
{
|
|
makeDestination () ;
|
|
|
|
glViewport ( 0, 0, width, height ) ;
|
|
|
|
glMatrixMode ( GL_PROJECTION ) ;
|
|
glLoadIdentity () ;
|
|
glOrtho ( -1, 1, -1, 1, -1, 1 ) ;
|
|
|
|
glMatrixMode ( GL_MODELVIEW ) ;
|
|
glLoadIdentity () ;
|
|
|
|
glDisable ( GL_DEPTH_TEST ) ;
|
|
glDisable ( GL_CULL_FACE ) ;
|
|
glDisable ( GL_BLEND ) ;
|
|
|
|
float s_min = 0.5f / (float) width ;
|
|
float s_max = (((float) width) - 0.5f) / (float) width ;
|
|
float t_min = 0.5f / (float) height ;
|
|
float t_max = (((float) height) - 0.5f) / (float) height ;
|
|
|
|
glBegin ( GL_QUADS ) ;
|
|
glTexCoord2f ( s_min, t_min ) ; glVertex2f ( -1, -1 ) ;
|
|
glTexCoord2f ( s_max, t_min ) ; glVertex2f ( 1, -1 ) ;
|
|
glTexCoord2f ( s_max, t_max ) ; glVertex2f ( 1, 1 ) ;
|
|
glTexCoord2f ( s_min, t_max ) ; glVertex2f ( -1, 1 ) ;
|
|
glEnd () ;
|
|
}
|
|
|
|
|