我对经典的水波算法略微做了些扩展

效果图

这是效果图注意荷叶边的效果。

经典的水波算法:

//能量的扩散
  t=waterB[a-mWidth];
  b=waterB[a+mWidth];
  r=waterB[a+1];
  l=waterB[a-1];
  waterA[a]=((t+b+l+r)>>1)-waterA[a];
  //能量的衰减
   waterA[a]-=(waterA[a]>>6);

一个非常重要的依据--能量守恒。

在无阻尼前提下,一个时间内的所有水分子的能量之和是不变的

上面的能量的扩散就是按照这个原则实现的,感兴趣的话看一下

http://tech.163.com/05/0624/10/1N0LUJM600091589.html
http://www.chinaitpower.com/A/2001-12-20/8376.html

这里就不再重复了。

waterA,waterB是两个int 数组,用来保存和推演波的能量。

什么样的波会反射?

      简单的来说我打了老婆十下,老婆也打了我十下这样就相当与有十下被反射回来了。

      当一个水分子给左边的水分子的能量被原样返回时便使得水波想右反射了。

     当我们计算waterB到A的变换(也就是上一个时间点和下一个时间点的波的变换)时,如果该点的波的能量被忽略过去时,该点会保留原来的能量,并把它保存到了下一个时间段,然后把自身的能量想周围扩散。

下面是关键部分的代码:

 for(int a=mWidth;a<mArrayLen-mWidth;a++)
 {

//边缘反射
  if(a%mWidth==0)
   continue;

//根据障碍物计算波的反射
  if(this->mBarrier!=NULL&&this->mBarrier[a*mBarrierBytesPerPix]!=0)
   continue;
  int t,b,l,r;
  //能量的扩散
  t=waterB[a-mWidth];
  b=waterB[a+mWidth];
  r=waterB[a+1];
  l=waterB[a-1];
  waterA[a]=((t+b+l+r)>>1)-waterA[a];
  //能量的衰减
  if(m_decayFactor>0)
   waterA[a]-=(waterA[a]>>m_decayFactor);
  
 }
 COLOR_INT *temp=waterA;
 waterA=waterB;
 waterB=temp;
 
 int xoff,yoff;
 for(int u=1;u<mWidth-1;u++)
 {
  for(int v=1;v<mHeight-1;v++)
  { 
   //判断坐标是否在窗口范围内   
   xoff=waterA[u-1+v*mWidth]-waterA[u+1+v*mWidth];
   yoff=waterA[u+(v-1)*mWidth]-waterA[u+1+(v+1)*mWidth];
   if ((v+yoff )< 0 ) {continue;}
   if ((v+yoff )>mHeight) {continue;}
   if ((u+xoff )< 0 ) {continue;}
   if ((u+xoff )>mWidth ) {continue;}
   //计算出偏移象素和原始象素的内存地址偏移量
   int Color;
   int BackIndex=(u+xoff+(v+yoff)*mWidth)*mBarrierBytesPerPix;
   if(this->mBarrier!=NULL&&this->mBarrier[BackIndex]!=0){
    Color=(mBarrier[BackIndex]);
    for(int i=1;i<mBarrierBytesPerPix;i++)
     Color+=mBarrier[BackIndex+i]<<(8*i);    
   }
   else
   {
    Color=(mBackImage[BackIndex]);
    for(int i=1;i<mBackImageBytesPerPix;i++)
     Color+=mBackImage[BackIndex+i]<<(8*i);    
   }
   //result[u+mWidth*v]=RGB(yoff,xoff,0);
   result[u+mWidth*v]=Color;
  }
  
 }

mBackImage:

背景水草图

mBarrier:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
### 回答1: Unity是一种常用的游戏引擎,可以用于开发各种不同类型的游戏。在Unity中,可以使用液体体积的技术来实现水波效果。 实现水波效果主要涉及到液体物理模拟和图形渲染两个方面。首先,需要在Unity中创建一个液体模拟系统,可以使用Unity内置的物理系统或者导入第三方物理引擎,如NVIDIA PhysX,来模拟水体的运动和行为。通过对水体的质量、密度、阻力等参数进行调整,可以使得水体在受到外部力的作用下产生类似于真实水波的效果。 然后,需要对水体的形状和表面进行图形渲染,使其在场景中能够被观察到。可以使用Unity的渲染引擎来创建水体的表面效果,如波纹、泡沫等。通过添加次表面散射、反射、折射等效果,可以增强水体的真实感。 此外,在实现水波效果时,需要考虑到性能和效果的平衡。液体模拟和图形渲染对计算资源和GPU的消耗较大,因此需要根据实际需求和硬件性能进行适当的优化。可以通过减少物理模拟的计算量、使用低多边形模型等方式来提高性能。 总的来说,通过利用Unity的液体体积技术,结合物理模拟和图形渲染,可以实现逼真的水波效果,为游戏或虚拟现实场景增加更多的真实感和沉浸感。 ### 回答2: Unity中的Liquid Volume工具可以用来创建逼真的水波效果。Liquid Volume是一个用于生成液体体积和形状的渲染工具。在Unity中使用Liquid Volume工具来制作水波效果可以通过以下步骤进行: 首先,我们需要导入Liquid Volume插件到Unity项目中。将插件文件夹复制到项目的Assets文件夹中,并在Unity编辑器中导入插件。 接下来,在场景中创建一个游戏对象并将其设置为Liquid Volume物体。调整物体的大小和位置以适应我们想要的水波效果区域。 在Liquid Volume组件上,我们可以调整许多属性来实现所需的水波效果。例如,我们可以调整颜色、透明度和表面纹理等参数来实现逼真的水波外观。 为了模拟水波,我们可以在Liquid Volume对象上添加一个脚本。这个脚本可以在每一帧中通过修改物体的位置、大小和形状来模拟水波运动。我们可以使用Unity的时间函数和数学函数来计算水波效果。 最后,在场景中添加一些光源来照亮水波效果,并调整其他需要的设置,如阴影和反射等。 通过以上步骤,我们可以利用Unity中的Liquid Volume工具来创建逼真的水波效果。这个工具非常实用,可以用于游戏开发、虚拟现实、增强现实等领域,为水景、海洋、湖泊等场景带来更加真实的效果。 ### 回答3: Unity液体容积可以用于创建逼真的水波效果。首先,我们需要创建一个液体对象并将其添加到场景中。在液体对象上,我们可以调整其容器的大小、形状和高度,以适应场景的需求。接下来,我们需要在液体表面上应用水波效果。 为了实现水波效果,我们可以使用Unity的Shader图形编程语言编写着色器。在这个着色器中,我们可以使用不同的算法模拟液体的波动。其中一种常见的方法是使用傅里叶变换来生成波纹。我们可以通过在着色器中将傅里叶函数应用于液体表面的顶点位置来实现此效果。这将使得液体表面上的顶点位置根据傅里叶函数的输入值产生波动。 另一种方法是使用顶点和片段着色器来模拟液体的动态波纹。我们可以使用顶点着色器来将波浪传播到液体表面的顶点位置,并使用片段着色器来计算液体表面的颜色和透明度,以模拟波纹的外观。 除了波纹,我们还可以添加其他效果,例如反射和折射。通过使用反射贴图和折射贴图,我们可以模拟液体表面对光的反射和折射,使其看起来更加逼真。 最后,我们可以通过使用动画来控制水波的运动。我们可以在液体表面上创建一个脚本来动态修改液体属性,例如高度、速度和方向。通过控制这些属性,我们可以实现液体表面的动态波浪效果。 总而言之,通过使用Unity液体容积和着色器编程,我们可以实现逼真的水波效果。无论是在游戏中的水景还是在视觉特效中,这些技术都可以为场景增添真实感和动态效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值