moved a few Extras projects into Extras/obsolete.

This commit is contained in:
erwin.coumans
2008-11-17 21:05:22 +00:00
parent fe461296c6
commit 50f475feb5
209 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,52 @@
(Add new stuff at the top!)
Sept 27th:
==========
* Added a 'collisionMap' and pre-populated it with the handles of
four of the cubes (which are coloured RED so you can see them).
* Non-red cubes are painted in shades of blue/green.
* Every cube (including the red ones) is gravitationally attracted
to all four red cubes in inverse proportion to their ranges.
Sept 9th:
=========
* Merged in my latest changes into SVN repository.
* Arranged to avoid reading/writing textures at same time.
* Removed depth and stencil buffers from FBO's.
* Eliminated 1-component FBO that caused grief for FBO completeness test.
* Added back missing cubeShaderNoTexture.vert
------------------- FIRST ADDITION TO SUBVERSION ---------------------
GPUphysics-0.4
==============
* Test for availability of vertex shader textures.
* Fixed 'status: xxxx' message.
* Added support for running the demo in the absence of vertex shader textures.
GPUphysics-0.3
==============
* Use signed initial velocities so everything doesn't slide off the screen!
* The 'bounce' now slows down X/Z motion as well as Y so things actually
do stop moving eventually.
* Caught up with some portability issues for more recent versions of
GLSL.
GPUphysics-0.2
==============
* Added MacOSX support.
* Added a ton of command-line debug options (see DEBUG_README)
* Changed to ZLib license.
GPUphysics-0.1
==============
* Fixes for stencil buffer problems on some systems.
GPUphysics-0.0
==============
* Initial release

View File

@@ -0,0 +1,67 @@
PROJECT(GPUphysics)
# This is basically the overall name of the project in Visual Studio this is the name of the Solution File
# For every executable you have with a main method you should have an add_executable line below.
# For every add executable line you should list every .cpp and .h file you have associated with that executable.
# This is the variable for Windows. I use this to define the root of my directory structure.
SET(GLUT_ROOT ${GPUphysics_SOURCE_DIR}/../../Glut)
# You shouldn't have to modify anything below this line
########################################################
# This is the shortcut to finding GLU, GLUT and OpenGL if they are properly installed on your system
# This should be the case.
INCLUDE (${CMAKE_ROOT}/Modules/FindGLU.cmake)
INCLUDE (${CMAKE_ROOT}/Modules/FindGLUT.cmake)
INCLUDE (${CMAKE_ROOT}/Modules/FindOpenGL.cmake)
IF (WIN32)
# This is the Windows code for which Opengl, and Glut are not properly installed
# since I can't install them I must cheat and copy libraries around
INCLUDE_DIRECTORIES(${GLUT_ROOT})
# LINK_DIRECTORIES(${GLUT_ROOT}\\lib)
IF (${GLUT_glut_LIBRARY} MATCHES "GLUT_glut_LIBRARY-NOTFOUND")
SET(GLUT_glut_LIBRARY ${GPUphysics_SOURCE_DIR}/Glut/glut32.lib)
# LINK_LIBRARIES(${GLUT_ROOT}\\lib\\glut32 ${OPENGL_gl_LIBRARY} ${OPENGL_glU_LIBRARY})
# TARGET_LINK_LIBRARIES(table ${GLUT_ROOT}\\lib\\glut32)
#
# ADD_CUSTOM_COMMAND(TARGET table POST_BUILD COMMAND copy ${GLUT_ROOT}\\lib\\glut32.dll ${GLUT_ROOT}\\bin\\vs2005\\Debug
# COMMAND copy ${GLUT_ROOT}\\lib\\glut32.dll ${GLUT_ROOT}\\bin\\vs2003\\Debug
# COMMAND copy ${GLUT_ROOT}\\lib\\glut32.dll ${GLUT_ROOT}\\bin\\vs6\\Debug)
ELSE (${GLUT_glut_LIBRARY} MATCHES "GLUT_glut_LIBRARY-NOTFOUND")
# LINK_LIBRARIES(${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glU_LIBRARY})
# TARGET_LINK_LIBRARIES(table ${GLUT_glut_LIBRARY})
ENDIF(${GLUT_glut_LIBRARY} MATCHES "GLUT_glut_LIBRARY-NOTFOUND")
# TARGET_LINK_LIBRARIES(table ${OPENGL_gl_LIBRARY})
# TARGET_LINK_LIBRARIES(table ${OPENGL_glu_LIBRARY})
ELSE (WIN32)
# This is the lines for linux. This should always work if everything is installed and working fine.
# SET(CMAKE_BUILD_TYPE Debug)
# SET(CMAKE_CXX_FLAGS_DEBUG "-g")
INCLUDE_DIRECTORIES(/usr/include /usr/local/include ${GLUT_INCLUDE_DIR})
# TARGET_LINK_LIBRARIES(table ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glU_LIBRARY})
# TARGET_LINK_LIBRARIES(checker ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glU_LIBRARY})
ENDIF (WIN32)
INCLUDE_DIRECTORIES(
../../Glut/GL/include
)
LINK_LIBRARIES(
../../Glut/glew/lib/glew32.lib ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glU_LIBRARY}
)
ADD_EXECUTABLE(GPUphysics
clock.cpp
fboSupport.cpp
GPU_physics_demo.cpp
shaderSupport.cpp
)

View File

@@ -0,0 +1,43 @@
I have added some command line options to hopefully
help with our debugging problems.
1) Run without any shaders at all:
GPU_physics_demo -s
This should produce a grey screen with a neat grid of randomly
coloured cubes that are sitting completely motionless. If this
doesn't work then render-to-texture and shaders are not the
problem and we have some very basic OpenGL problem to worry
about.
2) Run with just one shader - but no render-to-texture:
GPU_physics_demo -p
Just like '-s', this should produce a grey screen with a neat
grid of randomly coloured cubes that are sitting completely
motionless. This time, the vertex shader is reading the
positioning information from a texturemap. If this
doesn't work then render-to-texture isn't the problem but
something is amiss in shader-land.
There are several possibilities - the nastiest of which might
be that your graphics card/driver doesn't support floating point
textures. (This is pretty much 'Game Over' for you because
without that, doing physics in the GPU is going to be
virtually impossible).
3) Run without vertex texturing:
GPU_physics_demo -v
On hardware that doesn't support vertex texturing, this flag
is turned on by default (and things run about 5x slower!)
Use this flag to force the software to run without vertex
texturing on hardware that does actually support it.
You can use this flag in conjunction with any of the others.

View File

@@ -0,0 +1,116 @@
/**********************\
* *
* Determine OS type *
* *
\**********************/
#if defined(__CYGWIN__)
#define GPUP_WIN32 1
#define GPUP_CYGWIN 1 /* Windoze AND Cygwin. */
#elif defined(_WIN32) || defined(__WIN32__) || defined(_MSC_VER)
#define GPUP_WIN32 1
#define GPUP_MSVC 1 /* Windoze AND MSVC. */
#elif defined(__BEOS__)
#define GPUP_BEOS 1
#elif defined( macintosh )
#define GPUP_MACINTOSH 1
#elif defined(__APPLE__)
#define GPUP_MAC_OSX 1
#elif defined(__linux__)
#define GPUP_LINUX 1
#elif defined(__sgi)
#define GPUP_IRIX 1
#elif defined(_AIX)
#define GPUP_AIX 1
#elif defined(SOLARIS) || defined(sun)
#define GPUP_SOLARIS 1
#elif defined(hpux)
#define GPUP_HPUX 1
#elif (defined(__unix__) || defined(unix)) && !defined(USG)
#define GPUP_BSD 1
#endif
#if defined(BORLANDBUILDER)
#define GPUP_BB 1
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
Add specialised includes/defines...
*/
#ifdef GPUP_WIN32
#include <windows.h>
#include <mmsystem.h>
#include <regstr.h>
#define GPUP_WGL 1
#endif
#ifdef GPUP_CYGWIN
#include <unistd.h>
#define GPUP_WGL 1
#endif
#ifdef GPUP_BEOS
#include <be/kernel/image.h>
#define GPUP_GLX 1
#endif
#ifdef GPUP_MACINTOSH
#include <CodeFragments.h>
#include <unistd.h>
#define GPUP_AGL 1
#endif
#ifdef GPUP_MAC_OSX
#include <unistd.h>
#define GPUP_CGL 1
#endif
#if defined(GPUP_LINUX) || defined(GPUP_BSD) || defined(GPUP_IRIX) || defined(GPUP_SOLARIS) || defined(GPUP_AIX)
#include <unistd.h>
#include <dlfcn.h>
#include <fcntl.h>
#define GPUP_GLX 1
#endif
#if defined(GPUP_BSD)
#include <sys/param.h>
#define GPUP_GLX 1
#endif
#include <assert.h>
#include <limits.h>
#include <math.h>
#include <float.h>
#include <errno.h>
#if defined(GPUP_MAC_OSX) && !defined (VMDMESA)
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#include <GLUT/glut.h>
#include <OpenGL/glext.h>
#else
#include <GL/glew.h>
#include <GL/gl.h>
#include <GL/glut.h>
#endif
#ifdef DISABLE_GL_ERROR_CHECKS
inline void showGLerror ( const char * ) {}
#else
inline void showGLerror ( const char *msg )
{
GLenum err ;
while ( (err = glGetError()) != GL_NO_ERROR )
fprintf ( stderr, "%s: OpenGL Error - %s\n", msg, gluErrorString ( err ) ) ;
}
#endif

View File

@@ -0,0 +1,949 @@
#include "GPU_physics.h"
#include "fboSupport.h"
#include "shaderSupport.h"
#include "clock.h"
#define TIMESTEP 0.016f
enum DebugOptions
{
DRAW_WITHOUT_SHADERS,
DRAW_WITHOUT_PHYSICS,
DRAW_ALL
} ;
static float *positionData = NULL ;
static float *rotationData = NULL ;
static float *collisionData = NULL ;
static bool noVertexTextureSupport = false ;
static DebugOptions debugOpt = DRAW_ALL ;
void checkVertexTextureSupport ( bool disableVertexTextureSupport )
{
GLint nVertTextures ;
GLint nFragTextures ;
GLint nCombTextures ;
glGetIntegerv ( GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, & nVertTextures ) ;
glGetIntegerv ( GL_MAX_TEXTURE_IMAGE_UNITS, & nFragTextures ) ;
glGetIntegerv ( GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, & nCombTextures ) ;
fprintf(stderr, "INFO: This hardware supports at most:\n"
" %2d vert texture samplers\n"
" %2d frag texture samplers\n"
" %2d total texture samplers\n",
nVertTextures, nFragTextures, nCombTextures ) ;
noVertexTextureSupport = ( nVertTextures < 2 ) ;
if ( noVertexTextureSupport && debugOpt != DRAW_WITHOUT_SHADERS )
{
fprintf ( stderr, "\n"
"********************************************\n"
"* *\n"
"* WARNING: This graphics card doesn't have *\n"
"* vertex shader texture support - a work- *\n"
"* around will be used - but this demo will *\n"
"* be much less impressive as a result! *\n"
"* *\n"
"********************************************\n\n" ) ;
}
if ( ! noVertexTextureSupport && disableVertexTextureSupport )
{
fprintf ( stderr, "WARNING: Vertex Texture Support has"
"been disabled from the command line.\n" ) ;
noVertexTextureSupport = true ;
}
}
int irand ( int max )
{
return rand() % max ;
}
float frand ( float max )
{
return (float)(rand() % 32767) * max / 32767.0f ;
}
static GLSL_ShaderPair *velocityGenerator ;
static GLSL_ShaderPair *positionGenerator ;
static GLSL_ShaderPair *grndCollisionGenerator ;
static GLSL_ShaderPair *collisionGenerator ;
static GLSL_ShaderPair *forceGenerator ;
static GLSL_ShaderPair *cubeShader ;
static FrameBufferObject *position ;
static FrameBufferObject *rotation ;
static FrameBufferObject *velocity ;
static FrameBufferObject *rotvelocity ;
static FrameBufferObject *force ;
static FrameBufferObject *new_force ;
static FrameBufferObject *massSizeX ;
static FrameBufferObject *old ;
static FrameBufferObject *collisions ;
#define TEX_SIZE 16
#define NUM_CUBES ( TEX_SIZE * TEX_SIZE )
#define STRIPS_PER_CUBE 2
#define VERTS_PER_STRIP 8
#define NUM_VERTS ( NUM_CUBES * STRIPS_PER_CUBE * VERTS_PER_STRIP )
static GLuint vbo_vx = 0 ;
static GLuint vbo_tx = 0 ;
static GLuint vbo_co = 0 ;
static float vertices [ NUM_VERTS * 3 ] ;
static float texcoords [ NUM_VERTS * 2 ] ;
static float colours [ NUM_VERTS * 4 ] ;
static int starts [ NUM_CUBES * STRIPS_PER_CUBE ] ;
static int lengths [ NUM_CUBES * STRIPS_PER_CUBE ] ;
static GLuint vbo_collvx = 0 ;
static GLuint vbo_collt0 = 0 ;
static GLuint vbo_collt1 = 0 ;
static float collvertices [ NUM_CUBES * 4 * 3 ] ;
static float colltexcoords0 [ NUM_CUBES * 4 * 2 ] ;
static float colltexcoords1 [ NUM_CUBES * 4 * 2 ] ;
static int collstart ;
static int colllength ;
static int win_width = 640 ;
static int win_height = 480 ;
inline int idToIndex ( int x, int y )
{
/*
Convert a coordinate pair within the texture to an integer
1D array index (eg to index into the data array for that texture)
by multiplying the Y coordinate by the width of the texture and
adding the X coordinate.
*/
return y * TEX_SIZE + x ;
}
inline float idToFloat ( int x, int y )
{
/*
Convert a coordinate pair within the texture to a float
by putting one coordinate into the integer part and the
other into the fraction so we can retrieve Y using floor()
and X using fract() to recover them later on inside the shader.
*/
return ((float) idToIndex ( x, y )) / (float)TEX_SIZE ;
}
void keybd ( unsigned char, int, int )
{
exit ( 0 ) ;
}
void reshape ( int wid, int ht )
{
win_width = wid ;
win_height = ht ;
}
void initGLcontext ( int argc, char **argv,
void (*display)(void),
bool disableVertexTextureSupport )
{
glutInit ( &argc, argv ) ;
glutInitDisplayMode ( GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE ) ;
glutInitWindowSize ( win_width, win_height ) ;
glutCreateWindow ( "Shader Math Demo" ) ;
glutDisplayFunc ( display ) ;
glutKeyboardFunc ( keybd ) ;
glutReshapeFunc ( reshape ) ;
#if defined(GPUP_MAC_OSX) && !defined (VMDMESA)
#else
glewInit () ;
#endif
checkVertexTextureSupport ( disableVertexTextureSupport ) ;
}
void initMotionTextures ()
{
if ( debugOpt == DRAW_WITHOUT_SHADERS ) return ;
position = new FrameBufferObject ( TEX_SIZE, TEX_SIZE, 3, FBO_FLOAT ) ;
rotation = new FrameBufferObject ( TEX_SIZE, TEX_SIZE, 3, FBO_FLOAT ) ;
old = new FrameBufferObject ( TEX_SIZE, TEX_SIZE, 3, FBO_FLOAT ) ;
if ( debugOpt == DRAW_WITHOUT_PHYSICS )
{
velocity = NULL ;
rotvelocity = NULL ;
force = NULL ;
new_force = NULL ;
massSizeX = NULL ;
collisions = NULL ;
}
else
{
velocity = new FrameBufferObject ( TEX_SIZE, TEX_SIZE, 3, FBO_FLOAT ) ;
rotvelocity = new FrameBufferObject ( TEX_SIZE, TEX_SIZE, 3, FBO_FLOAT ) ;
force = new FrameBufferObject ( TEX_SIZE, TEX_SIZE, 3, FBO_FLOAT ) ;
new_force = new FrameBufferObject ( TEX_SIZE, TEX_SIZE, 3, FBO_FLOAT ) ;
massSizeX = new FrameBufferObject ( TEX_SIZE, TEX_SIZE, 3, FBO_FLOAT ) ;
collisions = new FrameBufferObject ( TEX_SIZE, TEX_SIZE, 3, FBO_FLOAT ) ;
}
positionData = new float [ TEX_SIZE * TEX_SIZE * 3 ] ;
rotationData = new float [ TEX_SIZE * TEX_SIZE * 3 ] ;
float *velocityData ;
float *rotvelocityData ;
float *forceData ;
float *massSizeXData ;
if ( debugOpt == DRAW_WITHOUT_PHYSICS )
{
velocityData = NULL ;
rotvelocityData = NULL ;
forceData = NULL ;
massSizeXData = NULL ;
collisionData = NULL ;
}
else
{
velocityData = new float [ TEX_SIZE * TEX_SIZE * 3 ] ;
rotvelocityData = new float [ TEX_SIZE * TEX_SIZE * 3 ] ;
forceData = new float [ TEX_SIZE * TEX_SIZE * 3 ] ;
massSizeXData = new float [ TEX_SIZE * TEX_SIZE * 3 ] ;
collisionData = new float [ TEX_SIZE * TEX_SIZE * 3 ] ;
}
/* Give the objects some initial position, rotation, mass, force, etc */
for ( int y = 0 ; y < TEX_SIZE ; y++ )
for ( int x = 0 ; x < TEX_SIZE ; x++ )
{
/*
Start the cubes on a nice, regular 5m grid, 10m above the ground
centered around the origin
*/
positionData [ idToIndex(x,y) * 3 + 0 ] = 5.0f * (float) (x - TEX_SIZE/2) ;
positionData [ idToIndex(x,y) * 3 + 1 ] = 0.0f ; // 10.0f ;
positionData [ idToIndex(x,y) * 3 + 2 ] = 5.0f * (float) (y - TEX_SIZE/2) ;
/* Zero their rotations */
rotationData [ idToIndex(x,y) * 3 + 0 ] = 0.0f ;
rotationData [ idToIndex(x,y) * 3 + 1 ] = 0.0f ;
rotationData [ idToIndex(x,y) * 3 + 2 ] = 0.0f ;
if ( debugOpt != DRAW_WITHOUT_PHYSICS )
{
/* Random (but predominantly upwards) velocities. */
if(irand(2)==0)
{
velocityData [ idToIndex(x,y) * 3 + 0 ] = frand ( 1.0f ) ;
velocityData [ idToIndex(x,y) * 3 + 1 ] = 0.0f ;
velocityData [ idToIndex(x,y) * 3 + 2 ] = frand ( 1.0f ) ;
}
else
{
velocityData [ idToIndex(x,y) * 3 + 0 ] = 0.0f ; //frand ( 10.0f ) - 5.0f;
velocityData [ idToIndex(x,y) * 3 + 1 ] = 0.0f ; //frand ( 100.0f ) ;
velocityData [ idToIndex(x,y) * 3 + 2 ] = 0.0f ; //frand ( 10.0f ) - 5.0f;
}
/* Random rotational velocities */
rotvelocityData [ idToIndex(x,y) * 3 + 0 ] = 0.0f ; //frand ( 3.0f ) ;
rotvelocityData [ idToIndex(x,y) * 3 + 1 ] = 0.0f ; //frand ( 3.0f ) ;
rotvelocityData [ idToIndex(x,y) * 3 + 2 ] = 0.0f ; //frand ( 3.0f ) ;
/* Zero forces */
forceData [ idToIndex(x,y) * 3 + 0 ] = 0.0f ;
forceData [ idToIndex(x,y) * 3 + 1 ] = 0.0f ;
forceData [ idToIndex(x,y) * 3 + 2 ] = 0.0f ;
/* One kg each */
massSizeXData [ idToIndex(x,y) * 3 + 0 ] = 0.05f ; /* Mass */
massSizeXData [ idToIndex(x,y) * 3 + 1 ] = 1.0f ; /* Radius */
massSizeXData [ idToIndex(x,y) * 3 + 2 ] = 0.0f ; /* Unused */
/* Zero out collision data */
collisionData [ idToIndex(x,y) * 3 + 0 ] = 0.0f ;
collisionData [ idToIndex(x,y) * 3 + 1 ] = 0.0f ;
collisionData [ idToIndex(x,y) * 3 + 2 ] = 0.0f ;
}
}
if ( debugOpt != DRAW_WITHOUT_PHYSICS )
{
/*
Object zero is the 'null' object for collision detection
so put it far away and stop it from moving around.
*/
positionData [ 0 ] = 1000000000.0f ;
positionData [ 1 ] = 1000000000.0f ;
positionData [ 2 ] = 1000000000.0f ;
velocityData [ 0 ] = 0.0f ;
velocityData [ 1 ] = 0.0f ;
velocityData [ 2 ] = 0.0f ;
massSizeXData [ 0 ] = 10000000.0f ; /* Mass */
massSizeXData [ 1 ] = 0.00000001f ; /* Radius */
massSizeXData [ 2 ] = 0.0f ; /* Unused */
collisionData [ 0 ] = 0.0f ;
collisionData [ 1 ] = 0.0f ;
collisionData [ 2 ] = 0.0f ;
}
/* Initialise the textures */
position -> fillTexture ( positionData ) ;
rotation -> fillTexture ( rotationData ) ;
old -> fillTexture ( positionData ) ; // Doesn't really need it...
if ( debugOpt != DRAW_WITHOUT_PHYSICS )
{
velocity -> fillTexture ( velocityData ) ;
rotvelocity -> fillTexture ( rotvelocityData ) ;
force -> fillTexture ( forceData ) ;
new_force -> fillTexture ( forceData ) ;
massSizeX -> fillTexture ( massSizeXData ) ;
collisions -> fillTexture ( collisionData ) ;
}
}
void initPhysicsShaders ()
{
if ( debugOpt == DRAW_WITHOUT_SHADERS ||
debugOpt == DRAW_WITHOUT_PHYSICS )
return ;
/*
The velocity generator shader calculates:
velocity = old_velocity + delta_T * ( F / m ) ;
*/
velocityGenerator = new GLSL_ShaderPair (
"VelocityGenerator",
NULL, NULL,
"uniform vec4 g_dt ;"
"uniform sampler2D old_velocity ;"
"uniform sampler2D force ;"
"uniform sampler2D massSizeX ;"
"void main() {"
" gl_FragColor = vec4 ("
" texture2D ( old_velocity, gl_TexCoord[0].st ).xyz +"
" g_dt.w * ( g_dt.xyz +"
" texture2D ( force , gl_TexCoord[0].st ).xyz /"
" texture2D ( massSizeX , gl_TexCoord[0].st ).x),"
" 1.0 ) ; }",
"VelocityGenerator Frag Shader" ) ;
assert ( velocityGenerator -> compiledOK () ) ;
/*
The position generater shader calculates:
position = old_position + delta_T * velocity ;
It's also used to update the rotational velocity.
*/
positionGenerator = new GLSL_ShaderPair (
"PositionGenerator",
NULL, NULL,
"uniform float delta_T ;"
"uniform sampler2D old_position ;"
"uniform sampler2D velocity ;"
"void main() {"
" gl_FragColor = vec4 ("
" texture2D ( old_position, gl_TexCoord[0].st ).xyz +"
" texture2D ( velocity , gl_TexCoord[0].st ).xyz *"
" delta_T,"
" 1.0 ) ; }",
"PositionGenerator Frag Shader" ) ;
assert ( positionGenerator -> compiledOK () ) ;
collisionGenerator = new GLSL_ShaderPair (
"CollisionGenerator",
NULL,
"collisionShader.frag" ) ;
assert ( collisionGenerator -> compiledOK () ) ;
forceGenerator = new GLSL_ShaderPair (
"ForceGenerator",
NULL, NULL,
"uniform sampler2D force ;"
"uniform sampler2D position ;"
"uniform sampler2D collisions ;"
"void main() {"
" vec3 last_force = texture2D ( force , gl_TexCoord[0].st ).xyz ;"
" vec2 id = texture2D ( collisions, gl_TexCoord[0].st ).xy ;"
" vec3 pos = texture2D ( position , gl_TexCoord[0].st ).xyz ;"
" vec3 rel = pos - texture2D ( position, id ).xyz ;"
" float lrel = max ( length ( rel ), 0.001 ) ;"
" gl_FragColor = vec4 ( last_force + (rel / lrel) / lrel, 1.0 ) ;"
"}",
"ForceGenerator Frag Shader" ) ;
assert ( forceGenerator -> compiledOK () ) ;
grndCollisionGenerator = new GLSL_ShaderPair (
"GroundCollisionGenerator",
NULL, NULL,
"uniform sampler2D position ;"
"uniform sampler2D old_velocity ;"
"void main() {"
" vec3 pos = texture2D ( position , gl_TexCoord[0].st ).xyz ;"
" vec3 vel = texture2D ( old_velocity, gl_TexCoord[0].st ).xyz ;"
" if ( pos [ 1 ] < 0.0 ) vel.y = abs(vel.y) ;"
" gl_FragColor = vec4 ( vel, 1.0 ) ; }",
"GroundCollisionGenerator Frag Shader" ) ;
assert ( grndCollisionGenerator -> compiledOK () ) ;
}
void initCollideVBO ()
{
float *p = collvertices ;
float *t0 = colltexcoords0 ;
float *t1 = colltexcoords1 ;
collstart = 0 ;
colllength = NUM_CUBES * 4 ;
for ( int y = 0 ; y < TEX_SIZE ; y++ )
for ( int x = 0 ; x < TEX_SIZE ; x++ )
{
/* Texcoord 0 data sets which corner of the texture this is. */
*t0++ = 0.5f /(float)TEX_SIZE ;
*t0++ = 0.5f /(float)TEX_SIZE ;
*t0++ = ((float)TEX_SIZE-0.5f)/(float)TEX_SIZE ;
*t0++ = 0.5f /(float)TEX_SIZE ;
*t0++ = ((float)TEX_SIZE-0.5f)/(float)TEX_SIZE ;
*t0++ = ((float)TEX_SIZE-0.5f)/(float)TEX_SIZE ;
*t0++ = 0.5f /(float)TEX_SIZE ;
*t0++ =((float)TEX_SIZE-0.5f)/(float)TEX_SIZE ;
/* Texcoord 1 sets which cube is which. */
*t1++ = ((float)x+0.5f)/(float)TEX_SIZE ;
*t1++ = ((float)y+0.5f)/(float)TEX_SIZE ;
*t1++ = ((float)x+0.5f)/(float)TEX_SIZE ;
*t1++ = ((float)y+0.5f)/(float)TEX_SIZE ;
*t1++ = ((float)x+0.5f)/(float)TEX_SIZE ;
*t1++ = ((float)y+0.5f)/(float)TEX_SIZE ;
*t1++ = ((float)x+0.5f)/(float)TEX_SIZE ;
*t1++ = ((float)y+0.5f)/(float)TEX_SIZE ;
*p++ = -1 ; *p++ = -1 ; *p++ = 0.0f ;
*p++ = +1 ; *p++ = -1 ; *p++ = 0.0f ;
*p++ = +1 ; *p++ = +1 ; *p++ = 0.0f ;
*p++ = -1 ; *p++ = +1 ; *p++ = 0.0f ;
}
glGenBuffersARB ( 1, & vbo_collvx ) ;
glBindBufferARB ( GL_ARRAY_BUFFER_ARB, vbo_collvx ) ;
glBufferDataARB ( GL_ARRAY_BUFFER_ARB, colllength * 3 * sizeof(float),
collvertices, GL_STATIC_DRAW_ARB ) ;
glGenBuffersARB ( 1, & vbo_collt0 ) ;
glBindBufferARB ( GL_ARRAY_BUFFER_ARB, vbo_collt0 ) ;
glBufferDataARB ( GL_ARRAY_BUFFER_ARB, colllength * 2 * sizeof(float),
colltexcoords0, GL_STATIC_DRAW_ARB ) ;
glGenBuffersARB ( 1, & vbo_collt1 ) ;
glBindBufferARB ( GL_ARRAY_BUFFER_ARB, vbo_collt1 ) ;
glBufferDataARB ( GL_ARRAY_BUFFER_ARB, colllength * 2 * sizeof(float),
colltexcoords1, GL_STATIC_DRAW_ARB ) ;
glBindBufferARB ( GL_ARRAY_BUFFER_ARB, 0 ) ;
}
void initCubeVBO ()
{
float *p = vertices ;
float *t = texcoords ;
float *c = colours ;
int nverts = 0 ;
for ( int k = 0 ;
k < (noVertexTextureSupport ? 1 : NUM_CUBES) * STRIPS_PER_CUBE ; k++ )
{
starts [ k ] = k * VERTS_PER_STRIP ;
lengths [ k ] = VERTS_PER_STRIP ;
}
for ( int y = 0 ; y < (noVertexTextureSupport ? 1 : TEX_SIZE) ; y++ )
for ( int x = 0 ; x < (noVertexTextureSupport ? 1 : TEX_SIZE) ; x++ )
{
/*
I use the colour data to set which cube is which in
the physics textures.
*/
for ( int k = 0 ; k < STRIPS_PER_CUBE * VERTS_PER_STRIP ; k++ )
{
*t++ = ((float)x+0.5f)/(float)TEX_SIZE ;
*t++ = ((float)y+0.5f)/(float)TEX_SIZE ;
if ( (x==20||x==100) && (y==20||y==100) )
{
*c++ = 1.0f ;
*c++ = 0.0f ;
*c++ = 0.0f ;
*c++ = 1.0f ;
}
else
{
*c++ = 0.0f ;
*c++ = frand ( 1.0f ) ;
*c++ = frand ( 1.0f ) ;
*c++ = 1.0f ;
}
}
float dx, dy, dz ;
if ( debugOpt == DRAW_WITHOUT_SHADERS )
{
dx = 5.0f * (float) (TEX_SIZE/2 - x) ;
dy = 10.0f ;
dz = 5.0f * (float) (TEX_SIZE/2 - y) ;
}
else
{
dx = 0.0f ;
dy = 0.0f ;
dz = 0.0f ;
}
*p++ = -1 + dx ; *p++ = -1 + dy ; *p++ = -1 + dz ;
*p++ = +1 + dx ; *p++ = -1 + dy ; *p++ = -1 + dz ;
*p++ = -1 + dx ; *p++ = +1 + dy ; *p++ = -1 + dz ;
*p++ = +1 + dx ; *p++ = +1 + dy ; *p++ = -1 + dz ;
*p++ = -1 + dx ; *p++ = +1 + dy ; *p++ = +1 + dz ;
*p++ = +1 + dx ; *p++ = +1 + dy ; *p++ = +1 + dz ;
*p++ = -1 + dx ; *p++ = -1 + dy ; *p++ = +1 + dz ;
*p++ = +1 + dx ; *p++ = -1 + dy ; *p++ = +1 + dz ;
*p++ = -1 + dx ; *p++ = +1 + dy ; *p++ = -1 + dz ;
*p++ = -1 + dx ; *p++ = +1 + dy ; *p++ = +1 + dz ;
*p++ = -1 + dx ; *p++ = -1 + dy ; *p++ = -1 + dz ;
*p++ = -1 + dx ; *p++ = -1 + dy ; *p++ = +1 + dz ;
*p++ = +1 + dx ; *p++ = -1 + dy ; *p++ = -1 + dz ;
*p++ = +1 + dx ; *p++ = -1 + dy ; *p++ = +1 + dz ;
*p++ = +1 + dx ; *p++ = +1 + dy ; *p++ = -1 + dz ;
*p++ = +1 + dx ; *p++ = +1 + dy ; *p++ = +1 + dz ;
nverts += STRIPS_PER_CUBE * VERTS_PER_STRIP ;
}
glGenBuffersARB ( 1, & vbo_vx ) ;
glBindBufferARB ( GL_ARRAY_BUFFER_ARB, vbo_vx ) ;
glBufferDataARB ( GL_ARRAY_BUFFER_ARB, nverts * 3 * sizeof(float),
vertices, GL_STATIC_DRAW_ARB ) ;
glGenBuffersARB ( 1, & vbo_tx ) ;
glBindBufferARB ( GL_ARRAY_BUFFER_ARB, vbo_tx ) ;
glBufferDataARB ( GL_ARRAY_BUFFER_ARB, nverts * 2 * sizeof(float),
texcoords, GL_STATIC_DRAW_ARB ) ;
glGenBuffersARB ( 1, & vbo_co ) ;
glBindBufferARB ( GL_ARRAY_BUFFER_ARB, vbo_co ) ;
glBufferDataARB ( GL_ARRAY_BUFFER_ARB, nverts * 4 * sizeof(float),
colours, GL_STATIC_DRAW_ARB ) ;
glBindBufferARB ( GL_ARRAY_BUFFER_ARB, 0 ) ;
if ( debugOpt == DRAW_WITHOUT_SHADERS )
cubeShader = NULL ;
else
{
if ( noVertexTextureSupport )
cubeShader = new GLSL_ShaderPair ( "CubeShader",
"cubeShaderNoTexture.vert",
"cubeShader.frag" ) ;
else
cubeShader = new GLSL_ShaderPair ( "CubeShader", "cubeShader.vert",
"cubeShader.frag" ) ;
assert ( cubeShader -> compiledOK () ) ;
}
}
void drawCubesTheHardWay ()
{
/*
Without vertex texture support, we have to read the position/rotation
data back from the hardware every frame and render each cube individually.
*/
float p0 = positionData [ 0 ] ;
float p1 = positionData [ 1 ] ;
float p2 = positionData [ 2 ] ;
position -> fetchTexture ( positionData ) ;
rotation -> fetchTexture ( rotationData ) ;
//if ( positionData [ 0 ] == p0 &&
// positionData [ 1 ] == p1 &&
// positionData [ 2 ] == p2 )
//{
// fprintf ( stderr, "WARNING: If nothing seems to be working, you may\n"
// "have an old version of the nVidia driver.\n"
// "Version 76.76 is known to be bad.\n" ) ;
//}
cubeShader -> use () ; /* Math = Cube shader */
glPushClientAttrib ( GL_CLIENT_VERTEX_ARRAY_BIT ) ;
glDisableClientState ( GL_TEXTURE_COORD_ARRAY ) ;
glEnableClientState ( GL_COLOR_ARRAY ) ;
glBindBufferARB ( GL_ARRAY_BUFFER_ARB, vbo_co ) ;
glColorPointer ( 4, GL_FLOAT, 0, vbo_co ? NULL : colours ) ;
glEnableClientState ( GL_VERTEX_ARRAY ) ;
glBindBufferARB ( GL_ARRAY_BUFFER_ARB, vbo_vx ) ;
glVertexPointer ( 3, GL_FLOAT, 0, vbo_vx ? NULL : vertices ) ;
for ( int y = 0 ; y < TEX_SIZE ; y++ )
for ( int x = 0 ; x < TEX_SIZE ; x++ )
{
float *pos = & positionData [ idToIndex ( x, y ) * 3 ] ;
float *rot = & rotationData [ idToIndex ( x, y ) * 3 ] ;
glPushMatrix () ;
glTranslatef ( pos [ 0 ], pos [ 1 ], pos [ 2 ] ) ;
glRotatef ( rot [ 0 ] * 180.0f / 3.14159f, 0, 1, 0 ) ;
glRotatef ( rot [ 1 ] * 180.0f / 3.14159f, 1, 0, 0 ) ;
glRotatef ( rot [ 2 ] * 180.0f / 3.14159f, 0, 0, 1 ) ;
glMultiDrawArraysEXT ( GL_TRIANGLE_STRIP, (GLint*)starts,
(GLint*)lengths,
STRIPS_PER_CUBE ) ;
glPopMatrix () ;
}
glBindBufferARB ( GL_ARRAY_BUFFER_ARB, 0 ) ;
glPopClientAttrib () ;
}
void drawCubeVBO ()
{
/*
With vertex texture support, we can leave the position/rotation
data on the hardware and render all of the cubes in one big VBO!
*/
if ( debugOpt != DRAW_WITHOUT_SHADERS )
{
cubeShader -> use () ; /* Math = Cube shader */
cubeShader -> applyTexture ( "position", position, 0 ) ;
cubeShader -> applyTexture ( "rotation", rotation, 1 ) ;
}
glPushClientAttrib ( GL_CLIENT_VERTEX_ARRAY_BIT ) ;
glEnableClientState ( GL_TEXTURE_COORD_ARRAY ) ;
glBindBufferARB ( GL_ARRAY_BUFFER_ARB, vbo_tx ) ;
glTexCoordPointer ( 2, GL_FLOAT, 0, vbo_tx ? NULL : texcoords ) ;
glEnableClientState ( GL_COLOR_ARRAY ) ;
glBindBufferARB ( GL_ARRAY_BUFFER_ARB, vbo_co ) ;
glColorPointer ( 4, GL_FLOAT, 0, vbo_co ? NULL : colours ) ;
glEnableClientState ( GL_VERTEX_ARRAY ) ;
glBindBufferARB ( GL_ARRAY_BUFFER_ARB, vbo_vx ) ;
glVertexPointer ( 3, GL_FLOAT, 0, vbo_vx ? NULL : vertices ) ;
glMultiDrawArraysEXT ( GL_TRIANGLE_STRIP, (GLint*)starts, (GLint*)lengths,
NUM_CUBES * STRIPS_PER_CUBE ) ;
glBindBufferARB ( GL_ARRAY_BUFFER_ARB, 0 ) ;
glPopClientAttrib () ;
}
void drawCubes ()
{
glMatrixMode ( GL_PROJECTION ) ;
glLoadIdentity () ;
glFrustum ( -1.0f, 1.0f,
-1.0f / ((float)win_width/(float)win_height),
1.0f / ((float)win_width/(float)win_height),
1.0f, 1000000.0f) ;
/* Set up camera position */
glMatrixMode ( GL_MODELVIEW ) ;
glLoadIdentity () ;
glTranslatef ( 10.0f * (float)TEX_SIZE/128.0f,
-100.0f * (float)TEX_SIZE/128.0f,
-500.0f * (float)TEX_SIZE/128.0f ) ;
glRotatef ( 20.0, 1.0, 0.0, 0.0 ) ;
glEnable ( GL_DEPTH_TEST ) ;
glEnable ( GL_CULL_FACE ) ;
glCullFace ( GL_FRONT ) ;
glClearColor ( 0.7f, 0.7f, 0.7f, 1.0f ) ;
glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ;
if ( noVertexTextureSupport )
drawCubesTheHardWay () ;
else
drawCubeVBO () ;
}
void runCollisionDetection ()
{
static Clock ck ;
ck.update () ;
double tall=ck.getDeltaTime () ;
static int firsttime = true ;
static unsigned int query = 0 ;
FrameBufferObject *tmp ;
FrameBufferObject *SCM = old ;
FrameBufferObject *DCM = collisions ;
unsigned int numHits ;
if ( firsttime )
{
glGenQueriesARB ( 1, (GLuint*) & query ) ;
firsttime = false ;
}
/* Fill SCM with big numbers */
glClearColor ( 1.0f, 1.0f, 1.0f, 1.0f ) ;
SCM -> prepare ( true ) ;
glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f ) ;
force -> prepare ( true ) ; /* Zero out all of the forces. */
int numPasses = 0 ;
glPushClientAttrib ( GL_CLIENT_VERTEX_ARRAY_BIT ) ;
glClientActiveTexture( GL_TEXTURE1 ) ;
glEnableClientState ( GL_TEXTURE_COORD_ARRAY ) ;
glBindBufferARB ( GL_ARRAY_BUFFER_ARB, vbo_collt1 ) ;
glTexCoordPointer ( 2, GL_FLOAT, 0, vbo_collt1 ? NULL : colltexcoords1 ) ;
glClientActiveTexture( GL_TEXTURE0 ) ;
glEnableClientState ( GL_TEXTURE_COORD_ARRAY ) ;
glBindBufferARB ( GL_ARRAY_BUFFER_ARB, vbo_collt0 ) ;
glTexCoordPointer ( 2, GL_FLOAT, 0, vbo_collt0 ? NULL : colltexcoords0 ) ;
glEnableClientState ( GL_VERTEX_ARRAY ) ;
glBindBufferARB ( GL_ARRAY_BUFFER_ARB, vbo_collvx ) ;
glVertexPointer ( 3, GL_FLOAT, 0, vbo_collvx ? NULL : collvertices ) ;
while ( true )
{
collisionGenerator -> use () ;
collisionGenerator -> applyTexture ( "position" , position, 0 ) ;
collisionGenerator -> applyTexture ( "old_collisions", SCM , 1 ) ;
/* Fill DCM with zeroes */
DCM -> prepare ( true ) ;
glBeginQueryARB ( GL_SAMPLES_PASSED_ARB, query ) ;
glMultiDrawArraysEXT ( GL_QUADS, (GLint*)& collstart, (GLint*)& colllength,
1 ) ;
numPasses++ ;
glEndQueryARB ( GL_SAMPLES_PASSED_ARB ) ;
forceGenerator -> use () ;
forceGenerator -> applyTexture ( "position" , position , 0 ) ;
forceGenerator -> applyTexture ( "force" , force , 1 ) ;
forceGenerator -> applyTexture ( "collisions", DCM , 2 ) ;
GLuint sampleCount ;
glGetQueryObjectuivARB ( query, GL_QUERY_RESULT_ARB, &sampleCount ) ;
//fprintf ( stderr, "%d ", sampleCount ) ;
if ( sampleCount == 0 )
break ;
new_force -> paint () ;
tmp = new_force ;
new_force = force ;
force = tmp ;
tmp = DCM ;
DCM = SCM ;
SCM = tmp ;
}
glBindBufferARB ( GL_ARRAY_BUFFER_ARB, 0 ) ;
glPopClientAttrib () ;
ck.update () ;
double tdone=ck.getDeltaTime () ;
static int ii = 0 ;
ii++;
if (ii%100==0)
fprintf ( stderr, "Performance: %d passes %d cubes: other=%fms collisions=%fms\n", numPasses, NUM_CUBES, tall*1000.0, tdone*1000.0 ) ;
}
void runPhysics ()
{
FrameBufferObject *tmp ;
/* Do some simple physics calculations in four stages */
/* Copy old velocity into old. */
tmp = old ;
old = velocity ;
velocity = tmp ;
velocityGenerator -> use () ;
velocityGenerator -> applyTexture ( "old_velocity", old , 0 ) ;
velocityGenerator -> applyTexture ( "force" , force , 1 ) ;
velocityGenerator -> applyTexture ( "massSizeX" , massSizeX, 2 ) ;
velocityGenerator -> setUniform4f ( "g_dt", 0.0f, /*-9.8f */ 0.0f, 0.0f, TIMESTEP ) ;
velocity -> paint () ;
/* Copy old position into old. */
tmp = old ;
old = position ;
position = tmp ;
positionGenerator -> use () ;
positionGenerator -> applyTexture ( "old_position", old , 0 ) ;
positionGenerator -> applyTexture ( "velocity" , velocity, 1 ) ;
positionGenerator -> setUniform1f ( "delta_T", TIMESTEP ) ;
position -> paint () ;
/* Copy old velocity into old. */
tmp = old ;
old = velocity ;
velocity = tmp ;
grndCollisionGenerator -> use () ;
grndCollisionGenerator -> applyTexture ( "position" , position, 0 ) ;
grndCollisionGenerator -> applyTexture ( "old_velocity", old , 1 ) ;
velocity -> paint () ;
/* Copy old rotation into old. */
tmp = old ;
old = rotation ;
rotation = tmp ;
positionGenerator -> use () ;
positionGenerator -> applyTexture ( "old_position", old , 0 ) ;
positionGenerator -> applyTexture ( "velocity" , rotvelocity, 1 ) ;
positionGenerator -> setUniform1f ( "delta_T", TIMESTEP ) ;
rotation -> paint () ;
restoreFrameBuffer () ;
}
void display ( void )
{
if ( debugOpt != DRAW_WITHOUT_SHADERS &&
debugOpt != DRAW_WITHOUT_PHYSICS )
{
runCollisionDetection () ;
runPhysics () ;
}
/* Now render the scene using the results */
glViewport ( 0, 0, win_width, win_height ) ;
drawCubes () ;
/* All done! */
glutSwapBuffers () ;
glutPostRedisplay () ;
}
void help ()
{
fprintf ( stderr, "GPUphysics: Usage -\n\n" ) ;
fprintf ( stderr, " GPUphysics_demo [-c][-p][-v][-a][-v]\n\n" ) ;
fprintf ( stderr, "Where:\n" ) ;
fprintf ( stderr, " -s -- Draw with shaders at all\n" ) ;
fprintf ( stderr, " -p -- Draw with shaders but no physics\n" ) ;
fprintf ( stderr, " -a -- Draw with all features enabled [default]\n" ) ;
fprintf ( stderr, " -v -- Disable vertex textures even if "
"they are supported in hardware\n" ) ;
fprintf ( stderr, "\n" ) ;
}
int main ( int argc, char **argv )
{
#ifdef WIN32
//until there is a first GPU that works under VertexTextureSupport under WIN32, disable it
bool disableVertexTextureSupport = true;
#else
bool disableVertexTextureSupport = false ;
#endif
debugOpt = DRAW_ALL ;
for ( int i = 1 ; i < argc ; i++ )
{
if ( argv [ i ][ 0 ] == '-' || argv [ i ][ 0 ] == '+' )
for ( int j = 1 ; argv[i][j] != '\0' ; j++ )
switch ( argv [ i ][ j ] )
{
case 's' : debugOpt = DRAW_WITHOUT_SHADERS ; break ;
case 'p' : debugOpt = DRAW_WITHOUT_PHYSICS ; break ;
case 'a' : debugOpt = DRAW_ALL ; break ;
case 'v' : disableVertexTextureSupport = true ; break ;
default : help () ; exit ( 0 ) ;
}
else
{
help () ;
exit ( 0 ) ;
}
}
initGLcontext ( argc, argv, display, disableVertexTextureSupport ) ;
initMotionTextures () ;
initPhysicsShaders () ;
initCubeVBO () ;
initCollideVBO () ;
glutMainLoop () ;
return 0 ;
}

View File

@@ -0,0 +1,23 @@
SubDir TOP Extras GPUphysics ;
if $(GLUT.AVAILABLE) = "yes"
{
# All demo apps have a lot in common, so use this rule to simply things
rule GPUDemo
{
Application $(<) : $(>) : noinstall console nomanifest ;
# LinkWith $(<) : GLUT ;
CFlags $(<) :
[ FIncludes $(TOP)/Demos/OpenGL ]
;
MsvcIncDirs $(<) :
"../../Demos/OpenGL"
;
ExternalLibs GPUphysics : GLUT GLew ;
}
}
GPUDemo GPUphysics : [ Wildcard *.h *.cpp ] ;

View File

@@ -0,0 +1,25 @@
/* GPUphysics -- A library and demo program to assist in running physics
simulations on a GPU.
Copyright (C) 2006 Stephen J. Baker
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
Steve Baker sjbaker1@airmail.net
*/

View File

@@ -0,0 +1,22 @@
HDRS = fboSupport.h shaderSupport.h GPU_physics.h clock.h
OBJS = GPU_physics_demo.o fboSupport.o shaderSupport.o clock.o
all: ${OBJS}
g++ -o GPU_physics_demo ${OBJS} -lglut -lGLEW -lGL
clock.o : clock.cpp ${HDRS}
g++ -c clock.cpp
shaderSupport.o : shaderSupport.cpp ${HDRS}
g++ -c shaderSupport.cpp
fboSupport.o : fboSupport.cpp ${HDRS}
g++ -c fboSupport.cpp
GPU_physics_demo.o : GPU_physics_demo.cpp ${HDRS}
g++ -c GPU_physics_demo.cpp
clean:
-rm -f ${OBJS}

View File

@@ -0,0 +1,22 @@
HDRS = fboSupport.h shaderSupport.h
OBJS = GPU_physics_demo.o fboSupport.o shaderSupport.o clock.o
all: ${OBJS}
g++ -framework GLUT -framework OpenGL -L"/System/Library/Frameworks/OpenGL.framework/Libraries" -lGL -lGLU -o GPU_physics_demo ${OBJS} -L"/System/Library/Frameworks/OpenGL.framework/Libraries" -lGLU -lGL -lGLU -lobjc
shaderSupport.o : shaderSupport.cpp ${HDRS}
g++ -c shaderSupport.cpp
fboSupport.o : fboSupport.cpp ${HDRS}
g++ -c fboSupport.cpp
GPU_physics_demo.o : GPU_physics_demo.cpp ${HDRS}
g++ -c GPU_physics_demo.cpp
clock.o : clock.cpp
g++ -c clock.cpp
clean:
-rm -f ${OBJS}

View File

@@ -0,0 +1,106 @@
Author : Steve Baker (sjbaker1@airmail.net)
Build using: 'make'
Run using: 'GPU_physics_demo'
Requires : A pretty modern graphics card - nVidia 6800 or better.
Not tested on ATI hardware.
License : zLib - see file: 'LICENSE'
----------------------------------------------------------
Demonstrates 16,384 cubes moving under the influence of
gravity and one other force - all with potentially different
masses, velocities, applied forces, etc. The CPU is not
involved in any of the calculations - or even in applying
those calculations to the graphics when rendering the cubes.
----------------------------------------------------------
C++ Sources:
shaderSupport.cxx -- A wrapper layer for OpenGL/GLSL shaders.
fboSupport.cxx -- A wrapper layer for render-to-texture tricks.
GPU_physics_demo.cxx -- The application code.
----------------------------------------------------------
GLSLShader Sources used in the Demo:
cubeShader.vert
cubeShaderNoVertexTexture.vert
cubeShader.frag
----------------------------------------------------------
The objective of this library is to provide a basis for the
the Bullet physics engine to:
* Compile shader source code into a 'class GLSL_ShaderPair' object.
* Allocate an NxM texture that you can render into. (class FrameBufferObject)
* Populate a specified texture with floating point data.
* Run a specified shader on a specified set of textures - leaving the
results in another specified texture.
* Demonstrate that this texture can be applied directly into the
graphics code without any CPU intervention whatever.
-------------------------------------------------------------
Step 1: In initialisation code:
* Declare some number of FrameBufferObjects. These are texture
maps that you can render to that represent the 'variables'
in the massively parallel calculations:
eg:
position = new FrameBufferObject ( 512, 512, 4, FBO_FLOAT ) ;
* Declare some number of GLSL_ShaderPair objects:
/* GLSL code read from disk */
teapotShaders = new GLSL_ShaderPair (
"TeapotShader", "shader.vert", "shader.frag" ) ;
/* ...or...Inline GLSL code */
textureShaders = new GLSL_ShaderPair (
"TextureShader",
"void main() { gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; }",
"Render2Texture Vert Shader",
"void main() { gl_FragColor = vec4 ( 1, 1, 0, 1 ) ; }",
"Render2Texture Frag Shader" ) )
* Check that they compiled OK:
assert ( textureShaders -> compiledOK () ) ;
assert ( teapotShaders -> compiledOK () ) ;
Step 2: In the main loop:
* Select one shader pair to use to do the calculations:
teapotShaders -> use () ;
* Set any 'uniform' parameters that the shader might need to be
the same for all of the objects being calculated:
teapotShaders -> setUniform3f ( "gravity", 0, -9.8f,0 ) ;
teapotShaders -> setUniform1f ( "delta_T", 0.016f ) ;
* Assign slot numbers to any FBO/Textures that the shader uses as inputs
and bind them to uniforms in the shader code:
/* Texture 'slots' 0 up to about 15 */
teapotShaders -> applyTexture ( "velocity" , velocityFBO, 0 ) ;
teapotShaders -> applyTexture ( "accelleration", accnFBO, 1 ) ;
* Choose a target FBO/Texture as the place to store the results and
render a polygon of suitable size to perform the calculations:
position -> paint () ;
* Restore the frame buffer to normal so we can go back to using the GPU
to do graphics:
restoreFrameBuffer () ;
Step 3: Draw stuff!

View File

@@ -0,0 +1,79 @@
#include <stdio.h>
#include <stdlib.h>
#include "GPU_physics.h"
#include "clock.h"
#ifdef GPUP_CYGWIN
typedef long long _int64;
#define LARGEINTEGER _int64
#endif
#ifndef GPUP_WIN32
# include <sys/time.h>
#endif
#include <time.h>
#ifdef GPUP_WIN32
double Clock::res ;
int Clock::perf_timer = -1;
void Clock::initPerformanceTimer ()
{
if ( perf_timer == -1 )
{
/* Use Performance Timer if it's available, mmtimer if not. */
__int64 frequency ;
perf_timer = QueryPerformanceFrequency ( (LARGE_INTEGER *) & frequency ) ;
if ( perf_timer )
{
res = 1.0 / (double) frequency ;
perf_timer = 1 ;
}
}
}
#endif
double Clock::getRawTime () const
{
#ifdef GPUP_WIN32
/* Use Performance Timer if it's available, mmtimer if not. */
if ( perf_timer )
{
__int64 t ;
QueryPerformanceCounter ( (LARGE_INTEGER *) &t ) ;
return res * (double) t ;
}
return (double) timeGetTime() * 0.001 ;
#else
timeval tv ;
gettimeofday ( & tv, NULL ) ;
return (double) tv.tv_sec + (double) tv.tv_usec / 1000000.0 ;
#endif
}
void Clock::update ()
{
now = getRawTime() - start ;
delta = now - last_time ;
last_time = now ;
}

View File

@@ -0,0 +1,45 @@
/*
High precision clocks.
*/
class Clock
{
double start ;
double now ;
double delta ;
double last_time ;
double max_delta ;
#ifdef GPUP_WIN32
static double res ;
static int perf_timer ;
void initPerformanceTimer () ;
#endif
double getRawTime () const ;
public:
Clock () { reset () ; }
void reset ()
{
#ifdef GPUP_WIN32
initPerformanceTimer () ;
#endif
start = getRawTime () ;
now = 0.0 ;
max_delta = 0.2 ;
delta = 0.0000001 ; /* Faked so stoopid programs won't div0 */
last_time = 0.0 ;
}
void setMaxDelta ( double maxDelta ) { max_delta = maxDelta ; }
double getMaxDelta () const { return max_delta ; }
void update () ;
double getAbsTime () const { return now ; }
double getDeltaTime () const { return delta ; }
double getFrameRate () const { return 1.0 / delta ; }
} ;

View File

@@ -0,0 +1,30 @@
uniform sampler2D position ;
uniform sampler2D old_collisions ;
void main()
{
vec2 my_id = gl_TexCoord[0].st ;
vec2 pr_id = gl_TexCoord[1].st ;
/* Object colliding with itself */
if ( length ( my_id - pr_id ) < 0.05) discard ;
vec2 last_id = texture2D ( old_collisions, my_id ).xy ;
/* Object collision that will already have been dealt with */
if ( pr_id.y >= last_id.y ) discard ;
if ( pr_id.y == last_id.y && pr_id.x >= last_id.y) discard ;
vec3 my_pos = texture2D ( position, my_id ).xyz ;
vec3 pr_pos = texture2D ( position, pr_id ).xyz ;
/* Objects that don't actually collide */
if ( length ( my_pos - pr_pos ) >= 2.0 ) discard ;
gl_FragColor = vec4 ( pr_id, 0, 1 ) ;
}

View File

@@ -0,0 +1,6 @@
void main()
{
gl_FragColor = gl_Color ;
}

View File

@@ -0,0 +1,42 @@
/* Use this for rendering the little cubes. */
/* Translation & rotation passed in texture maps */
uniform sampler2D position ;
uniform sampler2D rotation ;
/* gl_Color is just the vertex colour */
/* gl_MultiTexCoord0 selects where within the texture we
find this cubes location */
void main()
{
vec4 pos = vec4 ( texture2D ( position, gl_MultiTexCoord0.st ).xyz, 1.0 ) ;
vec3 rot = texture2D ( rotation, gl_MultiTexCoord0.st ).xyz ;
/* Build a rotation matrix */
float sh = sin ( rot.x ) ; float ch = cos ( rot.x ) ;
float sp = sin ( rot.y ) ; float cp = cos ( rot.y ) ;
float sr = sin ( rot.z ) ; float cr = cos ( rot.z ) ;
mat4 mat = mat4 ( ch * cr - sh * sr * sp,
-sh * cp,
sr * ch + sh * cr * sp,
0,
cr * sh + sr * sp * ch,
ch * cp,
sr * sh - cr * sp * ch,
0,
-sr * cp,
sp,
cr * cp,
0,
0.0, 0.0, 0.0, 1.0 ) ;
gl_FrontColor = gl_Color ;
pos.xyz += (mat * gl_Vertex).xyz ;
gl_Position = gl_ModelViewProjectionMatrix * pos ;
}

View File

@@ -0,0 +1,12 @@
/*
Use this for rendering the little cubes when
there is no vertex shader texture support.
*/
void main()
{
gl_FrontColor = gl_Color ;
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex ;
}

View File

@@ -0,0 +1,396 @@
#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 attachment.\n" ) ;
break ;
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT :
fprintf ( stderr, "WARNING: Incomplete FBO - missing attachment.\n" ) ;
break ;
#ifdef GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT
case GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT:
fprintf ( stderr, "WARNING: Incomplete FBO - duplicate attachment.\n" ) ;
break ;
#endif
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT :
fprintf ( stderr, "WARNING: Incomplete FBO - improper dimensions.\n" ) ;
break ;
case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT :
fprintf ( stderr, "WARNING: Incomplete FBO - improper formats.\n" ) ;
break ;
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT :
fprintf ( stderr, "WARNING: Incomplete FBO draw buffer.\n" ) ;
break ;
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT :
fprintf ( stderr, "WARNING: Incomplete FBO read buffer.\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 ;
}
fprintf(stderr,"@a\n" ) ;
glGenTextures ( 1, & textureHandle ) ;
fprintf(stderr,"@b\n" ) ;
glBindTexture ( GL_TEXTURE_2D, textureHandle ) ;
fprintf(stderr,"@c\n" ) ;
glTexParameterf ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ) ;
fprintf(stderr,"@d\n" ) ;
glTexParameterf ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ) ;
fprintf(stderr,"@e\n" ) ;
//glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ) ;
//glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ) ;
fillTexture ( (void *) NULL ) ;
fprintf(stderr,"@f\n" ) ;
glGenFramebuffersEXT ( 1, & fboHandle ) ;
fprintf(stderr,"@g\n" ) ;
glBindFramebufferEXT ( GL_FRAMEBUFFER_EXT, fboHandle ) ;
fprintf(stderr,"@h\n" ) ;
glFramebufferTexture2DEXT ( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_2D, textureHandle, 0 ) ;
fprintf(stderr,"@i\n" ) ;
#ifdef NEED_DEPTH_BUFFER
static GLuint depth_rb = 0 ;
if ( depth_rb == 0 )
{
fprintf(stderr,"@j\n" ) ;
glGenRenderbuffersEXT ( 1, & depth_rb ) ;
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 ) ;
}
else
{
fprintf(stderr,"@k\n" ) ;
glFramebufferRenderbufferEXT ( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT, depth_rb ) ;
}
#else
fprintf(stderr,"@l\n" ) ;
glDisable ( GL_DEPTH_TEST ) ;
glDepthMask ( 0 ) ;
fprintf(stderr,"@m\n" ) ;
glFramebufferRenderbufferEXT ( GL_FRAMEBUFFER_EXT , GL_DEPTH_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT, 0 ) ;
fprintf(stderr,"@n\n" ) ;
#endif
#ifdef NEED_STENCIL_BUFFER
static GLuint stencil_rb = 0 ;
if ( stencil_rb == 0 )
{
fprintf(stderr,"@o\n" ) ;
glGenRenderbuffersEXT ( 1, & stencil_rb ) ;
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
glFramebufferRenderbufferEXT ( GL_FRAMEBUFFER_EXT , GL_STENCIL_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT, stencil_rb ) ;
#else
fprintf(stderr,"@p\n" ) ;
glDisable ( GL_STENCIL_TEST ) ;
glStencilMask ( 0 ) ;
fprintf(stderr,"@q\n" ) ;
glFramebufferRenderbufferEXT ( GL_FRAMEBUFFER_EXT , GL_STENCIL_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT, 0 ) ;
fprintf(stderr,"@r\n" ) ;
#endif
// Check framebuffer completeness at the end of initialization.
checkFrameBufferStatus () ;
fprintf(stderr,"@s\n" ) ;
restoreFrameBuffer () ;
fprintf(stderr,"@t\n" ) ;
}
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 ( unsigned short *data )
{
if ( type != FBO_UNSIGNED_SHORT )
{
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 ( unsigned short *data )
{
if ( type != FBO_UNSIGNED_SHORT )
{
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::prepare ( bool clear )
{
makeDestination () ;
glViewport ( 0, 0, width, height ) ;
if ( clear ) glClear ( GL_COLOR_BUFFER_BIT ) ;
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 ) ;
}
void FrameBufferObject::fill ()
{
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 () ;
}

View File

@@ -0,0 +1,101 @@
GLuint makeTextureTarget ( GLuint textureHandle ) ;
void renderTo2DTexture ( GLuint fboHandle ) ;
void renderToFrameBuffer () ;
// #define NEED_STENCIL_BUFFER 1
// #define NEED_DEPTH_BUFFER 1
enum fboDataType
{
#ifndef GL_BYTE
FBO_BYTE = 0x1400,
FBO_UNSIGNED_BYTE = 0x1401,
FBO_SHORT = 0x1402,
FBO_UNSIGNED_SHORT = 0x1403,
FBO_INT = 0x1404,
FBO_UNSIGNED_INT = 0x1405,
FBO_FLOAT = 0x1406,
FBO_DOUBLE = 0x140A,
#else
FBO_BYTE = GL_BYTE,
FBO_UNSIGNED_BYTE = GL_UNSIGNED_BYTE,
FBO_SHORT = GL_SHORT,
FBO_UNSIGNED_SHORT = GL_UNSIGNED_SHORT,
FBO_INT = GL_INT,
FBO_UNSIGNED_INT = GL_UNSIGNED_INT,
FBO_FLOAT = GL_FLOAT,
FBO_DOUBLE = GL_DOUBLE,
#endif
#ifndef GL_HALF_FLOAT_NV
FBO_HALF = 0x140B
#else
FBO_HALF = GL_HALF_FLOAT_NV
#endif
} ;
class FrameBufferObject
{
int width ;
int height ;
int ncomps ;
fboDataType type ;
GLenum format ;
GLenum iformat ;
GLuint textureHandle ;
GLuint fboHandle ;
void fillTexture ( void *data ) ;
void fetchTexture ( void *data ) ;
public:
FrameBufferObject ( int _width, /* Must be a power of two! */
int _height, /* Must be a power of two! */
int _numComponents, /* 1, 2, 3 or 4 only! */
fboDataType _type ) ;
void makeDestination ()
{
#ifndef NEED_DEPTH_BUFFER
glDepthMask ( 0 ) ;
#endif
#ifndef NEED_STENCIL_BUFFER
glStencilMask ( 0 ) ;
#endif
glBindFramebufferEXT ( GL_FRAMEBUFFER_EXT, fboHandle ) ;
}
void use ( int texture_unit )
{
glActiveTexture ( GL_TEXTURE0 + texture_unit ) ;
glBindTexture ( GL_TEXTURE_2D, textureHandle ) ;
}
void prepare ( bool clear = false ) ;
void fill () ;
void paint ( bool clear = false ) { prepare ( clear ) ; fill () ; }
void fillTexture ( float *data ) ;
void fillTexture ( unsigned short *data ) ;
void fillTexture ( unsigned char *data ) ;
void fetchTexture ( float *data ) ;
void fetchTexture ( unsigned short *data ) ;
void fetchTexture ( unsigned char *data ) ;
} ;
inline void restoreFrameBuffer ()
{
glBindFramebufferEXT ( GL_FRAMEBUFFER_EXT, 0 ) ;
#ifndef NEED_DEPTH_BUFFER
glDepthMask ( 1 ) ;
#endif
#ifndef NEED_STENCIL_BUFFER
glStencilMask ( 1 ) ;
#endif
}

View File

@@ -0,0 +1,430 @@
#include "GPU_physics.h"
#include "shaderSupport.h"
#include "fboSupport.h"
#define DEFAULT_VERT_SHADER \
"void main()" \
"{" \
" gl_TexCoord[0] = gl_MultiTexCoord0 ;" \
" gl_TexCoord[1] = gl_MultiTexCoord1 ;" \
" gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex ;" \
"}"
class FrameBufferObject ;
class GLSL_Shader
{
GLenum type ;
GLhandleARB handle ;
char *name ;
char *source ;
public:
GLSL_Shader ()
{
type = (GLenum) 0 ;
handle = 0 ;
name = NULL ;
source = NULL ;
}
~GLSL_Shader ()
{
delete [] name ;
delete [] source ;
}
bool compileFile ( const char *fname , GLenum type ) ;
bool compileString ( const char *source, GLenum type,
const char *name ) ;
GLenum getType () { return type ; }
GLhandleARB getHandle () { return handle ; }
} ;
static char *readShaderText ( const char *fname )
{
FILE *fd = fopen ( fname, "r" ) ;
if (!fd)
{
//some platforms might require different path, try two additional locations
char newname[256];
sprintf(newname,"../../Extras/GPUphysics/%s",fname);
fd = fopen( newname ,"r");
if (!fd)
{
sprintf(newname,"Extras/GPUphysics/%s",fname);
fd = fopen( newname,"r");
}
}
if (!fd)
{
printf("cannot open file %s\n",fname);
exit(1);
}
int size = 0;
/* File operations denied? ok, just close and return failure */
if (fseek(fd, 0, SEEK_END) || (size = ftell(fd)) == EOF || fseek(fd, 0, SEEK_SET))
{
printf("Error: cannot get filesize from %s\n", fname);
exit (1);
}
char *shader = new char [ size + 1 ] ;
if ( fd == NULL )
{
fprintf ( stderr, "Cannot read shader '%s'\n", fname ) ;
exit ( 1 ) ;
}
int count = fread ( shader, 1, size, fd ) ;
shader [ count ] = '\0' ;
fclose ( fd ) ;
return shader ;
}
/*****************************\
* *
* Error handling stuff *
* *
\*****************************/
static void showShaderInfo ( const char *which,
GLhandleARB handle, const char *name )
{
int len = 0 ;
showGLerror ( "showShaderInfo_0" ) ;
glGetObjectParameterivARB ( handle, GL_OBJECT_INFO_LOG_LENGTH_ARB, (GLint*) &len ) ;
showGLerror ( "showShaderInfo_1" ) ;
if ( len > 0 )
{
int trueLen ;
char *s = new char [ len ] ;
glGetInfoLogARB ( handle, len, (GLint*)&trueLen, s ) ;
if ( trueLen > 0 && s [ 0 ] != '\0' )
fprintf ( stderr, "%s:%s - \n%s\n", which, name, s ) ;
delete [] s ;
}
}
/************************************\
* *
* Single Shader Stuff *
* *
\************************************/
bool GLSL_Shader::compileFile ( const char *fname, GLenum _type )
{
return compileString ( readShaderText ( fname ), _type, fname ) ;
}
bool GLSL_Shader::compileString ( const char *_source,
GLenum _type,
const char *_name )
{
delete [] name ;
delete [] source ;
type = _type ;
name = strdup ( _name ) ;
source = strdup ( _source ) ;
GLint stat ;
handle = glCreateShaderObjectARB ( type ) ;
glShaderSourceARB ( handle, 1, (const GLcharARB **) & source, NULL);
glCompileShaderARB ( handle ) ;
glGetObjectParameterivARB ( handle, GL_OBJECT_COMPILE_STATUS_ARB, & stat ) ;
showShaderInfo ( "Compiling", handle, name ) ;
if ( ! stat )
{
fprintf ( stderr, "Failed to compile shader '%s'.\n", name ) ;
return false ;
}
return true ;
}
/************************************\
* *
* Shader Pair Stuff *
* *
\************************************/
GLint GLSL_ShaderPair::getUniformLocation ( const char *uni_name )
{
assert ( success ) ;
GLint loc = glGetUniformLocationARB ( handle, uni_name ) ;
if ( loc == -1 )
fprintf ( stderr, "No such uniform as '%s' or"
" '%s' is unused in shader pair '%s'.\n", uni_name,
uni_name,
name ) ;
else
showGLerror ( "GLSL_ShaderPair::getUniformLocation" ) ;
return loc ;
}
void GLSL_ShaderPair::showActiveUniforms ( FILE *fd )
{
GLint maxlen = 0 ;
GLint maxattrs = 0 ;
if ( fd == NULL ) fd = stderr ;
glGetObjectParameterivARB ( handle,
GL_OBJECT_ACTIVE_UNIFORMS_ARB,
&maxattrs ) ;
if ( maxattrs == 0 )
{
fprintf ( fd, "No Active Uniforms.\n" ) ;
return ;
}
glGetObjectParameterivARB ( handle,
GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB,
&maxlen ) ;
char *name = new char [ maxlen+1 ] ;
fprintf ( fd, "Active Uniforms:\n" ) ;
for ( int i = 0 ; i < maxattrs ; i++ )
{
GLsizei len ;
GLint size ;
GLenum vartype ;
char *vartypename ;
GLint location ;
glGetActiveUniformARB ( handle, i,
maxlen+1, &len, &size, &vartype, name ) ;
location = glGetUniformLocationARB ( handle, name ) ;
switch ( vartype )
{
case GL_FLOAT : vartypename = "float " ; break ;
case GL_FLOAT_VEC2_ARB : vartypename = "vec2 " ; break ;
case GL_FLOAT_VEC3_ARB : vartypename = "vec3 " ; break ;
case GL_FLOAT_VEC4_ARB : vartypename = "vec4 " ; break ;
case GL_INT : vartypename = "int " ; break ;
case GL_INT_VEC2_ARB : vartypename = "intvec2 " ; break ;
case GL_INT_VEC3_ARB : vartypename = "intvec3 " ; break ;
case GL_INT_VEC4_ARB : vartypename = "intvec4 " ; break ;
case GL_BOOL : vartypename = "bool " ; break ;
case GL_BOOL_VEC2_ARB : vartypename = "boolvec2 " ; break ;
case GL_BOOL_VEC3_ARB : vartypename = "boolvec3 " ; break ;
case GL_BOOL_VEC4_ARB : vartypename = "boolvec4 " ; break ;
case GL_FLOAT_MAT2_ARB : vartypename = "mat2 " ; break ;
case GL_FLOAT_MAT3_ARB : vartypename = "mat3 " ; break ;
case GL_FLOAT_MAT4_ARB : vartypename = "mat4 " ; break ;
case GL_SAMPLER_1D_ARB : vartypename = "sampler1D" ; break ;
case GL_SAMPLER_2D_ARB : vartypename = "sampler2D" ; break ;
case GL_SAMPLER_3D_ARB : vartypename = "sampler3D" ; break ;
default : vartypename = "?????????" ; break ;
}
if ( size == 1 )
fprintf ( fd, "%2d) %s %s ; // @%d\n", i,
vartypename, name, location ) ;
else
fprintf ( fd, "%2d) %s %s [ %d ] ; // @%d\n", i,
vartypename, name, size, location ) ;
}
fprintf ( fd, "\n" ) ;
delete name ;
}
void GLSL_ShaderPair::showActiveAttribs ( FILE *fd )
{
if ( fd == NULL ) fd = stderr ;
GLint maxlen = 0 ;
GLint maxattrs = 0 ;
glGetObjectParameterivARB ( handle,
GL_OBJECT_ACTIVE_ATTRIBUTES_ARB,
&maxattrs ) ;
if ( maxattrs == 0 )
{
fprintf ( fd, "No Active Attributes.\n" ) ;
return ;
}
glGetObjectParameterivARB ( handle,
GL_OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARB,
&maxlen ) ;
char *name = new char [ maxlen+1 ] ;
fprintf ( fd, "Active Attributes:\n" ) ;
for ( int i = 0 ; i < maxattrs ; i++ )
{
GLsizei len ;
GLint size ;
GLenum vartype ;
char *vartypename ;
GLint location ;
glGetActiveAttribARB ( handle, i, maxlen+1, &len, &size, &vartype, name ) ;
location = glGetAttribLocationARB ( handle, name ) ;
switch ( vartype )
{
case GL_FLOAT : vartypename = "float" ; break ;
case GL_FLOAT_VEC2_ARB : vartypename = "vec2 " ; break ;
case GL_FLOAT_VEC3_ARB : vartypename = "vec3 " ; break ;
case GL_FLOAT_VEC4_ARB : vartypename = "vec4 " ; break ;
case GL_FLOAT_MAT2_ARB : vartypename = "mat2 " ; break ;
case GL_FLOAT_MAT3_ARB : vartypename = "mat3 " ; break ;
case GL_FLOAT_MAT4_ARB : vartypename = "mat4 " ; break ;
default : vartypename = "???? " ; break ;
}
if ( size == 1 )
fprintf ( fd, "%2d) %s %s ; // @%d\n", i,
vartypename, name, location ) ;
else
fprintf ( fd, "%2d) %s %s [ %d ] ; // @%d\n", i,
vartypename, name, size, location ) ;
}
fprintf ( fd, "\n" ) ;
delete name ;
}
bool GLSL_ShaderPair::link ()
{
GLint stat ;
handle = glCreateProgramObjectARB () ;
glAttachObjectARB ( handle, vertShader -> getHandle () ) ;
glAttachObjectARB ( handle, fragShader -> getHandle () ) ;
glLinkProgramARB ( handle ) ;
glGetObjectParameterivARB ( handle, GL_OBJECT_LINK_STATUS_ARB, &stat ) ;
showShaderInfo ( "Linking", handle, name ) ;
glValidateProgramARB ( handle ) ;
showShaderInfo ( "Validate", handle, name ) ;
if ( ! stat )
{
fprintf ( stderr, "Failed to link shader.\n" ) ;
return false ;
}
return true ;
}
GLSL_ShaderPair::GLSL_ShaderPair ( const char *_name,
const char *vertFname,
const char *fragFname )
{
name = strdup ( _name ) ;
handle = 0 ;
vertShader = new GLSL_Shader () ;
fragShader = new GLSL_Shader () ;
bool res1 = ( vertFname == NULL ) ?
vertShader -> compileString ( DEFAULT_VERT_SHADER,
GL_VERTEX_SHADER_ARB,
"Default Vertex Shader" ) :
vertShader -> compileFile ( vertFname, GL_VERTEX_SHADER_ARB ) ;
bool res2 = fragShader -> compileFile ( fragFname, GL_FRAGMENT_SHADER_ARB ) ;
success = ( res1 && res2 && link () ) ;
}
GLSL_ShaderPair::GLSL_ShaderPair ( const char *_name,
const char *vertSource,
const char *vertName,
const char *fragSource,
const char *fragName )
{
name = strdup ( _name ) ;
handle = 0 ;
vertShader = new GLSL_Shader () ;
fragShader = new GLSL_Shader () ;
bool res1 = ( vertSource == NULL ) ?
vertShader -> compileString ( DEFAULT_VERT_SHADER,
GL_VERTEX_SHADER_ARB,
"Default Vertex Shader" ) :
vertShader -> compileString ( vertSource,
GL_VERTEX_SHADER_ARB,
vertName );
bool res2 = fragShader -> compileString ( fragSource,
GL_FRAGMENT_SHADER_ARB,
fragName );
success = ( res1 && res2 && link () ) ;
}
GLSL_ShaderPair::~GLSL_ShaderPair ()
{
delete [] name ;
delete vertShader ;
delete fragShader ;
}
void GLSL_ShaderPair::applyTexture ( const char *uniformName,
FrameBufferObject *fbo,
int slot )
{
fbo -> use ( slot ) ;
glUniform1iARB ( getUniformLocation ( uniformName ), slot ) ;
}

View File

@@ -0,0 +1,76 @@
class GLSL_Shader ;
class FrameBufferObject ;
class GLSL_ShaderPair
{
GLSL_Shader *vertShader ;
GLSL_Shader *fragShader ;
GLhandleARB handle ;
char *name ;
bool success ;
bool link () ;
public:
GLSL_ShaderPair ( const char *_name,
const char *vertFname, const char *fragFname ) ;
GLSL_ShaderPair ( const char *_name,
const char *vertSource, const char *vertName,
const char *fragSource, const char *fragName ) ;
~GLSL_ShaderPair () ;
bool compiledOK () { return success ; }
/* Debug functions */
void showActiveUniforms ( FILE *fd = NULL ) ;
void showActiveAttribs ( FILE *fd = NULL ) ;
GLint getUniformLocation ( const char *varname ) ;
void applyTexture ( const char *uniformName,
FrameBufferObject *fbo,
int slot ) ;
void setUniform1f ( const char *uniformName, float valueX )
{
glUniform1fARB ( getUniformLocation ( uniformName ), valueX ) ;
}
void setUniform2f ( const char *uniformName, float valueX,
float valueY )
{
glUniform2fARB ( getUniformLocation ( uniformName ), valueX, valueY ) ;
}
void setUniform3f ( const char *uniformName, float valueX,
float valueY,
float valueZ )
{
glUniform3fARB ( getUniformLocation ( uniformName ), valueX, valueY,
valueZ ) ;
}
void setUniform4f ( const char *uniformName, float valueX,
float valueY,
float valueZ,
float valueW )
{
glUniform4fARB ( getUniformLocation ( uniformName ), valueX, valueY,
valueZ, valueW ) ;
}
/* To apply the shaders for rendering */
void use ()
{
assert ( success ) ;
glUseProgramObjectARB ( handle ) ;
}
} ;