Example #1
0
/**
 * @fn Flo::Initialize()
 * @brief Initializes the Flo simulator.
 * 
 * Here we initialize the simulation.
 */ 
void Flo::Initialize(CGcontext context)
{
  // create the offscreen buffer -- this has to be a float buffer because
  // we need float precision for the simulation.
  _pOffscreenBuffer = new RenderTexture(_iWidth, _iHeight, false);
  
  // Offscreen buffer does not update a texture object, it calls 
  // wglShareLists, it has no depth/stencil, mipmaps, or aniso filtering.  
  // 32 bits per channel.
  _pOffscreenBuffer->Initialize(true, false, false, false, false, 
                                32, 32, 32, 32);

  // Set the constant state for the pbuffer.
  _pOffscreenBuffer->BeginCapture();
  {
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glMatrixMode(GL_PROJECTION);
    gluOrtho2D(0, 1, 0, 1);
    glDisable(GL_DEPTH_TEST);
    glClearColor(0, 0, 0, 0);
  }
  _pOffscreenBuffer->EndCapture();
  
  // create texture objects -- there are four: velocity, pressure, divergence,
  // and density.  All are float textures.
  int iTex = 0;
  glGenTextures(TEXTURE_COUNT, _iTextures);
  for (iTex = 0; iTex < TEXTURE_COUNT; ++iTex)
  {
    glBindTexture(GL_TEXTURE_RECTANGLE_NV, _iTextures[iTex]);
    glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, GL_FLOAT_RGBA_NV, 
                 _iWidth, _iHeight, 0, GL_RGBA, GL_FLOAT, NULL);
    
    glTexParameteri(GL_TEXTURE_RECTANGLE_NV, 
                    GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_RECTANGLE_NV, 
                    GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_RECTANGLE_NV, 
                    GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_RECTANGLE_NV, 
                    GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  }

  glGenTextures(1, &_iBCTexture);
  glBindTexture(GL_TEXTURE_RECTANGLE_NV, _iBCTexture);
  glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, GL_RGBA8,
               _iWidth, _iHeight, 0, GL_RGBA, GL_FLOAT, NULL);
  
  glTexParameteri(GL_TEXTURE_RECTANGLE_NV, 
                  GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  glTexParameteri(GL_TEXTURE_RECTANGLE_NV, 
                  GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  glTexParameteri(GL_TEXTURE_RECTANGLE_NV, 
                  GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  glTexParameteri(GL_TEXTURE_RECTANGLE_NV, 
                    GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

  _ClearTexture(_iBCTexture);

  glGenTextures(1, &_iBCDisplayTexture);
  glBindTexture(GL_TEXTURE_2D, _iBCDisplayTexture);
  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 64, 64, 0, GL_RGBA, GL_FLOAT, NULL);

  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

  _ClearTexture(_iBCDisplayTexture, GL_TEXTURE_2D);
  
  // create the display texture
  glGenTextures(1, &_iDisplayTexture);
  glBindTexture(GL_TEXTURE_2D, _iDisplayTexture);
  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, _iWidth, _iHeight, 
			   0, GL_RGBA, GL_FLOAT, NULL);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);


  unsigned char *bcColor = NULL;
  int bcWidth, bcHeight, bcChannels;
  LoadTGA("bc.tga", bcColor, bcWidth, bcHeight, bcChannels);

  glGenTextures(1, &_iBCDetailTexture);
  glBindTexture(GL_TEXTURE_2D, _iBCDetailTexture);
  glTexImage2D(GL_TEXTURE_2D, 0, bcChannels == 3 ? GL_RGB8 : GL_RGBA8, 
               bcWidth, bcHeight, 0, bcChannels == 3 ? GL_RGB : GL_RGBA, 
               GL_UNSIGNED_BYTE, bcColor);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);


  _CreateOffsetTextures();

  // Initialize the slabops...
  _InitializeSlabOps(context);

  // clear the textures
  Reset();
}
Example #2
0
void FluidBase::Initialize(CGcontext context)
{
    _CreateOffsetTextures();

    data_path media;
    media.path.push_back(".");
	media.path.push_back("Media");

    std::string programsPath = media.get_path("programs/gpgpu_fluid/flo.cg");
    if (programsPath.empty())
    {
        printf("Error: Unable to locate Cg programs...\n");
    }

    programsPath += "/";

    std::string args = "-I" + programsPath;
    std::vector<const char*> fpargs;
    fpargs.clear();
    fpargs.push_back(args.c_str());
    fpargs.push_back(0);

    // Compute the minimum and maximum vertex and texture coordinates for 
    // rendering the Stream interiors (sans boundaries).
    float xMin  = 1.0f / (float)_iWidth;         // one pixel from left
    float xMax  = 1.0f - 1.0f / (float)_iWidth;  // one pixel from right
    float yMin  = 1.0f / (float)_iHeight;        // on pixel from bottom
    float yMax  = 1.0f - 1.0f / (float)_iHeight; // one pixel from top

    float sMin  = 1.0f;                          // the same, this time in 
    float sMax  = (float)_iWidth - 1.0f;         // texture coordinates
    float tMin  = 1.0f;
    float tMax  = (float)_iHeight - 1.0f;
//*?* I think this is where at least one change goes.
	/*xMin = sMin;
	xMax = sMax;
	yMin = tMin;
	yMax = tMax;*/

    // Add Impulse.  This renders a Gaussian "splat" into the specified texture,
    // with the specified position, radius, and color.
    _addImpulse.InitializeFP(context, programsPath + "splat.cg", "splat");
    _addImpulse.SetFragmentParameter2f("windowDims", 
                                       (float)_iWidth, (float)_iHeight);
    _addImpulse.SetTexCoordRect(0, sMin, tMin, sMax, tMax);
    _addImpulse.SetStreamRect(xMin, yMin, xMax, yMax);

    // Advection:  This advects a field by the moving velocity field.  This is 
    // used to advect both velocity and scalar values, such as mass.  The result
    // of applying this to the velocity field is a moving but divergent velocity
    // field.  The next few steps correct that divergence to give a divergence-
    // free velocity field.
    _advect.SetFPArgs(fpargs);
    _advect.InitializeFP(context, programsPath + "flo.cg", "advect");
    _advect.SetFragmentParameter1f("rdx", 1.0f / _dx);
    _advect.SetFragmentParameter1f("dissipation", 1);
    _advect.SetTexCoordRect(0, sMin, tMin, sMax, tMax);
    _advect.SetStreamRect(xMin, yMin, xMax, yMax);

    // Divergence of velocity: This computes how divergent the velocity field is
    // (how much in/out flow there is at every point).  Used as input to the 
    // Poisson solver, below.
    _divergence.SetFPArgs(fpargs);
    _divergence.InitializeFP(context, programsPath + "flo.cg", "divergence");
    _divergence.SetFragmentParameter1f("halfrdx", 0.5f / _dx);
    _divergence.SetTexCoordRect(0, sMin, tMin, sMax, tMax);
    _divergence.SetStreamRect(xMin, yMin, xMax, yMax);

    // Poisson-pressure solver: By running this Jacobi Relaxation solver for 
    // multiple iterations, this solves for the pressure disturbance in the 
    // fluid given the divergence of the velocity.
    _poissonSolver.SetFPArgs(fpargs);
    _poissonSolver.InitializeFP(context, programsPath + "flo.cg", "jacobi");
    _poissonSolver.SetFragmentParameter1f("alpha", -_dx * _dx);
    _poissonSolver.SetFragmentParameter1f("rBeta", 0.25f);
    _poissonSolver.SetTexCoordRect(0, sMin, tMin, sMax, tMax);
    _poissonSolver.SetStreamRect(xMin, yMin, xMax, yMax);

    // Poisson solver for viscous diffusion: By running this Jacobi Relaxation 
    // solver for multiple iterations, this solves for the velocity diffusion in 
    // a viscous fluid.
    _poissonSolverVec2.SetFPArgs(fpargs);
    _poissonSolverVec2.InitializeFP(context, programsPath + "flo.cg", "jacobiVec2");
    _poissonSolverVec2.SetTexCoordRect(0, sMin, tMin, sMax, tMax);
    _poissonSolverVec2.SetStreamRect(xMin, yMin, xMax, yMax);

    // Subtract Gradient.  After solving for the pressure disturbance, this 
    // subtracts the pressure gradient from the divergent velocity field to 
    // give a divergence-free field.
    _subtractGradient.SetFPArgs(fpargs);
    _subtractGradient.InitializeFP(context, programsPath + "flo.cg", "gradient");
    _subtractGradient.SetFragmentParameter1f("halfrdx", 0.5f / _dx);
    _subtractGradient.SetTexCoordRect(0, sMin, tMin, sMax, tMax);
    _subtractGradient.SetStreamRect(xMin, yMin, xMax, yMax);

    // vorticity computation.
    _vorticity.SetFPArgs(fpargs);
    _vorticity.InitializeFP(context, programsPath + "flo.cg", "vorticity");
    _vorticity.SetFragmentParameter1f("halfrdx", 0.5f / _dx);
    _vorticity.SetTexCoordRect(0, sMin, tMin, sMax, tMax);
    _vorticity.SetStreamRect(xMin, yMin, xMax, yMax);

    // vorticity confinement force computation.
    _vorticityForce.SetFPArgs(fpargs);
    _vorticityForce.InitializeFP(context, programsPath + "flo.cg", "vortForce");
    _vorticityForce.SetFragmentParameter1f("halfrdx", 0.5f / _dx);
    _vorticityForce.SetTexCoordRect(0, sMin, tMin, sMax, tMax);
    _vorticityForce.SetStreamRect(xMin, yMin, xMax, yMax);

    // This applies pure neumann boundary conditions (see floPoissonBC.cg) to 
    // the pressure field once per iteration of the poisson-pressure jacobi 
    // solver.  Also no-slip BCs to velocity once per time step.
    _boundaries.SetFPArgs(fpargs);
    _boundaries.InitializeFP(context, programsPath + "flo.cg", "boundary");
    _boundaries.SetTexCoordRect(0, 0, (float)_iWidth, (float)_iHeight);
    _boundaries.SetTexResolution(_iWidth, _iHeight);
    _boundaries.SetFragmentParameter1f("scale", 0);

    _updateOffsets.SetFPArgs(fpargs);
    _updateOffsets.InitializeFP(context, programsPath + "flo.cg", "updateOffsets");
    _updateOffsets.SetTexCoordRect(0, 0, 0, (float)_iWidth, (float)_iHeight);
    _updateOffsets.SetStreamRect(xMin, yMin, xMax, yMax);

    // setup the arbitrary boundary operations.
    _arbitraryVelocityBC.SetFPArgs(fpargs);
    _arbitraryVelocityBC.InitializeFP(context, programsPath + "flo.cg", 
                                      "arbitraryVelocityBoundary");
    _arbitraryVelocityBC.SetTexCoordRect(0, 0, 0, (float)_iWidth, (float)_iHeight);
    _arbitraryVelocityBC.SetStreamRect(xMin, yMin, xMax, yMax);

    _arbitraryPressureBC.SetFPArgs(fpargs);
    _arbitraryPressureBC.InitializeFP(context, programsPath + "flo.cg", 
                                      "arbitraryPressureBoundary");
    _arbitraryPressureBC.SetTexCoordRect(0, 0, 0, (float)_iWidth, (float)_iHeight);
    _arbitraryPressureBC.SetStreamRect(xMin, yMin, xMax, yMax);

    _zcullSetupBoundaries.SetFPArgs(fpargs);
    _zcullSetupBoundaries.InitializeFP(context, programsPath + "flo.cg", "zCullSetupBoundaries");
    _zcullSetupBoundaries.SetTexCoordRect(0, 0, (float)_iWidth, (float)_iHeight);
    _zcullSetupBoundaries.SetStreamRect(xMin, yMin, xMax, yMax, 1);

    _zcullSetupPressure.SetFPArgs(fpargs);
    _zcullSetupPressure.InitializeFP(context, programsPath + "flo.cg", "zCullSetupPressure");
    _zcullSetupPressure.SetTexCoordRect(0, 0, (float)_iWidth, (float)_iHeight);
    _zcullSetupPressure.SetStreamRect(xMin, yMin, xMax, yMax, 1);
}