From b548455ae9311712cddc274f9b3a4a96ab28b68e Mon Sep 17 00:00:00 2001 From: ejcoumans Date: Mon, 18 Sep 2006 20:16:43 +0000 Subject: [PATCH] added Steven Baker's GPU physics code (work in progress) --- Extras/GPUphysics/CHANGES | 29 ++ Extras/GPUphysics/CMakeLists.txt | 66 +++ Extras/GPUphysics/DEBUGGING_README | 67 +++ Extras/GPUphysics/GPU_physics_demo.cxx | 553 +++++++++++++++++++++++++ Extras/GPUphysics/LICENSE | 25 ++ Extras/GPUphysics/Makefile | 19 + Extras/GPUphysics/Makefile.Mac | 19 + Extras/GPUphysics/README | 105 +++++ Extras/GPUphysics/cubeShader.frag | 6 + Extras/GPUphysics/cubeShader.vert | 42 ++ Extras/GPUphysics/fboSupport.cxx | 261 ++++++++++++ Extras/GPUphysics/fboSupport.h | 84 ++++ Extras/GPUphysics/shaderSupport.cxx | 441 ++++++++++++++++++++ Extras/GPUphysics/shaderSupport.h | 79 ++++ 14 files changed, 1796 insertions(+) create mode 100644 Extras/GPUphysics/CHANGES create mode 100644 Extras/GPUphysics/CMakeLists.txt create mode 100644 Extras/GPUphysics/DEBUGGING_README create mode 100644 Extras/GPUphysics/GPU_physics_demo.cxx create mode 100644 Extras/GPUphysics/LICENSE create mode 100644 Extras/GPUphysics/Makefile create mode 100644 Extras/GPUphysics/Makefile.Mac create mode 100644 Extras/GPUphysics/README create mode 100644 Extras/GPUphysics/cubeShader.frag create mode 100644 Extras/GPUphysics/cubeShader.vert create mode 100644 Extras/GPUphysics/fboSupport.cxx create mode 100644 Extras/GPUphysics/fboSupport.h create mode 100644 Extras/GPUphysics/shaderSupport.cxx create mode 100644 Extras/GPUphysics/shaderSupport.h diff --git a/Extras/GPUphysics/CHANGES b/Extras/GPUphysics/CHANGES new file mode 100644 index 000000000..dbc22551a --- /dev/null +++ b/Extras/GPUphysics/CHANGES @@ -0,0 +1,29 @@ + +GPUphysics-0.0 +============== + +* Initial release + + +GPUphysics-0.1 +============== + +* Fixes for stencil buffer problems on some systems. + + +GPUphysics-0.2 +============== + +* Added MacOSX support. +* Added a ton of command-line debug options (see DEBUG_README) +* Changed to ZLib license. + +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. + +* Added to the Bullet Subversion repository at Sourceforge.net + See http://sf.net/projects/bullet diff --git a/Extras/GPUphysics/CMakeLists.txt b/Extras/GPUphysics/CMakeLists.txt new file mode 100644 index 000000000..4c453381b --- /dev/null +++ b/Extras/GPUphysics/CMakeLists.txt @@ -0,0 +1,66 @@ +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( +glew/include +) + +LINK_LIBRARIES( + glew/lib/glew32.lib ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glU_LIBRARY} +) + +ADD_EXECUTABLE(GPUphysics + fboSupport.cxx + GPU_physics_demo.cxx + shaderSupport.cxx +) + diff --git a/Extras/GPUphysics/DEBUGGING_README b/Extras/GPUphysics/DEBUGGING_README new file mode 100644 index 000000000..ca45b70a0 --- /dev/null +++ b/Extras/GPUphysics/DEBUGGING_README @@ -0,0 +1,67 @@ + +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 either: + + a) 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). + + b) Your graphics card/driver doesn't support vertex shader + textures (or it supports them but sets the maximum number + to zero - which is the same thing). This means that we + can't move things around using GPU textures - but we can + still use the GPU to accellerate physics calculations. + In practical game scenarios, I think the CPU needs to know + where all the objects are - so this may not be the serious + issue it sounds like. What it mostly does is to clobber + the idea of running physics on particle system types of + effect where a vast number of objects are involved but + where individual objects have zero effect on game play. + +3) Run without forces being applied: + + GPU_physics -f + + This sets the cubes off moving at constant speed (each cube + going at a different speed and spinning). + + Run without collision against the ground: + + GPU_physics -c + + The cubes move under gravity - but don't interact with the + notional ground plane so the eventually fall off the bottom + of the screen.. + + If either (3) or (4) fails but (1) and (2) worked then the + problem is probably something to do with render-to-texture. + + This is the most likely scenario. + + + diff --git a/Extras/GPUphysics/GPU_physics_demo.cxx b/Extras/GPUphysics/GPU_physics_demo.cxx new file mode 100644 index 000000000..4fe54bddb --- /dev/null +++ b/Extras/GPUphysics/GPU_physics_demo.cxx @@ -0,0 +1,553 @@ +#ifndef WIN32 +#include +#endif +#include +#include +//think different +#if defined(__APPLE__) && !defined (VMDMESA) +#include +#include +#include +#else +#include +#include +#endif +#include "fboSupport.h" +#include "shaderSupport.h" + +enum DebugOptions +{ + DRAW_WITHOUT_SHADERS, + DRAW_WITHOUT_PHYSICS, + DRAW_WITHOUT_COLLISIONS, + DRAW_WITHOUT_FORCES, + DRAW_ALL +} ; + + +DebugOptions debugOpt = DRAW_ALL ; + + +float frand ( float max ) +{ + return (float)(rand() % 32767) * max / 32767.0f ; +} + +static GLSL_ShaderPair *velocityGenerator ; +static GLSL_ShaderPair *positionGenerator ; +static GLSL_ShaderPair *collisionGenerator ; +static GLSL_ShaderPair *cubeShader ; + +static FrameBufferObject *position ; +static FrameBufferObject *rotation ; +static FrameBufferObject *velocity ; +static FrameBufferObject *rotvelocity ; +static FrameBufferObject *force ; +static FrameBufferObject *mass ; + +#define TEX_SIZE 128 +#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 int win_width = 640 ; +static int win_height = 480 ; + + +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) ) +{ + 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 ) ; + + glewInit () ; +} + + +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 ) ; + + if ( debugOpt == DRAW_WITHOUT_PHYSICS ) + { + velocity = NULL ; + rotvelocity = NULL ; + force = NULL ; + mass = NULL ; + } + else + { + velocity = new FrameBufferObject ( TEX_SIZE, TEX_SIZE, 3, FBO_FLOAT ) ; + rotvelocity = new FrameBufferObject ( TEX_SIZE, TEX_SIZE, 3, FBO_FLOAT ) ; + + if ( debugOpt == DRAW_WITHOUT_FORCES ) + { + force = NULL ; + mass = NULL ; + } + else + { + force = new FrameBufferObject ( TEX_SIZE, TEX_SIZE, 3, FBO_FLOAT ) ; + mass = new FrameBufferObject ( TEX_SIZE, TEX_SIZE, 1, FBO_FLOAT ) ; + } + } + + float *positionData = new float [ TEX_SIZE * TEX_SIZE * 3 ] ; + float *rotationData = new float [ TEX_SIZE * TEX_SIZE * 3 ] ; + float *velocityData ; + float *rotvelocityData ; + float *forceData ; + float *massData ; + + if ( debugOpt == DRAW_WITHOUT_PHYSICS ) + { + velocityData = NULL ; + rotvelocityData = NULL ; + forceData = NULL ; + massData = NULL ; + } + else + { + velocityData = new float [ TEX_SIZE * TEX_SIZE * 3 ] ; + rotvelocityData = new float [ TEX_SIZE * TEX_SIZE * 3 ] ; + + if ( debugOpt == DRAW_WITHOUT_FORCES ) + { + forceData = NULL ; + massData = NULL ; + } + else + { + forceData = new float [ TEX_SIZE * TEX_SIZE * 3 ] ; + massData = new float [ TEX_SIZE * TEX_SIZE ] ; + } + } + + /* Give the objects some initial position, rotation, mass, force, etc */ + + for ( int i = 0 ; i < TEX_SIZE ; i++ ) + for ( int j = 0 ; j < TEX_SIZE ; j++ ) + { + /* + Start the cubes on a nice, regular 5m grid, 10m above the ground + centered around the origin + */ + + positionData [ (i*TEX_SIZE + j) * 3 + 0 ] = 5.0f * (float) (TEX_SIZE/2 - i) ; + positionData [ (i*TEX_SIZE + j) * 3 + 1 ] = 10.0f ; + positionData [ (i*TEX_SIZE + j) * 3 + 2 ] = 5.0f * (float) (TEX_SIZE/2 - j) ; + + /* Zero their rotations */ + rotationData [ (i*TEX_SIZE + j) * 3 + 0 ] = 0.0f ; + rotationData [ (i*TEX_SIZE + j) * 3 + 1 ] = 0.0f ; + rotationData [ (i*TEX_SIZE + j) * 3 + 2 ] = 0.0f ; + + if ( debugOpt != DRAW_WITHOUT_PHYSICS ) + { + /* Random (but predominantly upwards) velocities. */ + velocityData [ (i*TEX_SIZE + j) * 3 + 0 ] = frand ( 10.0f ) ; + velocityData [ (i*TEX_SIZE + j) * 3 + 1 ] = frand ( 100.0f ) ; + velocityData [ (i*TEX_SIZE + j) * 3 + 2 ] = frand ( 10.0f ) ; + + /* Random rotational velocities */ + rotvelocityData [ (i*TEX_SIZE + j) * 3 + 0 ] = frand ( 3.0f ) ; + rotvelocityData [ (i*TEX_SIZE + j) * 3 + 1 ] = frand ( 3.0f ) ; + rotvelocityData [ (i*TEX_SIZE + j) * 3 + 2 ] = frand ( 3.0f ) ; + + if ( debugOpt != DRAW_WITHOUT_FORCES ) + { + /* Zero forces (just gravity) */ + forceData [ (i*TEX_SIZE + j) * 3 + 0 ] = 0.0f ; + forceData [ (i*TEX_SIZE + j) * 3 + 1 ] = 0.0f ; + forceData [ (i*TEX_SIZE + j) * 3 + 2 ] = 0.0f ; + + /* One kg in weight each */ + massData [ i*TEX_SIZE + j ] = 1.0f ; + } + } + } + + /* Initialise the textures */ + + position -> fillTexture ( positionData ) ; + rotation -> fillTexture ( rotationData ) ; + + if ( debugOpt != DRAW_WITHOUT_PHYSICS ) + { + velocity -> fillTexture ( velocityData ) ; + rotvelocity -> fillTexture ( rotvelocityData ) ; + + if ( debugOpt != DRAW_WITHOUT_FORCES ) + { + force -> fillTexture ( forceData ) ; + mass -> fillTexture ( massData ) ; + } + } +} + + +void initPhysicsShaders () +{ + if ( debugOpt == DRAW_WITHOUT_SHADERS || + debugOpt == DRAW_WITHOUT_PHYSICS ) + return ; + + if ( debugOpt == DRAW_WITHOUT_FORCES ) + { + velocityGenerator = NULL ; + } + else + { + /* + The velocity generator shader calculates: + + velocity = old_velocity + delta_T * ( F / m ) ; + */ + + velocityGenerator = new GLSL_ShaderPair ( + "VelocityGenerator", + NULL, NULL, + "uniform float delta_T ;" + "uniform vec3 g ;" + "uniform sampler2D old_velocity ;" + "uniform sampler2D force ;" + "uniform sampler2D mass ;" + "void main() {" + " gl_FragColor = vec4 (" + " texture2D ( old_velocity, gl_TexCoord[0].st ).xyz +" + " delta_T * ( g +" + " texture2D ( force , gl_TexCoord[0].st ).xyz /" + " texture2D ( mass , 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 () ) ; + + if ( debugOpt == DRAW_WITHOUT_COLLISIONS ) + { + collisionGenerator = NULL ; + } + else + { + collisionGenerator = new GLSL_ShaderPair ( + "CollisionGenerator", + 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 [ 1 ] *= -0.90 ;" + " gl_FragColor = vec4 ( vel, 1.0 ) ; }", + "CollisionGenerator Frag Shader" ) ; + assert ( collisionGenerator -> compiledOK () ) ; + } +} + + +void initCubeVBO () +{ + float *p = vertices ; + float *t = texcoords ; + float *c = colours ; + + for ( int k = 0 ; k < NUM_CUBES * STRIPS_PER_CUBE ; k++ ) + { + starts [ k ] = k * VERTS_PER_STRIP ; + lengths [ k ] = VERTS_PER_STRIP ; + } + + for ( int i = 0 ; i < TEX_SIZE ; i++ ) + for ( int j = 0 ; j < TEX_SIZE ; j++ ) + { + int n = i * TEX_SIZE + j ; + + /* + 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)i+0.5f)/(float)TEX_SIZE ; + *t++ = ((float)j+0.5f)/(float)TEX_SIZE ; + + *c++ = frand ( 1.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 - i) ; + dy = 10.0f ; + dz = 5.0f * (float) (TEX_SIZE/2 - j) ; + } + 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 ; + } + + glGenBuffersARB ( 1, & vbo_vx ) ; + glBindBufferARB ( GL_ARRAY_BUFFER_ARB, vbo_vx ) ; + glBufferDataARB ( GL_ARRAY_BUFFER_ARB, NUM_VERTS * 3 * sizeof(float), + vertices, GL_STATIC_DRAW_ARB ) ; + + glGenBuffersARB ( 1, & vbo_tx ) ; + glBindBufferARB ( GL_ARRAY_BUFFER_ARB, vbo_tx ) ; + glBufferDataARB ( GL_ARRAY_BUFFER_ARB, NUM_VERTS * 2 * sizeof(float), + texcoords, GL_STATIC_DRAW_ARB ) ; + + glGenBuffersARB ( 1, & vbo_co ) ; + glBindBufferARB ( GL_ARRAY_BUFFER_ARB, vbo_co ) ; + glBufferDataARB ( GL_ARRAY_BUFFER_ARB, NUM_VERTS * 4 * sizeof(float), + colours, GL_STATIC_DRAW_ARB ) ; + + glBindBufferARB ( GL_ARRAY_BUFFER_ARB, 0 ) ; + + if ( debugOpt == DRAW_WITHOUT_SHADERS ) + cubeShader = NULL ; + else + { + cubeShader = new GLSL_ShaderPair ( "CubeShader", "cubeShader.vert", + "cubeShader.frag" ) ; + assert ( cubeShader -> compiledOK () ) ; + } +} + + +void drawCubeVBO () +{ + 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) ; + + glMatrixMode ( GL_MODELVIEW ) ; + glLoadIdentity () ; + glTranslatef ( 10.0, -100.0, -500.0 ) ; + 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 ) ; + + drawCubeVBO () ; +} + + +void display ( void ) +{ + if ( debugOpt != DRAW_WITHOUT_SHADERS && + debugOpt != DRAW_WITHOUT_PHYSICS ) + { + /* Do some simple physics calculations in four stages */ + + if ( debugOpt != DRAW_WITHOUT_FORCES ) + { + velocityGenerator -> use () ; + velocityGenerator -> applyTexture ( "old_velocity", velocity, 0 ) ; + velocityGenerator -> applyTexture ( "force" , force , 1 ) ; + velocityGenerator -> applyTexture ( "mass" , mass , 2 ) ; + velocityGenerator -> setUniform1f ( "delta_T" , 0.016f ) ; + velocityGenerator -> setUniform3f ( "g", 0.0f, -9.8f, 0.0f ) ; + velocity -> paint () ; + } + + positionGenerator -> use () ; + positionGenerator -> applyTexture ( "old_position", position, 0 ) ; + positionGenerator -> applyTexture ( "velocity" , velocity, 1 ) ; + positionGenerator -> setUniform1f ( "delta_T", 0.016f ) ; + position -> paint () ; + + if ( debugOpt != DRAW_WITHOUT_COLLISIONS ) + { + collisionGenerator -> use () ; + collisionGenerator -> applyTexture ( "position" , position, 0 ) ; + collisionGenerator -> applyTexture ( "old_velocity", velocity, 1 ) ; + velocity -> paint () ; + } + + positionGenerator -> use () ; + positionGenerator -> applyTexture ( "old_position", rotation , 0 ) ; + positionGenerator -> applyTexture ( "velocity" , rotvelocity, 1 ) ; + positionGenerator -> setUniform1f ( "delta_T", 0.016f ) ; + rotation -> paint () ; + + /* Now render the scene using the results */ + + restoreFrameBuffer () ; + } + + glViewport ( 0, 0, win_width, win_height ) ; + + if ( debugOpt != DRAW_WITHOUT_SHADERS ) + { + cubeShader -> use () ; /* Math = Cube shader */ + cubeShader -> applyTexture ( "position", position, 0 ) ; + cubeShader -> applyTexture ( "rotation", rotation, 1 ) ; + } + + drawCubes () ; + + /* All done! */ + + glutSwapBuffers () ; + glutPostRedisplay () ; +} + + +void help () +{ + fprintf ( stderr, "GPUphysics: Usage -\n\n" ) ; + fprintf ( stderr, " GPUphysics_demo [-c][-p][-v][-a]\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, " -c -- Draw with physics but no ground collisions\n" ) ; + fprintf ( stderr, " -f -- Draw with physics but no forces\n" ) ; + fprintf ( stderr, " -a -- Draw with all features enabled [default]\n" ) ; + fprintf ( stderr, "\n" ) ; +} + + +int main ( int argc, char **argv ) +{ + 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 'c' : debugOpt = DRAW_WITHOUT_COLLISIONS ; break ; + case 'f' : debugOpt = DRAW_WITHOUT_FORCES ; break ; + case 'a' : debugOpt = DRAW_ALL ; break ; + + default : help () ; exit ( 0 ) ; + } + else + { + help () ; + exit ( 0 ) ; + } + } + + initGLcontext ( argc, argv, display ) ; + + initMotionTextures () ; + initPhysicsShaders () ; + initCubeVBO () ; + + glutMainLoop () ; + return 0 ; +} + diff --git a/Extras/GPUphysics/LICENSE b/Extras/GPUphysics/LICENSE new file mode 100644 index 000000000..ecc1a1005 --- /dev/null +++ b/Extras/GPUphysics/LICENSE @@ -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 +*/ + diff --git a/Extras/GPUphysics/Makefile b/Extras/GPUphysics/Makefile new file mode 100644 index 000000000..8062dbd48 --- /dev/null +++ b/Extras/GPUphysics/Makefile @@ -0,0 +1,19 @@ + +HDRS = fboSupport.h shaderSupport.h +OBJS = GPU_physics_demo.o fboSupport.o shaderSupport.o + +all: ${OBJS} + g++ -o GPU_physics_demo ${OBJS} -lglut -lGLEW -lGL + +shaderSupport.o : shaderSupport.cxx ${HDRS} + g++ -c shaderSupport.cxx + +fboSupport.o : fboSupport.cxx ${HDRS} + g++ -c fboSupport.cxx + +GPU_physics_demo.o : GPU_physics_demo.cxx ${HDRS} + g++ -c GPU_physics_demo.cxx + +clean: + -rm -f ${OBJS} + diff --git a/Extras/GPUphysics/Makefile.Mac b/Extras/GPUphysics/Makefile.Mac new file mode 100644 index 000000000..b0ef9ba00 --- /dev/null +++ b/Extras/GPUphysics/Makefile.Mac @@ -0,0 +1,19 @@ + +HDRS = fboSupport.h shaderSupport.h +OBJS = GPU_physics_demo.o fboSupport.o shaderSupport.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 -lGLEW -lGL -lGLU -lobjc + +shaderSupport.o : shaderSupport.cxx ${HDRS} + g++ -c shaderSupport.cxx + +fboSupport.o : fboSupport.cxx ${HDRS} + g++ -c fboSupport.cxx + +GPU_physics_demo.o : GPU_physics_demo.cxx ${HDRS} + g++ -c GPU_physics_demo.cxx + +clean: + -rm -f ${OBJS} + diff --git a/Extras/GPUphysics/README b/Extras/GPUphysics/README new file mode 100644 index 000000000..8ee76ae31 --- /dev/null +++ b/Extras/GPUphysics/README @@ -0,0 +1,105 @@ + +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 +cubeShader.frag -- Used to render the cubes. + +---------------------------------------------------------- +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! + + diff --git a/Extras/GPUphysics/cubeShader.frag b/Extras/GPUphysics/cubeShader.frag new file mode 100644 index 000000000..17a11a76c --- /dev/null +++ b/Extras/GPUphysics/cubeShader.frag @@ -0,0 +1,6 @@ + +void main() +{ + gl_FragColor = gl_Color ; +} + diff --git a/Extras/GPUphysics/cubeShader.vert b/Extras/GPUphysics/cubeShader.vert new file mode 100644 index 000000000..f6b10dff4 --- /dev/null +++ b/Extras/GPUphysics/cubeShader.vert @@ -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 ; +} + diff --git a/Extras/GPUphysics/fboSupport.cxx b/Extras/GPUphysics/fboSupport.cxx new file mode 100644 index 000000000..e87f2ec95 --- /dev/null +++ b/Extras/GPUphysics/fboSupport.cxx @@ -0,0 +1,261 @@ +#include +#include +#include + +// #define FBO_USE_NVIDIA_FLOAT_TEXTURE_EXTENSION 1 +#include + +#if defined(__APPLE__) && !defined (VMDMESA) +#include +#include +#include +#else +#include +#include +#endif +#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 : + /* choose different formats */ + break ; + default : + printf("status : %i\n",status); + assert ( 1 ) ; /* programming error; will fail on all hardware */ + } +} + + + +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 + statuc 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 ) ; +#endif + + // Check framebuffer completeness at the end of initialization. + + checkFrameBufferStatus () ; + restoreFrameBuffer () ; +} + + + +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 () ; +} + + diff --git a/Extras/GPUphysics/fboSupport.h b/Extras/GPUphysics/fboSupport.h new file mode 100644 index 000000000..62e870a1f --- /dev/null +++ b/Extras/GPUphysics/fboSupport.h @@ -0,0 +1,84 @@ + +GLuint makeTextureTarget ( GLuint textureHandle ) ; +void renderTo2DTexture ( GLuint fboHandle ) ; +void renderToFrameBuffer () ; + +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 ; + GLuint depth_rb ; + +#ifdef NEED_STENCIL + GLuint stencil_rb ; +#endif + + void fillTexture ( 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 () + { + glBindFramebufferEXT ( GL_FRAMEBUFFER_EXT, fboHandle ) ; + } + + void use ( int texture_unit ) + { + glActiveTexture ( GL_TEXTURE0 + texture_unit ) ; + glBindTexture ( GL_TEXTURE_2D, textureHandle ) ; + } + + void paint () ; + + void fillTexture ( float *data ) ; + void fillTexture ( unsigned char *data ) ; + + void fetchTexture ( float *data ) ; + void fetchTexture ( unsigned char *data ) ; +} ; + + +inline void restoreFrameBuffer () +{ + glBindFramebufferEXT ( GL_FRAMEBUFFER_EXT, 0 ) ; +} + diff --git a/Extras/GPUphysics/shaderSupport.cxx b/Extras/GPUphysics/shaderSupport.cxx new file mode 100644 index 000000000..3e7b8b562 --- /dev/null +++ b/Extras/GPUphysics/shaderSupport.cxx @@ -0,0 +1,441 @@ +#include +#include +#include +#include +#include +#ifndef WIN32 +#include +#endif +#include +#include +#if defined(__APPLE__) && !defined (VMDMESA) +#include +#include +#include +#else +#include +#include +#endif +#include "shaderSupport.h" +#include "fboSupport.h" + +static void showGLerror () +{ + GLenum err ; + + while ( (err = glGetError()) != GL_NO_ERROR ) + fprintf ( stderr, "OpenGL Error: %s\n", gluErrorString ( err ) ) ; +} + + +#define DEFAULT_VERT_SHADER \ + "void main()" \ + "{" \ + " gl_TexCoord[0] = gl_MultiTexCoord0 ;" \ + " 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 ; } +} ; + + + +/************************************\ +* * +* Low level File I/O junk * +* * +\************************************/ + +static int fSize ( const char *fname ) +{ + struct stat st ; + return ( stat ( fname, &st ) != -1 ) ? st . st_size : -1 ; +} + + +static char *readShaderText ( const char *fname ) +{ + int size = fSize ( fname ) ; + + char *shader = new char [ size + 1 ] ; + + FILE *fd = fopen ( fname, "r" ) ; + + 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 () ; + glGetObjectParameterivARB ( handle, GL_OBJECT_INFO_LOG_LENGTH_ARB, (GLint*) &len ) ; + showGLerror () ; + + 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 () ; + + 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 ) ; +} + + diff --git a/Extras/GPUphysics/shaderSupport.h b/Extras/GPUphysics/shaderSupport.h new file mode 100644 index 000000000..a76fcc2a2 --- /dev/null +++ b/Extras/GPUphysics/shaderSupport.h @@ -0,0 +1,79 @@ + +#include +#include + +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 ) ; + } + +} ; + +