【博物纳新】Unity海洋场景构建
【博物纳新】是UWA重磅推出的全新栏目,旨在为开发者推荐新颖、易用、有趣的开源项目,帮助大家在项目研发之余发现世界上的热门项目、前沿技术或者令人惊叹的视觉效果,并探索将其应用到自己项目的可行性。很多时候,我们并不知道自己想要什么,直到某一天我们遇到了它。
更多精彩内容请关注:lab.uwa4d.com
导读
这个项目是基于Unity社区中一个经典Ocean shader多次改进后海洋场景,海平面实现了浮力、波浪、风、气泡、交互泡沫、焦散以及其他的一些光的反射折射效果。本文重点介绍海平面场景的构建,其他效果的实现不作重点介绍。
开源库地址:
https://lab.uwa4d.com/lab/5b442d9bd7f10a201faf74b5
Unity社区原版项目地址:
https://forum.unity.com/threads/wanted-ocean-shader.16540
效果展示:
普通效果
与岛屿交互
开启风效果,并设置较大风
使用方法
项目作者将重要参数可视化,在Inspector面板中进行修改。如果不太明白该参数的模拟的效果,可点击参数末尾的“?”按钮,会有详细的解释。
例如:Waves Settings 中的参数,由上而下依次可已设置波浪大小、波浪波动大小、流速、波浪密度。
Ocean Object属性面板
并在其中预置了一些参数集作为可选场景,大家也可以保存自己修改后的参数集,添加可选场景。
可选场景列表
实验原理/方法
- 浮力效果在Buoyancy中实现;
- 海平面的效果在Ocean.cs中实现,其中SetupOffscreenRendering、RenderReflectionAndRefraction等函数用于一些光影效果的实现,本文不做重点介绍,有兴趣的读者可以下载源代码研究。
开启折射反射效果
不开启折射反射效果
作者采用绘制Mesh作为海平面、采用LOD技术进行优化。
作者将海平面区域划分为如图所示的11*11块方形区域,采用5级LOD、最外层加载一个铜钱形状Mesh来填充最外围的场景。
海平面分割图
所有Mesh全部生成在名为Ocean的Object下,部分生成的Mesh列表如下:
Mesh列表
船体永远位于5*5Mesh区域内,LOD级别为LOD_0,绘制最为精细的细节与效果。其余部分采取较低级别LOD,如图所示:
普通场景
开启WireFrame
当船体移动,驶出该区域,Ocean 组件会计算偏移量,然后将Ocean Object整体移动一块Mesh的距离,例如,在场景开始后控制船体向X轴负方向前进,直至驶出该Mesh区域,此时Ocean Object通过计算,也平移了一段距离:
注意Mesh的移动
移动前
移动后
这样可以保证距离摄像机最近的地方显示效果最佳,距离摄像机较远的地方绘制的Mesh采用较低等级的LOD,以节省开销。
以下节选相应代码:
用于计算偏移量,来决定是否移动Ocean Object
:1 void calculateCenterOffset() {2 if (followMainCamera && player) {3 centerOffset.x = MyFloorInt(player.position.x * sizeInv.x) * size.x;4 centerOffset.z = MyFloorInt(player.position.z * sizeInv.y) * size.z;5 centerOffset.y = transform.position.y;6 if(transform.position != centerOffset) {7 ticked = true;8 transform.position = centerOffset; 9 //确保在偏移更改时立即更新LOD0
10 updateTiles(0, 1);
11 ticked2 = true;
12 }
13 //计算高度
14 if(player) {
15 if(farLodOffset!=0) {
16 flodFact = 1f - Mathf.Clamp01((player.position.y)*0.0007f);
17 //调整摄像机距离
18 ffact = MyFloorInt(flodFact*10.5f);
19 if(ffact != oldffact) {
20 oldffact = ffact;
21 ticked = true;
22 updateTiles(1, max_LOD);
23 }
24 }
25 }
26 }
27 }
产生Mesh并选择对应的LOD级别(变量christ):
1 void GenerateTiles() {23 int chDist, nmaxLod=0; // Chebychev distance45 //设置LOD级别6 for (int y=0; y<tiles; y++) {7 for (int x=0; x<tiles; x++) {8 chDist = System.Math.Max (System.Math.Abs (tiles / 2 - y), System.Math.Abs (tiles / 2 - x));9 chDist = chDist > 0 ? chDist - 1 : 0;
10 if(nmaxLod<chDist) nmaxLod = chDist;
11 }
12 }
13 max_LOD = nmaxLod+1;
14
15 flodoffset = new float[max_LOD+1];
16 float ffact = farLodOffset/max_LOD;
17 for(int i=0; i<max_LOD+1; i++) {
18 flodoffset[i] = i*ffact;
19 }
20
21 btiles_LOD = new List<Mesh>();
22 tiles_LOD = new List<List<Mesh>>();
23//添加Mesh
24 for (int L0D=0; L0D<max_LOD; L0D++) {
25 btiles_LOD.Add(new Mesh());
26 tiles_LOD.Add (new List<Mesh>());
27 }
28
29 GameObject tile;
30
31 int ntl = LayerMask.NameToLayer ("Water");
32
33 for (int y=0; y<tiles; y++) {
34 for (int x=0; x<tiles; x++) {
35 chDist = System.Math.Max (System.Math.Abs (tiles / 2 - y), System.Math.Abs (tiles / 2 - x));
36 chDist = chDist > 0 ? chDist - 1 : 0;
37 if(nmaxLod<chDist) nmaxLod = chDist;
38 float cy = y - Mathf.Floor(tiles * 0.5f);
39 float cx = x - Mathf.Floor(tiles * 0.5f);
40 tile = new GameObject ("Lod_"+chDist.ToString()+":"+y.ToString()+"x"+x.ToString());
41
42 Vector3 pos=tile.transform.position;
43 pos.x = cx * size.x;
44 pos.y = transform.position.y;
45 pos.z = cy * size.z;
46
47 tile.transform.position=pos;
48 tile.AddComponent <MeshFilter>();
49 tile.AddComponent <MeshRenderer>();
50 Renderer renderer = tile.GetComponent<Renderer>();
51
52 tile.GetComponent<MeshFilter>().mesh = btiles_LOD[chDist];
53 //tile.isStatic = true;
54
55 //选择Material
56 if(numberLods==2) {
57 if(chDist <= sTilesLod) { if(material) renderer.material = material; }
58 if(chDist > sTilesLod) { if(material1) renderer.material = material1; }
59 }else if(numberLods==3){
60 if(chDist <= sTilesLod ) { if(material) renderer.material = material; }
61 if(chDist == sTilesLod+1) { if(material1) renderer.material = material1; }
62 if(chDist > sTilesLod+1) { if(material2) renderer.material = material2; }
63 }
64 } else {
65 renderer.material = material;
66 }
67
68//设置为子节点
69 tile.transform.parent = transform;
70
71//也不希望在进行折射/反射传递时绘制这些,
72//所以将添加到水层以便于过滤。
73
74 tile.layer = ntl;
75
76 tiles_LOD[chDist].Add( tile.GetComponent<MeshFilter>().mesh);
77 }
78 }
79
80 //是否开启最外层铜钱状Mesh
81 initDisc();
82 }
不同的LOD级别也对应不同的Material
1mat[0] = material;
2 mat[1] = material1;
3 mat[2] = material2;
不同LOD级别的材质
性能测试
本次性能测试中,使用了开启多线程渲染的版本,分别在小米8、红米Note2两款设备上进行了测试,并使用UWA GOT Online获取性能数据。得到数据如下:
可以看到即使在红米Note2这样的低端机上,这个Demo也可以跑出平均46帧,在这样的效果来说属于性能非常不错的移动端海洋效果,推荐在移动设备上使用。
开源库传送门:
https://lab.uwa4d.com/lab/5b442d9bd7f10a201faf74b5
今天的推荐就到这儿啦,或者它可直接使用,或者它需要您的润色,或者它启发了您的思路~请不要吝啬您的点赞和转发,让我们知道我们在做对的事。当然如果您可以留言给出宝贵的意见,我们会越做越好。
快用UWA Lab合辑Mark好项目!
【博物纳新】Unity海洋场景构建相关推荐
- shader 反射 水面_【博物纳新】水面涟漪反射效果开源库测评
[博物纳新]是UWA重磅推出的全新栏目,旨在为开发者推荐新颖.易用.有趣的开源项目,帮助大家在项目研发之余发现世界上的热门项目.前沿技术或者令人惊叹的视觉效果,并探索将其应用到自己项目的可行性.很多时 ...
- 【博物纳新】Isaura—光环特效开源库评测
[博物纳新]是UWA重磅推出的全新栏目,旨在为开发者推荐新颖.易用.有趣的开源项目,帮助大家在项目研发之余发现世界上的热门项目.前沿技术或者令人惊叹的视觉效果,并探索将其应用到自己项目的可行性.很多时 ...
- 《基于Unity与SteamVR构建虚拟世界》(Yanlz+Unity+XR+SteamVR+LeapMotion+Neuron+Kinect+IMU+Kickstarter+立钻哥哥++ok++)
<基于Unity与SteamVR构建虚拟世界> <基于Unity与SteamVR构建虚拟世界> 版本 作者 参与者 完成日期 备注 SteamVR_Unity_V01_1.0 ...
- 一直在构建工作空间_基于用户场景构建的建筑工程弱电设计工作设想
[摘要]因为弱电产品更新速度快,功能差异变化大,往往会出现设计成果同预期有所区别的情况.针对类似情形,文章提出借鉴发展变化更加迅速的互联网行业中产品设计的理念,通过业主方或者设计方构建用户场景的手段, ...
- 智能驾驶仿真场景构建技术
随着汽车智能化程度的不断提高,智能汽车通过环境传感器与周边行驶环境的信息交互与互联更为密切,需应对的行驶环境状况也越来越复杂,包括行驶道路.周边交通和气象条件等诸多因素,具有较强的不确定性.难以重复. ...
- Unity大型场景程序化生成及优化技术—FPS迷宫生成和优化
Unity大型场景程序化生成及优化技术-FPS迷宫生成和优化 1.知名游戏中的大型场景生成 场景程序化生成技术是一个广泛应用在游戏开发中的技术,较早的使用这类技术有名游戏<暗黑破坏神>系列 ...
- SSM+在线纳新系统 毕业设计-附源码241540
基于SSM在线纳新系统 摘 要 21世纪时信息化的时代,几乎任何一个行业都离不开计算机,将计算机运用于在线纳新也是十分常见的.过去使用手工的管理方式对在线纳新进行管理,造成了管理繁琐.难以维护等问题, ...
- Unity(13)-场景切换,保留资源
文章目录 前言 其他介绍 上一篇笔记 一.项目结构 二.脚本 [1]. 场景切换 [2]. 资源保留 前言 在切换场景的时候会删除上一个场景的所有资源,所以需要给需要的游戏对象上挂载脚本,从而保留游戏 ...
- 虚幻引擎进行世界场景构建的总览-学习UE4需要首先学习的部分
本文由AlvinCR总结自官网视频教程: https://learn.unrealengine.com/course/3584597/module/6933184?moduletoken=UHxxnD ...
最新文章
- jquery获得option的值和对option进行操作
- 苹果状态栏HTML,CSS3实现苹果电脑的DOCK菜单栏_html/css_WEB-ITnose
- sicily 1345. 能量项链
- python数字求和为什么得不出结果_WPS表格求和问题,只出公式不出结果数字
- jsp代码编写简单的BBS论坛项目的总结
- windows10系统 java JDK下载安装及环境变量配置教程
- 嵌入式单片机及外设(硬件)知识基础一
- 以Crotex M3为例讲解stm32芯片内部原理
- 厦门大学2022年计算机考研复试流程
- 图片验证码 java_java生成图片验证码
- 计算机无法共享的原因,文件夹无法共享的原因及其解决办法
- Python爬虫:史上最详细的Python爬虫库urllib讲解,绝对经典,值得收藏
- 2020美团点评暑期实习一面
- 百度竞价十万个为什么
- java 音频解码_java视频音频解码-封装xuggle-实现多种视频编码格式解码扩展
- Android代码修改SIM的PIN码,中兴U970如何修改SIM卡或UIM卡的PIN码
- 飞信引发股价暴涨 神州泰岳背后的基金推手
- tags文件生成及使用
- c语言十进制转换八进制和十六进制
- DWA算法在局部路径规划中的应用
热门文章
- 【云原生 | 37】Docker快速部署编程语言Golang
- P5445 [APIO2019]路灯
- 旋转图片验证码(识别/破解)解决(一)
- iOS开发 国际化/多语言适配
- 二本大一新生拒绝摆烂,2个月后的觉醒
- 第六章 组合数据类型----元组
- 董老师又双叒叕送书啦,10本《Python程序设计入门与实践》
- 获取PancakeSwap Price
- The Annotated Diffusion Model(翻译)
- 年薪80万+年终奖汽车|显扬科技招聘三维机器视觉研发总监、高级三维算法工程师...