2

我正在尝试使用GPU 上的快速水力侵蚀模拟和可视化论文作为模拟水的模板来实现流体表面模拟。但是,我得到这样的工件:

波伪影

我的更新功能的代码如下,我已经关注了关于这个主题的另一篇文章,但更改没有帮助。

    private void updateHeight (float dt, float dx){
    float dhL, dhR, dhF, dhB, DV;
    float totalFlux;
    float updateConstant;
    float fluxConstant = dt*GRAVITY/(2*VISCOUSCOEFFICEINT*dx);
    //Update Flux
    for (int y=1; y<=N-1; y++){
        for(int x=1;x<=N-1;x++){
            dhL = this.height[x][y] - this.height[x-1][y];
            dhR = this.height[x][y] - this.height[x+1][y];
            dhF = this.height[x][y] - this.height[x][y+1];
            dhB = this.height[x][y] - this.height[x][y-1];

            if (Mathf.Abs(dhL) < 0.0001f){
                dhL=0.0f;
            }
            if (Mathf.Abs(dhR) < 0.0001f){
                dhR=0;
            }
            if (Mathf.Abs(dhF) < 0.0001f){
                dhF=0;
            }
            if (Mathf.Abs(dhB) < 0.0001f){
                dhB=0;
            }

            this.tempFluxArray[x][y].fluxL = Mathf.Max(0.0f, this.fluxArray[x][y].fluxL + fluxConstant*dhL);
            this.tempFluxArray[x][y].fluxR = Mathf.Max(0.0f, this.fluxArray[x][y].fluxR + fluxConstant*dhR);
            this.tempFluxArray[x][y].fluxF = Mathf.Max(0.0f, this.fluxArray[x][y].fluxF + fluxConstant*dhF);
            this.tempFluxArray[x][y].fluxB = Mathf.Max(0.0f, this.fluxArray[x][y].fluxB + fluxConstant*dhB);

            totalFlux = this.tempFluxArray[x][y].fluxL + this.tempFluxArray[x][y].fluxR + this.tempFluxArray[x][y].fluxF + this.tempFluxArray[x][y].fluxB;

            if(totalFlux > 0){
                updateConstant = Mathf.Min(1.0f, this.height[x][y]* dx*dx/(totalFlux * dt));
                this.tempFluxArray[x][y].fluxL = updateConstant * this.tempFluxArray[x][y].fluxL;
                this.tempFluxArray[x][y].fluxR = updateConstant * this.tempFluxArray[x][y].fluxR;
                this.tempFluxArray[x][y].fluxF = updateConstant * this.tempFluxArray[x][y].fluxF;
                this.tempFluxArray[x][y].fluxB = updateConstant * this.tempFluxArray[x][y].fluxB;
            }
        }
    }
    swap();
    //Height Calculation
    for (int y=1; y<=N-1; y++){
        for(int x=1;x<=N-1;x++){
            DV = dt*(this.fluxArray[x-1][y].fluxR + this.fluxArray[x][y-1].fluxF + this.fluxArray[x+1][y].fluxL + this.fluxArray[x][y+1].fluxB - this.fluxArray[x][y].fluxL - this.fluxArray[x][y].fluxR - this.fluxArray[x][y].fluxF - this.fluxArray[x][y].fluxB);
            this.height[x][y] = this.height[x][y] + DV/(dx*dx);
            if(this.height[x][y] < 1){
                // Debug.Log(x);
                // Debug.Log(y);
            }
        }
    }
}

可能是因为使用 this 而不是 ref 吗?我与下面写的水面互动的方式。

    private void waterdrop(int x, int y){
    float sqrD = 0.8f*0.8f;
    for (int j = 1; j < N; j++) {
        for (int i = 1; i < N; i++) {
            float sqrDToVert = (float)0.2f*(i - x)*(i-x) + 0.2f*(j - y)*(j-y);
            if (sqrDToVert <= sqrD){
                float distanceCompensator = 1 - (sqrDToVert/sqrD);
                this.fluxArray[i][j].fluxL = this.fluxArray[i][j].fluxL + (0.02f * distanceCompensator);
                this.fluxArray[i][j].fluxR = this.fluxArray[i][j].fluxR + (0.02f * distanceCompensator);
                this.fluxArray[i][j].fluxF = this.fluxArray[i][j].fluxF + (0.02f * distanceCompensator);
                this.fluxArray[i][j].fluxB = this.fluxArray[i][j].fluxB + (0.02f * distanceCompensator);
                //this.height[i][j] = this.height[i][j] - 1.0f * distanceCompensator;
                Debug.Log(this.height[i][j]);
            }
            //Debug.Log("x = "+i+"\n y = "+j+" height is "+this.height[i][j]);
        }
    }
}

即只是在各个方向的某个点改变通量。

我尝试过的一些解决方案是改变高度,但这不起作用或仅限制小的变化,但它只是建立起来。边界条件是所有边界上的零通量,并且高度将与最近点相同。

4

0 回答 0