• Introduction to my galaxy engine 8 : Real Time Fluid Rendering


    最近正在研究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

    References:

    [1] GPU Gems, Chapter 38. Fast Fluid Dynamics Simulation on the GPU

    [2] GPU Germs, CHAPTER 30. REAL-TIME SIMULATION AND RENDERING OF 3D FLUIDS

    [3] 关于Vorticity的介绍 http://www.student.math.uwaterloo.ca/~amat361/Fluid%20Mechanics/topics/vorticity.htm

    [4] NVIDA SDK http://developer.nvidia.com/gpu-computing-sdk

  • 相关阅读:
    swiper 内容超出纵向滚动 解决办法
    js判断 微信浏览器 或者 QQ内置浏览器
    移动端滑动 增加弹性 滑动更加顺畅
    移动端点击激活时背景色
    文字两端对齐
    移动端元素被选中时,去除背景
    CSS动画 防止动画结束后,回归原位
    centos 防火墙配置
    知识图谱研究
    jmeter 压测工具
  • 原文地址:https://www.cnblogs.com/RobinG/p/2545028.html
Copyright © 2020-2023  润新知