【Unity】移动端草海解决方案

news2024/9/22 17:37:28

      草海是开放大世界渲染的必不可少的因素,Unity 原生的 Terrain 草海效率较低,而且无法与 RVT 结合起来,无法在移动端上实现。因此我们自己搓出来一套草海系统,使用 C# 多线程辅助运算,并能支持割草、烧草等进阶玩法。草的位置、密度、类型还需要根据美术和地形的信息进行自适应。

        最终效果可以看这个演示视频(虽然这个视频美术表现力不行,但是已经可以看到 GpuTerrain基础下的实时运算的草海效果了。对于游戏开发者而言,显然能明白这个演示已经实现了既定目标)

GpuTerrain+草海_哔哩哔哩_bilibili地形用GpuTerrain渲染;草海是自定义实时生成运算+Gpu渲染。, 视频播放量 103、弹幕量 0、点赞数 0、投硬币枚数 0、收藏人数 0、转发人数 0, 视频作者 魔术师dix, 作者简介 我们这么努力,不是为了改变世界,而是为了不让世界改变我们。,相关视频:Island_G效果演示(8月版本),原型工程1.0演示视频,玲珑岛12贴图版本_1.0,Unity3D 战斗系统核心技术: 高度可扩展的技能与多Buff系统(收藏级),【中配】A*寻路算法:算法解释 - Sebastian Lague,很多3a游戏的马还不如塞尔达的真实生动,新动作又被虐了,Skyrim Special Edition-定海神针-金箍棒,【Unity3D/资产发布】拟真向URP海面渲染系统——HigWaterSystem,游戏,还是现实?icon-default.png?t=N7T8https://www.bilibili.com/video/BV1nj411D7tm

方案设计

        这里我按照 1*1 的范围将地图进行分块,每一块视为一整片草,进行整体剔除和计算。

        如上图的示例,将草分块之后,进行AOI剔除,最后得到所有可能在视野中的草(注意:这里没有进行视锥体剔除),之后再使用生成式算法得到最终的草数据(精确到每一株草的实体)。然后再直接将数据打包传入 GPU,使用之前提到过的 GPU 驱动的渲染上屏,完成草海渲染。

        这里就涉及到之前的一些实现过的架构了:

  • 需要得到地面的高度和法线,与 开放大世界的 GpuTerrain + RVT-CSDN博客 共用一张高度法线图。
  • 上屏方案 : GPU驱动的大规模静态物件渲染-CSDN博客

        除此之外,草海还需要一张密度图(表示每个格子的草的密度和类型),和 GpuTerrain 的高度法线图每个像素一一对应。

        有了上述数据之后,草海就能正常运转了。在项目前期,我们是将草海的生成式算法放到C#多线程中的,目的是为了方便调试和交互。后续功能稳定了,可以将这个算法移动到 ComputeShader 中,效率可以更高(这也是最终成型方案)。

框架与数据管理

        制作地图时,生成棋盘格,每个格子 1*1 米,每512 *512 个棋盘生成视为一个地块。统一棋盘格的尺寸,对应高度图、植被密度图的数据。

        一般来讲,对于视野远端的地块,不需要生成格子,也不需要计算。对于近处的地块,才需要生成草海,当然距离越近性能越好。按照一些文章的说法,80米的视野范围就能满足需求,如果加上视锥体剔除,视角设置为60度,那么算下来大概需要 3696 个格子参与生成计算(后面按照4000个格子计算)。

        4000 个格子,每个格子生成 64 棵草(密度最大),每颗草的数据(Transfrom数据)大约为 30 byte,算下来总共占用约 7.5 MB 内存,即便是移动端也可以接受。(为了减少对GPU的数据传输,我们其实使用了4个80*80的区域,内存占用更多,原因下文有解释)

草海系统的生命周期管理

        对于 Patch 而言,最高运算的部分在生成(以及根据玩法对数据的修改部分),因此在运行时并没有复杂逻辑,就只是在原地不动。生成之后最大的性能瓶颈就是在玩法(例如割草)上对实体的遍历。但因为能实现限制 Patch 进行刷新,所以遍历的量并不会很大。

草海编辑工具

        因为草海已经脱离了 Unity 的Terrain,所以需要一编辑工具。

  • 根据 GpuTerrain + RVT 数据直接还原地形的工具,方便美术开发。
  • 类似于 Terrain 的刷子工具,可以绘制草海密度图。
  • 草海类型配置:配置不同类型的草,以及其出现频率,可以实时预览。
  • 运行时调试工具,方便运行时查找问题。
草海密度图示例

        

其他细节问题        

        这里记录一些细节问题,可以帮助大家实现时做参考。

面片草还是网格草?

  • 面片草顶点数少,但是依赖 AlphaTest,这一步在很多移动设备上非常昂贵。
  • 网格草顶点数高,但因为是 实体渲染,性能表现远远优于 AlphaTest。

        此外,对于某些表现效果(例如高光、碰撞弯曲)上,面片制作起来困难;在视角上,面片草存在穿帮死角,大致上只适合固定视角。所以还是建议使用网格草。

草海密度图存的什么数据?

        草海密度图我这里将每个像素的 rgba 各设置为一种类型的草的密度,每一个草的密度取值从 0~256表示其密度。在生成草海数据时,查询到某个位置有颜色,则根据通道(例如 R通道 表示杂草,G表示花、B表示地衣、小石头)密度算出需要生成特定类型、特定数量的实体。生成完成之后,将数据收集起来统一传给 GPU。

        实际上,每一个通道的256的值对于密度还是太多了,本来一个地块最多64个实体,精度肯定超标了。后续如果要优化,完全可以将密度的精度降低到8,再将其他位记录其他地图数据。

生成式算法

        成式算法其实是根据项目相关,所以不必去网上特意查找。一般来讲,只需要设置一个随机方式(噪声图、或者固定随机种子),根据算法进行随机。只要满足一个要求就行:每一次生成的位置、旋转、缩放都是相同的结果。

        同时,在生成时可能需要根据地形信息有所变化,这点也需要考虑到。

草海实时重建的频率

        在计算哪些草块(Pitch)需要计算时,为了减少对 GPU 交互的频率,改为周围 80m 的棋盘格都计算了一起扔给 GPU。因此这样占用的内存大了4倍,但数据交互频率显著降低,就不用每帧都生成一次数据了。否则,一旦加上视锥体剔除,那么一旦相机旋转了,每帧都要实时计算一次、传值,数据大了还是很不划算的(实际上,视锥体剔除我们也试过,数据量少了很多,但传输数据的频率就大幅提升了)。

        当然这是妥协,如果在 GPU 里计算草海就没这个问题了。所以,最终的完整版本还是要在 ComputeShader 里生成草海。

图片数据读取

        GPU端直接通过 Texture.GetPixel 也太蠢了,效率还低。这里我们的做法是将图片转换成 NativeArray 然后再在多线程读取。这里需要注意的时,如果是多线程读取 NativeArray ,需要一点点操作:

NativeArray<Color32> HeightMap = texture.GetPixelData<Color32>(0);//获取图片的原始数据

//根据已有的数据生成不安全的只读 NativeArray,否则多线程无法使用。
NativeArray<Color32> ConvertedHeightMap= NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray<Color32>(HeightMap.GetUnsafeReadOnlyPtr(), HeightMap.Length, Allocator.Invalid);

#if ENABLE_UNITY_COLLECTIONS_CHECKS 
//只有编辑器下才存在 SetAtomicSafetyHandle 
NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref ConvertedHeightMap, AtomicSafetyHandle.Create());
#endif

        按照上图示例,就可以在多线程中使用 Unity 的 NativeArray 了。要注意的是,SetAtomicSafetyHandle 只在编辑器下使用,在真机上是会报错的。参考:NativeArrayUnsafeUtility seems to not work in builds - Unity Engine - Unity Discussions

割草烧草如何实现

        类似于塞尔达的割草、烧草效果,如果是在 CPU 端是比较好弄的。直接可以将技能(或者玩家交互)的计算结果记录下来,然后调用一次草海刷新,然后就能根据新的数据计算出结果,再传给 GPU 即可。

        如果是在 GPU 端实现,有一个简单的方案:从头顶照一个相机下来使其能覆盖所有的草。然后所有的技能一般都会有一些特效显示,这个相机就专门照这个特效。然后 GPU 直接就能读取到这个相机生成的图片,就可以直接拿来计算了,根本不用写 CPU 和 GPU 的交互,非常地方便。

模型上种草如何实现

        目前只实现了地形上种草,而模型上种草没有实现。

        模型上种草其实也有过设计,需要提前将模型进行烘培,且需要让美术指定模型的哪些地方是可以种草的(类似于刷 UV 图)。然后在渲染模型时,根据模型的草皮图、法线等直接生成草海,后续的步骤和地皮生成草海类似了。

参考文章

移动端草海的渲染方案(一)_terrain detail 交互-CSDN博客

移动端草海的渲染方案(二)_nature renderer-CSDN博客

移动端草海的渲染方案(三)-CSDN博客

移动端草海的渲染方案(四)_恶毒的狗 草海-CSDN博客

移动端草海的渲染方案(五)-CSDN博客

TA实践分享:材质与渲染——植物与风(Unity+UE)

【C#】并行编程实战:序章_并行编程实战基于c#8-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2071778.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

springboot嵌入式数据库实践-H2内嵌数据库(文件、内存)

本文章记录笔者的嵌入式数据库简单实现&#xff0c; 记录简要的配置过程。自用文章&#xff0c;仅作参考。 目录 本文章记录笔者的嵌入式数据库简单实现&#xff0c; 记录简要的配置过程。自用文章&#xff0c;仅作参考。 嵌入式数据库 -------------------------------具…

数学基础(八)

一、假设检验 什么是假设&#xff1a; 对总体参数&#xff08;均值、比例等&#xff09;的具体数值所作的陈述。 什么是假设检验&#xff1a; 先对总体的参数提出某种假设&#xff0c;然后利用样本的信息判断假设是否成立的过程 假设检验的应用&#xff1a; 推广新的教育…

【C++ Primer Plus习题】4.10

问题: 解答: #include <iostream> #include <array> using namespace std;int main() {array<float, 3> grade;float average0;for (int i 0; i < 3; i){cout << "请输入第" << i 1 << "次跑40米的成绩:";cin &…

『功能项目』新输入系统【06】

我们打开上一篇04禁止射线穿透行为项目&#xff0c; 本章要做的事情是在Unity编辑器中添加 新输入系统 实现主角在场景中鼠标右键可以使主角 转向。 本次项目需要让Unity引擎重新启动所以先保存当前项目 再次打开项目后&#xff0c; 修改为Both 点击Apply前注意要先保存项目&a…

Apollo9.0 PNC源码学习之Planning模块—— Lattice规划(五):横向运动轨迹规划

参考文章: (1)自动驾驶规划理论与实践 (2)Apollo6.0代码Lattice算法详解——Part5: 生成横纵向轨迹 0 前言 横向运动轨迹规划主要对车辆方向盘转向的控制策略;求解方法分为基于s的5次多项式和基于二次规划的方法 2 基于s的5次多项式的横向运动轨迹的生成 纵向运动轨迹…

Linux环境使用docker搭建Navidrome本地个人音乐库并实现远程访问

文章目录 前言1. 安装Docker2. Docker镜像源添加方法3. 创建并启动Navidrome容器 前言 本文和大家分享一款目前在G站有11KStar的开源跨平台音乐服务器Navidrome&#xff0c;如何在Linux环境本地使用Docker部署&#xff0c;并结合cpolar内网穿透工具配置公网地址&#xff0c;实…

Docker安装Logstash,并结合logback实现ELK日志收集

拉取镜像 docker pull docker.elastic.co/logstash/logstash:8.14.3创建文件夹 mkdir /mnt/data/logstash创建默认文件 先不做目录挂载&#xff0c;run出一个容器 docker run -d --rm -it docker.elastic.co/logstash/logstash:8.14.3将config和pipeline从容器cp到宿主机 …

BEV学习---LSS-1:论文原理及代码串讲

目前在自动驾驶领域&#xff0c;比较火的一类研究方向是基于采集到的环视图像信息&#xff0c;去构建BEV视角下的特征完成自动驾驶感知的相关任务。所以如何准确的完成从相机视角向BEV视角下的转变就变得由为重要。目前感觉比较主流的方法可以大体分为两种&#xff1a; 1、显式…

Linux驱动.之字符设备驱动框架,及手动,自动注册创建/dev下设备节点详解(一)

一、Linux 字符设备驱动框架 Linux一切皆文件&#xff0c;通过VFS虚拟文件系统&#xff0c;把所有外设的细节都隐藏起来&#xff0c;最后都以文件的形态呈现于应用层&#xff0c; 操作设备&#xff0c;就像对文件的打开、关闭、读写、控制。这种方式完美的统一了对用户的接口&a…

WIN/MAC 图像处理软件Adobe Photoshop PS2024软件下载安装

目录 一、软件概述 1.1 基本信息 1.2 主要功能 二、系统要求 2.1 Windows 系统要求 2.2 macOS 系统要求 三、下载 四、使用教程 4.1 基本界面介绍 4.2 常用工具使用 4.3 进阶操作 一、软件概述 1.1 基本信息 Adobe Photoshop&#xff08;简称PS&#xff09;是一款…

快手怎么免费的去掉视频水印?分享这三个工具给你

​ 我们经常会遇到想要保存的视频带有水印&#xff0c;这不仅影响美观&#xff0c;也不利于分享。为了解决这个问题&#xff0c;我将分享三个免费去除视频水印的工具&#xff0c;帮助你轻松去除水印&#xff0c;享受无干扰的视频体验。 工具一&#xff1a;奈斯水印助手(小程序…

挑战Infiniband, 爆改Ethernet(3)

Infiniband的特点 Infiniband在HPC集群和AI集群中获得广泛应用是和Infiniband技术的特点密切相关的&#xff0c;今天我们看看Infiniband的技术特点: 1&#xff09;网络分层模型 这个分层模型并不是Infiniband技术独有的&#xff0c;各种现代网络技术都普遍采用分层模型来设计…

在.NET开发中使用 Excel 的最佳方式之一:MiniExcel

前言 在桌面开发应用中&#xff0c;处理 Excel 文件是一个非常常见的需求。无论是生成报表、导入数据&#xff0c;还是与客户或其他系统进行数据交换&#xff0c;Excel 文件都扮演着重要角色。在 .NET 生态系统中&#xff0c;有许多处理 Excel 文件的工具和库&#xff0c;其中…

Flutter ListView 实现不同样式 item

我们在实际开发中会创建显示不同类型内容的列表。以下是使用 Flutter 创建此类结构的方法&#xff1a; 1. 创建包含不同类型项目的数据源。 2. 将数据源转换为小部件列表。 创建包含不同类型项目的数据源 项目类型 要表示列表中不同类型的项目&#xff0c;请为每种类型的项目…

链表(静态/动态创建,遍历,计数,查找,在节点的前/后方插入新节点,头插法,尾插法)

目录 一、前言 二、链表的静态创建和遍历 三、链表统计节点&#xff0c;查找节点是否存在 四、从指定节点的后方插入新节点 五、从指定节点的前方插入新节点 六、动态创建链表&尾插法 七、头插法 八、删除节点 一、前言 链表本质是一个结构体&#xff0c;结构体里…

19448 算法设计与分析(第五版)习题2-7 集合划分问题

### 思路 1. **递归公式**&#xff1a;根据提示信息&#xff0c;递归公式为&#xff1a; - \( f(n, x) f(n-1, x-1) f(n-1, x) \times x \) - 其中&#xff0c;\( f(n, x) \) 表示将 \( n \) 个元素分成 \( x \) 个非空子集的方案数。 2. **边界条件**&#xff1a; …

【STM32】串口(异步通信部分)

经典的串口接口硬件说实话在现在的电脑上已经很难见到了&#xff0c;而是被USB这种通用的串行接口替代了&#xff0c;哪怕外部设备要以串口连接到电脑&#xff0c;都需要进行各种硬件转换。但不得不说&#xff0c;在工业领域&#xff0c;串口还是一个非常常用的数据传输方式。 …

LEAP模型在能源环境发展、碳排放建模预测及分析中实践应用

采用部门分析法建立的LEAP&#xff08;Long Range Energy Alternatives Planning System/ Low emission analysis platform&#xff0c;长期能源可替代规划模型&#xff09;是一种自下而上的能源-环境核算工具&#xff0c;由斯德哥尔摩环境研究所和美国波士顿大学联合研发。该模…

后端Web之登录校验(上篇)

目录 1.概述 2.会话技术 3.JWT令牌 1.概述 基础的登录功能实际上就是查询数据库中有没有输入的用户和密码&#xff0c;有就放行&#xff0c;没有就返回错误信息&#xff0c;根据三层架构进行开发&#xff1a; controller层&#xff1a; service层&#xff1a; mapper层&…

Visual C++ 的免费绘图库 EasyX下载安装

EasyX Graphics Library 是针对 Visual C++ 的免费绘图库,支持 VC6.0 ~ VC2022,简单易用,学习成本极低,应用领域广泛。目前已有许多大学将 EasyX 应用在教学当中。 下载地址:EasyX Graphics Library for C++ 1、应用 2、文中有很多的C++应用案例 3、编程需要的数学知识 …