APP下载

基于Unity3D的水面波浪模拟

2020-04-24欧阳劲夫龚捷

电脑知识与技术 2020年5期
关键词:着色器

欧阳劲夫 龚捷

摘要:在游戏,电影以及其他应用领域中,对自然界的模拟成为研究热点。而水作为自然界中重要的元素,其研究价值不言而喻。在一个以水为背景的项目中,如海洋钻井模拟训练系统,战舰世界游戏等等,水的真实感将会成为项目好坏的评判标准之一。为了更好地模拟具有真实感的水面,该文使用了Unity3D引擎,C#语言编写,应用引擎自带的组件模拟光的反射折射,利用法线贴图代替公式计算,利用可视化编程制作水体着色器,从而达到低性能损耗,模拟效果较好的目的。

关键词:Unity3D;柏林噪声;uv纹理贴图坐标;着色器;C#

中图分类号:TP37 文献标识码:A

文章编号:1009-3044(2020)05-0219-02

开放科学(资源服务)标识码(OSID):

水在自然界中的存在十分普遍,对于水的模拟在许多应用领域都很有必要,例如水面的运动分析,物理校正流动模拟分析。对水的模拟加上一点特效,可以增强真实感,这在游戏和电影产业中非常盛行。然而,这种自然界独特的流体所具有的随机性,导致模拟计算水流需要复杂的算法和大量的计算性能。在这种情况下使用传统模拟3D流体的方法将意味着极其巨大的网格,以及海量的运算,使用这种方法在普通的计算机上是几乎不可能模拟出来的。然而Jerry Tessendorf 2004年提出的基于高度场的水面模拟,为普通计算机模拟水体提供了可能,甚至在现代大规模GPU计算下也能进行实时模拟。Unity是一款由Unity Technologies研发的跨平台2D/3D游戏引擎,可用于开发Windows、MacOS及Linux平台的游戏。Unity带有的Mesh Renderer组件可方便绘制模型的三角形网格,并对其编程,获取顶点高度数据,用来定义水面网格非常合适。而Shad-er -直是Unity开发者的一个难关,因为涉及数学,图形学,Shader语法等多个难题,而最新版本的Unity则推出了ShaderGraph,通过可视化界面编程,可以轻松实现着色器的创建和编辑。这为我们制作贴图流动,菲涅尔反射效应,光的反射折射,进而实现更为逼真的水体效果提供了便利。

1 实现过程

1.1 创建水面网格

首先新建Unity项目,然后在左侧菜单栏中创建一个空对象(Create Empty)并改名为Waves,用于容纳Waves脚本。然后创建Waves脚本。

private int[] GenerateTries0

{var tries= new int[Mesh.vertices.Length*6);

for(int x=0;x

{ for(int z=0;z

( tries[index(x,z)8 6+0]=index(x,z);

tries[index(x,z)*6+l]=index(x+1,z+1);

tries[index(x,Z)*6+2]=index(x+1,z);

tries[index(x,z)*6+3]=index(x,Z);

tries[index(x,Z)*6+4]=index(x,z+1);

tries[index(x,z)*6+5]=index(x+1,z+1);

]]

return tries;)

以上代码的作用为根据坐标生成三角形网格。然后在In-spector视窗中创建Mesh Renderer组件(Component),选用默认材质(Default Material),即可根据脚本生成所需的网格,在Wire-Frame模式中可预览效果。

1.2 柏林噪声

柏林噪声是一种自然噪声生成算法,由Ken Perlin提出,指在一维或二维空间中,对一个随机的点指定一个值和梯度。在噪声图像中,坐标轴不是整数,而是由梯度双线性内插法计算得来的值。柏林噪声和Navier-Stokes方程是生成水体随机高度数据非常有效的办法,但Navier-Stokes方程非常复杂且难以实现,所以在这个项目中使用法线贴图代替。

i{ (Octaves[o].alternate)

{var perl= Mathf.PerlinNoise《x*Octaves[o].scale.x)/Dimen-sion,(z*

Octaves[o].scale.y)/Dimension)*Mathf.PI*2f.

y+= Mathf. Cos(perl+Octaves[o]. speed. magnitude*Time.time)4

Octaves[o].height;}

else

*Octaves[o].speed.x),Dimension,(z*Octaves[o].scale.y+

Time.time*Octaves[o].speed.y)/Dimension) - 0.5f;

y+= perl*Octaves[o].height;]

以上操作完成后,应该得到了一个卷曲,运动的表面,但進入Unity阴影模式(Shaded Mode),表面并没有阴影或者高光,这是因为还没有计算顶点法线和生成UV动画。

1.3 生成uv动画

UV动面是一种常用的渲染技巧,经常用来描述水的流动、霓虹灯的闪烁等。实现的原理为动态修改贴图的UV坐标,使物体表面产生变化。用一张水波的贴图,处理其UV值,这样就用静态纹理和UV动画模拟出了动态水流动的效果。在这个项目中还可以让UV偏移与柏林噪声相关,实现较普通UV动画更为真实的水面模拟效果。

private Vector2[] GenerateUVs()

{ var uvs= new Vector2[Mesh.vertices.Length]

for (int x=0;x<=Dimension; x++)

{ for (int z=0;z<=Dimension; z++)

(var vec= new Vector2《x,UVScale)%2,(z/UVScale)%2);

uvs[index(x,z)]_new Vector2(vec.x<=1 7 vec.x:2 -

vec.x,vec.y<=1 7 vec.y:2- vec.y);}

return uvs;1

2 制作着色器(Shader)

接下来就是制作水面着色器(Shader),虽然Unity有白带的标准着色器,但效果一般,所以使用Unity的渲染管线(RenderPipeline)重新制作着色器。首先进入Unity界面,选择Window选项卡,选择Package Manager,安装Lightweight Render Pipeline(LWRP)。然后空白处右键创建着色器(Shader),选择PBRGraph,再创建一个材质(Material),使用刚创建好的PBR Graph。然后双击材质球即可进入Unity Shader Graph界面。图1着色器采样

4 总结

本文研究了使用Unity3D引擎模拟自然界水体的过程,其中包括使用网格组件构成了基本的水面,为下一步的渲染做准备;从网上下载了水面纹理的贴图,并处理其UV值,以较低的系统性能损耗模拟出了动态水流;运用Unity全新的Shader Graph可视化编程技术,方便快捷的制作了水体着色器,使模拟的真实感更强。

参考文献:

[1]平桉,程乃伟.基于Unity3D粒子系统的消防水枪流体喷射仿真研究[J].科技创新与应用,2017(9):42.

[2]赵忠琛,程乃伟.基于Unity3D的水波涟漪仿真模拟[J].山东工业技术,2017(8):293.

[3]胡能发.基于Unity3d游戏开发中地面及水下效果的渲染设计[J].电子世界,2015(22):161-162.

[4]余凡.基于Unity3d的福建省海洋立体实时观测网交互展示系统[J].数字技术与应用,2016(12):58-59.

[5]谭同德,赵硕,赵红领.应用折射反射纹理的实时水面仿真技术[J].郑州大学学报:工学版,201 1,32(2):88-92.

【通聯编辑:唐一东】 收稿日期:2019 -11-15

作者简介:欧阳劲夫(1994-),男,硕士,主要研究方向为虚拟现实与计算机模拟;龚捷,男,副教授,主要研究方向为计算机模拟,计算机网络。

猜你喜欢

着色器
零建模也能制作“大波浪”,Blender着色器教程
“魔戒”铸造指南:Blender建模着色教程
基于UE4 实时射线追踪技术的研究与探讨
基于Unity Shader石油泄漏现象模拟的研究
基于IMx6的opengl图形着色器开发研究
基于可编程GPU的光照模型实验案例设计
基于WebGL的在线图像浏览器的设计与实现
河道流动水体三维仿真方法研究
DirectX 12来临! 异步着色器让你轻松玩游戏
基于可编程渲染管线的雷达图像分层模型设计与实现