Unity大面积草地渲染——4、对大面积草地进行区域剔除和显示等级设置

news2024/12/25 9:03:26

目录
1、Shader控制一棵草的渲染
2、草地的动态交互
3、使用GPUInstancing渲染大面积的草
4、对大面积草地进行区域剔除和显示等级设置

Unity使用GPU Instancing制作大面积草地效果

大家好,我是阿赵。
这里开始讲大面积草地渲染的第四个部分,对大面积草地进行区域剔除和显示等级设置。
在上一篇文章里面,我使用了GPU Instancing来渲染草,渲染的合并是比较的成功,但如果草地的面积太大,会导致同屏渲染100多万的面。这个数量级比较高,对显卡有一定的要求。所以这一篇文章来想办法解决这个问题。

一、一个区域内的草的多种等级渲染

我这里在一个5X5的范围内,分别生成了不同数量的草:
等级1,总共有1000棵草
在这里插入图片描述

等级2,总共有500棵草
在这里插入图片描述

等级3,有100棵草
在这里插入图片描述

这三个等级,有点类似于LOD的概念,我打算在不同的距离观察这个5X5区域时,会显示不同等级的草。当然,如果有需要,继续增加等级,比如等级4 、5之类。

二、九宫等级显示

刚才我们已经有了三个等级的草,我现在先忽略了地形的区别,假设有一片无限大的草地,都是平的。然后我从顶视图把这个草地划分为每5X5为一格。然后不同深度的格子,是不同显示等级的草。纯绿色的是1级,然后颜色渐渐变浅等级就越低。
假设中间红色的小球是一个人,他走到了这个格子的时候,如果按照标准的九宫格来显示草的疏密等级,就有以下这个图:
在这里插入图片描述
直观的显示成刚才的3种等级的草,会是这样的:
在这里插入图片描述

但这个九宫的设计会有一个问题,当角色走到格子边缘的时候,会看到明显的接缝,然后跨越格子的时候,会明显的看到草地的疏密变化,效果不是很好:
在这里插入图片描述

于是,我在这个基础上,把最里面的等级1,增加多一圈,变成了下图这样:
在这里插入图片描述

这个情况下,当人走到一个格子的边缘时,人周围一圈的格子草地都保证不会发生疏密变化,只有在更远一圈的地方才会发生变化。
在这里插入图片描述

从顶视图看的效果是这样的:

开放世界大地图草地算法

三、草地LOD信息的存储

由于我们的草是用同一个网格模型渲染出来的,所以原则上我们只需要记录同一个区域内,每一颗草的位置就行了。位置有xyz三个信息,我这里是使用了图片的格式加一个配置文件来存储。比如下面这个区域的草地信息,我保存如下:
在这里插入图片描述
在这里插入图片描述

从配置文件看,这是一个5X5区域的草地,总共有250棵草,所有草的坐标的最小XYZ值,还有从最小值到最大值的偏移值,都记录下来了。
然后每棵草的坐标,其实就是图片里面的rgb颜色。
这里有250棵草,一张16X16的贴图,就有256个像素,就已经够存储了。
具体的算法是,每个坐标减去最小值再除以偏移值,就是它的颜色值。还原的时候同样的算法。

接下来思考几个扩展问题:
1、加入一个山坡有不同的高度变化,不再是一片平底,该怎样处理呢?这里有3个做法可以作为参考:

1.每一片5X5的区域生成一个贴图和配置信息,配置信息里面加上这块5X5区域的中心点坐标
2.还是用同一片5X5区域信息,在首次生成某个5X5区域的草地时,使用碰撞的方式获取一下当前草地的高度,并存起来,作为生成单棵草时的高度。
3.还是用同一片5X5区域信息,给山坡的大区域生成一个高度图,然后当需要生成某个坐标的草时,通过高度图来获取草的实际高度。 反正做法有很多。

2、假如我希望显示的草的旋转和缩放有不一样,该怎么办呢?

其实非常简单,还是用rgb把它们存储起来就行了,根据需要,同一个等级的图片增加一张单独旋转的和一张缩放的就行。

3、假如我希望显示的草不止一种,而是有很多种,该怎么办?

注意我们刚才使用了图片的rgb而已,还有alpha没有用。所以如果我们用上的话,0-255的alpha值保存在图片的每个像素上,我们最多可以支持256种草,按道理怎么都够用了吧?

刚才的例子,我生成了4个级别的LOD草信息,总共是这么多文件,容量加起来只有5k,就能渲染无限大面积的草地了:
在这里插入图片描述

值得注意的是,读取这个图片,我们有可能会发现读取出来的颜色值和实际保存的值不一样。
如果是直接放在Unity内部的图片,要记得取消所有压缩设置
在这里插入图片描述

四、使用API渲染策略

上面我们已经有了数据了,那么我们怎样才能实现LOD渲染呢?是不是应该把草都摆在场景里面,然后使用Unity的LOD Group呢?
这里我的做法是这样的:
1、先获取角色当前的坐标,如果我们是以5X5做为一格,那么算出当前角色所在的5X5区域的横竖Index
2、通过区域的坐标,算出当前5X5区域的中心点,根据实际需要显示的圈数,通过遍历,找到相邻多圈的其他5X5区域
3、计算每个区域应该显示的LOD等级,然后获取每个区域的坐标矩阵
4、如果想中间的区域显示多少圈等级1的草,可以再加多一个参数控制
5、得到所有需要显示的区域的坐标矩阵之后,按照列表长度不超过1023,重新把它们存放到一个或者多个矩阵数组里面。
6、通过API渲染:Graphics.DrawMeshInstanced(mesh, 0, mat, matrixs, matrixs.Length);
从上面的算法看,好像有很复杂的计算,其实并没有。因为当第1步计算当前角色所在的区域Index时,可以和上一次计算的值做对比,如果没有发生变化,证明角色并没有跨区域,所以2-5步都可以省略掉,直接执行第6步就可以了。

然后我看了一些网上介绍大面积草地做法的文章,他们比我做得更精细,还通过各种算法,去剔除摄像机背面的草,剔除被物体挡住的草,等等。我并没有这么做。因为我觉得,现在这一套策略,在GPU不是太差的情况下,真正的瓶颈是在CPU的计算上,而那些剔除算法,基本上都是需要额外增加CPU的计算的,而且还是每一帧都需要计算。我现在的CPU压力只会在角色跨过一个5X5区域时,稍微有一次计算,对比起来,其实是省了很多计算的。
如果真的担心GPU承受不了,我们可以通过游戏内提供显示质量等级让玩家来选择。

五、不同质量等级的显示控制

留意看刚才的渲染策略,可以发现,我留了2个参数控制草地显示的范围:
1.实际显示的圈数
2.中间显示多少圈等级1
我再加多一个参数,
3.最高等级显示到多少级
通过这三个参数的组合,我们可以组合出很多种显示质量等级了,比如我这个例子里面设置了高中低三个等级:
在这里插入图片描述

最高等级,有300多万面需要渲染,不过效果很好,一望无际,移动的过程中也完全看不出草地的接缝变化。
在这里插入图片描述

中等等级,有一百多万面需要显示,稍微可以看出远处有草的疏密变化
在这里插入图片描述

低等级,有30万面,草看起来比较稀疏,在移动过程中疏密变化比较明显。

这个demo我发到手机和模拟器上面跑过,就算调到最高显示质量,实际上都是60帧满帧的,所以看着好像很可怕的几百万面,在使用了GPU Instancing合并渲染之后,其实效率还是比较高的。如果实在是害怕有手机跑不动,其实还可以进一步的调整草的模型面数,我现在这一束草的面数有一百多面,其实也偏高了一些。

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

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

相关文章

零知识证明:安全定义

之前在本科的课程仅仅略微介绍了下零知识证明,之后自学了一些相关内容,但不成体系。本学期跟着邓老师较为系统地学习了 ZKP,发现自己之前有很多的误解,临近期末整理下重要内容。 参考文献: Goldreich O. Foundations…

C语言实现个人通讯录(功能优化)

实战项目---通讯录(功能优化) 1.基本思路介绍:1.1基本思路: 2.通讯录的具体实现:2.1 通讯录的建立:2.2通讯录功能: 3.具体功能函数的实现:3.1 增添联系人:3.2 删除联系人…

从零开始学习JVM--初识Java虚拟机

1 虚拟机与Java虚拟机 1.1 基本介绍 所谓虚拟机(Virtual Machine)。就是一台虚拟的计算机。它是一款软件,用来执行一系列虚拟计算机指令。大体上,虚拟机可以分为系统虚拟机和程序虚拟机。 系统虚拟机:完全对物理计算…

树莓派(主)与STM32(从)使用SPI通信(持续更新中)

1.实验目的 使用树莓派作为主机向 STM32 从机发送数据,STM32 收到数据后通过串口的方式将数据打印到电脑上,同时返回给树莓派数据。树莓派接收到数据后打印在控制台上。 2.SPI 简介 SPI(Serial Peripheral Interface,串行外设接…

进程控制下(程序替换部分)

目录: 1. 进程程序替换的原理 2.将磁盘的数据和代码加载进物理内存 3.程序替换函数的基本使用 ----------------------------------------------------------------------------------------------------------------------------- 1. 进程程序替换的原理 蓝色框内…

图解LeetCode——48. 旋转图像

一、题目 给定一个 n n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。 你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。 二、示例 2.1> 示例 1: 【输入】matrix [[1,2,3],[…

AVL树的实现

文章目录 AVL树前言1. AVL树的概念2. AVL树的结构2.1 AVL树节点的定义2.2 AVL树的结构 3. AVL树的操作3.1 AVL树的插入3.2 AVL树的旋转(重要)3.2.1 左单旋过程代码 3.2.2 右单旋过程代码 3.2.3 左右双旋过程代码 3.2.4 右左双旋过程代码 旋转整体代码 3.3 AVL树的验证3.4 AVL树…

Day967.团队拓扑学 -遗留系统现代化实战

团队拓扑学 Hi,我是阿昌,今天学习记录的是关于团队拓扑学的内容。 看看最近这几年来新诞生的组织结构模型——团队拓扑学(Team Topologies)。 一、团队拓扑 尽管组件团队、特性团队和 Spotify 模型,都为团队的组成提…

JavaScript实现输入年份判断是否为闰年的代码

以下为实现输入年份判断是否为闰年的程序代码和运行截图 目录 前言 一、输入年份判断是否为闰年 1.1 运行流程及思想 1.2 代码段 1.3 JavaScript语句代码 1.4 运行截图 前言 1.若有选择,您可以在目录里进行快速查找; 2.本博文代码可以根据题目要…

阿里云 aliplayer 加密的视频 key解密解密下载过程实现

第一步:打开开发者工具 打开需要下载的视频链接,按F12打开开发者工具,然后强制刷新(ctrlf5) 第二步:定位key加密 内存搜索,关键词:_sce_dlgtqred 进入第二个结果:https…

Map在循环中修改自己的key与value

Map在循环中修改自己的key与value 1.解决方案2.深入了解 1.解决方案 使用ConcurrentHashMap package com.company.newtest;import java.util.*; import java.util.concurrent.ConcurrentHashMap;public class test30 {public static void main(String[] args) {Map<String…

【Linux】进程信号详解(一)信号概念信号产生

文章目录 前言信号概念信号入门1.查看所有信号2.信号处理常见方式3. 发送信号过程信号是谁发送的&#xff1f; 信号产生介绍signal函数来捕捉进程1.通过键盘产生例子&#xff1a;Core Dump核心转储 2.程序出现异常&#xff0c;导致收到信号空指针异常浮点数异常 3. 调用系统函数…

1_1torch基础知识

1、torch安装 pytorch cuda版本下载地址&#xff1a;https://download.pytorch.org/whl/torch_stable.html 其中先看官网安装torch需要的cuda版本&#xff0c;之后安装cuda版本&#xff0c;之后采用pip 下载对应的torch的gpu版本whl来进行安装。使用pip安装时如果是conda需要切…

【Linux】安装部署elasticsearch

安装 Java 在安装 Elasticsearch 之前&#xff0c;您需安装并配置好 JDK, 设置好环境变量 $JAVA_HOME。 众所周知&#xff0c;Elasticsearch 版本很多&#xff0c;不同的版本对 Java 的依赖也有所差别: Elasticsearch 5 需要 Java 8 以上版本&#xff1b;Elasticsearch 6.5 开…

旋转目标检测【1】如何设计深度学习模型

前言 平常的目标检测是平行的矩形框&#xff0c;“方方正正”的&#xff1b;但对于一些特殊场景&#xff08;遥感&#xff09;&#xff0c;需要倾斜的框&#xff0c;才能更好贴近物体&#xff0c;旋转目标检测来啦~ 一、如何定义旋转框 常见的水平框参数表达方式为&#xff0…

PMP项目管理-[第九章]资源管理

资源管理知识体系&#xff1a; 规划资源管理&#xff1a; 估算活动资源&#xff1a; 获取资源&#xff1a; 建设团队&#xff1a; 管理团队&#xff1a; 9.1 规划资源管理 定义&#xff1a;定义如何估算、获取、管理和利用团队以及实物资源的过程 作用&#xff1a;根据项目类型…

Azure Data Lake Storage Gen2 简介

Azure Data Lake Storage Gen2 基于 Azure Blob 存储构建&#xff0c;是一套用于大数据分析的功能。 Azure Data Lake Storage Gen1 和 Azure Blob Storage 的功能在 Data Lake Storage Gen2 中组合在一起。例如&#xff0c;Data Lake Storage Gen2 提供规模、文件级安全性和文…

Cesium入门之三:隐藏Cesium初始化页面小部件的两种方法

上一级我们实现了第一个三维地球&#xff0c;但是在这个页面上有很多小部件&#xff0c;我们不想让其显示&#xff0c;应该如何设置呢&#xff1f;这一节我们通过两种方式来隐藏小部件 方法1&#xff1a;通过js代码实现 在js代码中&#xff0c;通过在new Cesium.Viewer(conta…

算法之路--直接插入排序算法

在介绍插入排序算法之前&#xff0c;先举证一个我们都熟悉不过的例子即可理解插入排序。我们在打牌的时候&#xff0c;由于每次抽到的牌大小不一&#xff0c;为了在出牌时了解自己手里都还剩什么牌型&#xff0c;所以每次对抽到的新牌都会做一个排序&#xff0c;怎么比较呢&…

AWS 中的另外一种远程工具 AWS Session Manager

作者&#xff1a;SRE运维博客 博客地址&#xff1a;https://www.cnsre.cn/ 文章地址&#xff1a;https://www.cnsre.cn/posts/230129126154/ 相关话题&#xff1a;https://www.cnsre.cn/tags/aws/ 背景需求 因为项目的安全性。为了避免项目的服务器暴露在公网中。很多时候我们…