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