
Author     : Steve Baker (sjbaker1@airmail.net)
Build using: 'make'
Run   using: 'GPU_physics_demo'
Requires   : A pretty modern graphics card - nVidia 6800 or better.
             Not tested on ATI hardware.
License    : zLib - see file: 'LICENSE'

----------------------------------------------------------
Demonstrates 16,384 cubes moving under the influence of
gravity and one other force - all with potentially different
masses, velocities, applied forces, etc.  The CPU is not
involved in any of the calculations - or even in applying
those calculations to the graphics when rendering the cubes.
----------------------------------------------------------
C++ Sources:

shaderSupport.cxx -- A wrapper layer for OpenGL/GLSL shaders.

fboSupport.cxx -- A wrapper layer for render-to-texture tricks.

GPU_physics_demo.cxx -- The application code.

----------------------------------------------------------
GLSLShader Sources used in the Demo:

cubeShader.vert
cubeShaderNoVertexTexture.vert
cubeShader.frag

----------------------------------------------------------
The objective of this library is to provide a basis for the
the Bullet physics engine to:

* Compile shader source code into a 'class GLSL_ShaderPair' object.
* Allocate an NxM texture that you can render into. (class FrameBufferObject)
* Populate a specified texture with floating point data.
* Run a specified shader on a specified set of textures - leaving the
  results in another specified texture.
* Demonstrate that this texture can be applied directly into the
  graphics code without any CPU intervention whatever.

-------------------------------------------------------------
Step 1: In initialisation code:

* Declare some number of FrameBufferObjects.  These are texture
  maps that you can render to that represent the 'variables'
  in the massively parallel calculations:

  eg:

  position = new FrameBufferObject ( 512, 512, 4, FBO_FLOAT ) ;

* Declare some number of GLSL_ShaderPair objects:

  /* GLSL code read from disk */

  teapotShaders = new GLSL_ShaderPair (
        "TeapotShader", "shader.vert", "shader.frag" ) ;

  /* ...or...Inline GLSL code */

  textureShaders = new GLSL_ShaderPair (
    "TextureShader",
    "void main() { gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; }",
    "Render2Texture Vert Shader",
    "void main() { gl_FragColor = vec4 ( 1, 1, 0, 1 ) ; }",
    "Render2Texture Frag Shader" ) )

* Check that they compiled OK:

  assert ( textureShaders -> compiledOK () ) ;
  assert ( teapotShaders  -> compiledOK () ) ;

Step 2: In the main loop:

* Select one shader pair to use to do the calculations:

  teapotShaders -> use () ;

* Set any 'uniform' parameters that the shader might need to be
  the same for all of the objects being calculated:

  teapotShaders -> setUniform3f ( "gravity", 0, -9.8f,0 ) ; 
  teapotShaders -> setUniform1f ( "delta_T", 0.016f ) ; 

* Assign slot numbers to any FBO/Textures that the shader uses as inputs
  and bind them to uniforms in the shader code:

  /* Texture 'slots' 0 up to about 15 */
  teapotShaders -> applyTexture ( "velocity" , velocityFBO, 0 ) ;
  teapotShaders -> applyTexture ( "accelleration", accnFBO, 1 ) ;

* Choose a target FBO/Texture as the place to store the results and
  render a polygon of suitable size to perform the calculations:

  position -> paint () ;

* Restore the frame buffer to normal so we can go back to using the GPU
  to do graphics:

  restoreFrameBuffer () ;

Step 3: Draw stuff!


