最近正在研究real time fluid effect方面的问题,主要适用于液体,烟雾,火焰方面的实时模拟。一般是通过GPGPU(general purpose GPU)来实现的。
以下是2D Fluid初步实验的截图:
要理解实现原理,首先要熟悉其基于的物理模型:“stable fluids” by Stam 1999. 从实现角度来说,根据fluid effect的计算公式
主要考虑如下几个要素:Advection [气]水平对流, pressure, diffusion, (Vorticity [涡旋] Confinement 主要用于烟雾,火焰), external forces. 每一个要素的作用大小是通过读取其对应的图片来获取的。
具体实现步骤如下:
1.将屏幕分为一定大小数量的网格,如图所示:
由于我的窗口大小设定为800*600,横行分为了80*2格,纵向分为了60*2格.之后的相关计算都是以格子为单位。蓝色为边界部分,不做为渲染区域。
2. 根据网格生成顶点。
VS_INPUT_FLUIDSIM_STRUCT tempVertex1;
VS_INPUT_FLUIDSIM_STRUCT tempVertex2;
VS_INPUT_FLUIDSIM_STRUCT tempVertex3;
VS_INPUT_FLUIDSIM_STRUCT tempVertex4;
int w = m_dim[0];
int h = m_dim[1];
float left = -1.0f + 2.0f/w;//exclude the boundary cell, each cell size is 2.0f/w
float right = 1.0f - 2.0f/w;
float top = 1.0f - 2.0f/h;
float bottom = -1.0f + 2.0f/h;
tempVertex1.Pos = D3DXVECTOR3( left, top, 0.0f);//projection screen pos
tempVertex1.Tex = D3DXVECTOR3( 1.0f, 1.0f, 0.0f);//texture pos, exclude boundary cell
tempVertex2.Pos = D3DXVECTOR3( right, top, 0.0f);
tempVertex2.Tex = D3DXVECTOR3( (w-1.0f), 1.0f, 0.0f);
tempVertex3.Pos = D3DXVECTOR3( right, bottom, 0.0f);
tempVertex3.Tex = D3DXVECTOR3( (w-1.0f), (h-1.0f), 0.0f);
tempVertex4.Pos = D3DXVECTOR3( left, bottom, 0.0f);
tempVertex4.Tex = D3DXVECTOR3( 1.0f, (h-1.0f), 0.0f);
(*vertices)[index++] = tempVertex1;
(*vertices)[index++] = tempVertex2;
(*vertices)[index++] = tempVertex3;
(*vertices)[index++] = tempVertex1;
(*vertices)[index++] = tempVertex3;
(*vertices)[index++] = tempVertex4;
3. 生成速度场velocity field。
液体的流动,是由于外力的作用,在这里,力的大小我们通过每一个点的速度大小来度量。屏幕上每一点的速度保存在屏幕大小的一张图片上,如图所示:
由于是2D,所以只有X,Y平面上的速度。X方向的力用红色表示,Y方向的力用绿色表示。颜色深度表示力的大小。需要注意的是此图中只能看到正向方向的力,负向方向力由于图片颜色最小值为0,负值被截去了所以的里看不出来,但实际从render target中是可以读出负值的。
速度场的计算方式有很多种,在这里我用的是gaussian splat,公式如下:
速度场大小是随半径大小成指数递减的,公式中大括号里少了个负号。代码表示为spaltColor = force * exp(-dist / g_Radius);
4. 生成油墨,烟或者火焰。
实现方法类似速度场,不过我稍作了改变,用了这个公式:spaltColor = force * (dist < g_Radius ? 1.0f : 0.0f);
5. Advection.
有了速度场,就可以计算单位时间内油墨的偏移量和速度场自身的偏移量。原理图如下:
u(x,t)点的颜色值用X点的颜色值来更新。两者的距离为u(x,t)乘以单位时间g_TimeStep。
6. Diffustion.迭代计算公式如下:
a = (dx)2/vdt, and b = 4 + a.
v表示速度,为定值。dx此处为1. x表示需要更新的速度值,通过N次迭代计算更新。Diffuse还可作用于颜色上,此时v表示之前的颜色值,X表示更新的颜色值。
7. Vorticity confinement
。。。。。。。。。内容太多,明天继续。。。。。。。。。。。。。。
8. Velocity Divergence.
9. Pressure.
10. Project Velocity
11.static obstacle