added Steven Baker's GPU physics code (work in progress)

This commit is contained in:
ejcoumans
2006-09-18 20:16:43 +00:00
parent d87a85ae97
commit b548455ae9
14 changed files with 1796 additions and 0 deletions

29
Extras/GPUphysics/CHANGES Normal file
View File

@@ -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

View File

@@ -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
)

View File

@@ -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.

View File

@@ -0,0 +1,553 @@
#ifndef WIN32
#include <sys/time.h>
#endif
#include <assert.h>
#include <GL/glew.h>
//think different
#if defined(__APPLE__) && !defined (VMDMESA)
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#include <GL/gl.h>
#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 ;
}

25
Extras/GPUphysics/LICENSE Normal file
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,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}

View File

@@ -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}

105
Extras/GPUphysics/README Normal file
View File

@@ -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!

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,261 @@
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
// #define FBO_USE_NVIDIA_FLOAT_TEXTURE_EXTENSION 1
#include <GL/glew.h>
#if defined(__APPLE__) && !defined (VMDMESA)
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#include <GL/gl.h>
#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 () ;
}

View File

@@ -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 ) ;
}

View File

@@ -0,0 +1,441 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifndef WIN32
#include <unistd.h>
#endif
#include <assert.h>
#include <GL/glew.h>
#if defined(__APPLE__) && !defined (VMDMESA)
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#include <GL/gl.h>
#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 ) ;
}

View File

@@ -0,0 +1,79 @@
#include <stdio.h>
#include <stdlib.h>
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 ) ;
}
} ;