public static MultiGridLinearSolver2D Build(int maxLevel, int finerWidth, int finerHeight,
                                                RenderTexture2D level0Pressure, RenderTexture2D level0PressureSwap,
                                                RenderTexture2D level0Marker, RenderTexture2D level0Divergence,
                                                RenderTexture2D level0Levelset)
    {
        MultiGridLinearSolver2D multiGridSolver = new MultiGridLinearSolver2D();

        multiGridSolver.mMaxLevel             = maxLevel;
        multiGridSolver.mCellMakerArray       = new RenderTexture2D[maxLevel];
        multiGridSolver.mResidualTexArray     = new RenderTexture2D[maxLevel];
        multiGridSolver.mErrorTexArray        = new RenderTexture2D[maxLevel];
        multiGridSolver.mErrorTexSwapArray    = new RenderTexture2D[maxLevel];
        multiGridSolver.mRightPoissonTexArray = new RenderTexture2D[maxLevel];
        multiGridSolver.mLevelsetArray        = new RenderTexture2D[maxLevel];
        // sets level0
        multiGridSolver.mRightPoissonTexArray[0] = level0Divergence;
        multiGridSolver.mCellMakerArray[0]       = level0Marker;
        multiGridSolver.mResidualTexArray[0]     = new RenderTexture2D(finerWidth, finerHeight, "MG_Residual" + 0.ToString());
        multiGridSolver.mErrorTexArray[0]        = level0Pressure;
        multiGridSolver.mErrorTexSwapArray[0]    = level0PressureSwap;
        multiGridSolver.mLevelsetArray[0]        = level0Levelset;
        for (int i = 1; i < maxLevel; i++)
        {
            int currentWidth  = finerWidth >> i;
            int currentHeight = finerHeight >> i;
            multiGridSolver.mCellMakerArray[i]       = new RenderTexture2D(currentWidth, currentHeight, "MG_CellMarker" + i.ToString(), RenderTextureFormat.RInt);
            multiGridSolver.mLevelsetArray[i]        = new RenderTexture2D(currentWidth, currentHeight, "MG_Levelset" + i.ToString());
            multiGridSolver.mResidualTexArray[i]     = new RenderTexture2D(currentWidth, currentHeight, "MG_Residual" + i.ToString());
            multiGridSolver.mErrorTexArray[i]        = new RenderTexture2D(currentWidth, currentHeight, "MG_Error" + i.ToString());
            multiGridSolver.mErrorTexSwapArray[i]    = new RenderTexture2D(currentWidth, currentHeight, "MG_ErrorSwap" + i.ToString());
            multiGridSolver.mRightPoissonTexArray[i] = new RenderTexture2D(currentWidth, currentHeight, "MG_RightPoisson" + i.ToString());
        }
        return(multiGridSolver);
    }
    private void InitFluidStartStage()
    {
        int initKernel = mComputeInitialize.FindKernel("InitFluid");

        UploadGlobalParameters(mComputeInitialize);
        mComputeInitialize.SetTexture(initKernel, "gLevelSet", mLevelSet[READ].Source);
        mComputeInitialize.SetTexture(initKernel, "gVelocityU", mVelocityU[READ].Source);
        mComputeInitialize.SetTexture(initKernel, "gVelocityV", mVelocityV[READ].Source);
        mComputeInitialize.Dispatch(initKernel, Mathf.CeilToInt(mWidth * 1.0f / mGroupThreadSizeX), Mathf.CeilToInt(mHeight * 1.0f / mGroupThreadSizeX), 1);

        UpdateFluidGridMarker();//

        if (mPressureSolverType == FluidPressureSolverType.MultiGridFMG ||
            mPressureSolverType == FluidPressureSolverType.MultiGridVCycle)
        {
            int maxLevel = 3;
            mMultiGridSolver = MultiGridLinearSolver2D.Build(maxLevel, mWidth, mHeight, mPressure,
                                                             mPressureWrite, mGridMarker, mDivergence, mLevelSet[READ]);
            mMultiGridSolver.SetMGComputeShaders(mComputePressure,
                                                 mComputeRestrict, mComputeResidual, mComputePrologation, mComputeCorrect);
        }
    }