UE引擎 LandscapeGrass 实现机制分析(UE5.2)

前言

随着电脑和手机硬件性能越来越高,游戏越来越追求大世界,而大世界非常核心的一环是植被,目前UE5引擎提供给植被生成的主流两种方式为 手刷植被LandscapeGrass(WeightMap程序化植被)。当然UE5.3推出新一代PCGFramework 节点程序化生成框架,也可以用于植被生成。(本文暂不涉及到PCGFramework), 主要分析LandscapeGrass方案

手刷植被

手刷植被是比较传统的植被生成方式,基本各种引擎都会提供植被编辑器让美术人力刷植被,这里倒是没什么好分析的。UE5提供了手刷植被模式FoliageMode, 工具比较齐全,比较易用,能让场景美术高效率手工刷植被。FoliageMode生成的植被是用HISM组件管理,不明白的可以看看我的另外一篇博客(UE4 4.27) UHierarchicalInstancedStaticMesh(HISM)原理分析

LandscapeGrass(WeightMap程序化植被)

背景

weightmap程序化植被, 顾名思义: 由地形weightmap程序化生成的植被。首先地形WeightMap的概念,说白了就是地形材质混合的权重图,不懂的可以看下UE地形系统材质混合实现和Shader生成分析(UE5 5.2)。场景美术在地形上频繁刷了各种材质,比如草原或者沙漠,然后需要再相应的地貌上种植相应植被,比如草原种绿草,沙漠种仙人掌,因为地形的材质层是频繁改动,每次刷完草或者沙漠后,又得用FoliageMode 在相应地貌刷植被,两重工作量,而且容易遗忘,这时候就非常需要一种工具:  在相应的WeightMap上程序化铺满一种或许多种植被,每次刷完WeightMap后地形可以自动生成。UE引擎 就有这样一套方案,叫LandscapeGrass

LandscapeGrass使用简介

配置LandscapeGrassType

材质Grass采样层配置

显示结果

LandscapeGrass生成分析

LandscapeGrass UML图

LandscapeGrass执行流程图

这里重点介绍RenderGrassMap,GrassInstancedStaticMeshComponent, FAsyncGrassTask.

这里的三个过程都是逐组件的,针对单独一个Landscapecomponent进行

RenderGrassMap(Per LandscapeComponent)

GrassMap本质就是一张图集(TextureAltas)

这里是将LandscapeComponent的HeightMap和Grass用到的所有WeightMap(也就是上面的L2,L3,L4,L5)合并到一张图集里,格式为PF_B8G8R8A8,也就是所谓的RenderGrassMap。

假设一个Landscapecomponent 分辨率为128,一张HeightMap占16位,一张WeightMap占8位, 由于上面使用了L2,L3,L4,L5四个草权重层,则 (2 + 4)/ 4 = 1.5, 得使用两张128 * 128,合起来(128 * 2)* 128 = 256 * 128,这就是RenderGrassMap图集。

GrassMap创建

Render GrassMap

通过DrawLandscapeComponentMesh,设置Ortho正交相机, 进行多次RenderPass, 将HeightMap和WeightMap写入到GrassMap图集里。一次RenderPass写入4个8位通道,6个8位通道就是需要两次RenderPass. 

核心代码:

FLandscapeGrassWeightVS,FLandscapeGrassWeightPS, FLandscapeGrassWeightMeshProcessor等文件

grass.CaptureNextGrassUpdate 1 可以对RenderGrassMap进行Renderdoc抓帧

GrassMap fetch成cpu数据

上一步生成了GrassMap 图集,里面存储了LandscapeComponent地块的HeightMap数据和所有的Grass相关的WeightMap数据。最终直接对GrassMap进行CPU ReadBack,读取数据出来,合并到FLandscapeComponentGrassData的 TArray<uint8> HeightWeightData里。HeightWeightData按顺序分段存储了高度数据和所有的Grass各层权重数据。

为什么需要Render GrassMap

回过头来看RenderGrassMap存在的意义是因为UE引擎地形的各个LandscapeComponent共用了HeightMap和WeightMap, RenderGrassMap就是把每个组件的HeightData和GrassWeightData从公用纹理抽离出来,存到LandscapeComponent里,方便每个LandscapeComponent生成自己的GrassInstancedStaticMeshComponent.

GrassInstancedStaticMeshComponent

GrassInstancedStaticMeshComponent继承于HISM组件,两者基本没什么区别。这里需要强调的是一个GSMC组件针对一个LandcapeComponent的LandscapeGrassType的GrassVariety来创建的。

FAsyncGrassTask(随机撒点和HISM构建)

LandscapeComponent已经获取高度和权重数据,下面就是进行随机撒点。FAsyncGrassTask

随机撒点

撒点密度由LandscapeComponent地块大小和GrassVariety的密度决定

FAsyncGrassBuilder封装了随机撒点的核心算法, 目前一共提供了两种随机撒点算法: JitterGrid和 Halto序列

勾选了UseGrid就是使用了JitterGrid随机撒点,反之使用Halto随机撒点。

JitterGrid

JitterGrid也就是根据密度把整个地形块均分切成多个块,每个块内随机生成一个二维点,并且加上一定的旋转和位置偏移,最终得到一个随机点。具体算法参考我之前一篇博客: 程序化物件放置(procedural placement)之泊松硬盘采样(poisson disk sampling)

一个随机点虽然生成出来了,但是是否存活得满足一定条件:

可以看出当权重为0,百分百不通过。权重为1时,通过率是百分百,如果权重为其它,那就看随机的运气了。

Halto序列

Halto随机数生成参考 应用halton序列生成均匀散点图

Halto序列生成的随机点存活条件判断和JitterGrid是一样的。比较注意的是,JitterGrid和Halto序列生成的随机点都是二维的,都需要进行一次SampleHeight来得到高度位置Z,Sample方法是 Bilinear interpolates。

撒完点后最终进行HISM构建。

FoliageModeLandscapeGrass的区别

未完待续

参考文章

[1] UE地形系统材质混合实现和Shader生成分析(UE5 5.2)

[2] (UE4 4.27) UHierarchicalInstancedStaticMesh(HISM)原理分析

[3] 应用halton序列生成均匀散点图

[4] 源码文件:LandscapeGrass.cpp

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Halcon reduce_domain和scale_image的作用

在Halcon中&#xff0c;reduce_domain是用于缩小图像域&#xff08;Image Domain&#xff09;的操作。 它的作用是通过指定一个感兴趣区域&#xff08;ROI&#xff0c;Region of Interest&#xff09;&#xff0c;将图像数据限制在该区域内&#xff0c;从而实现对图像进行裁剪…

领导力的3个常见误区,你可能中了其中之一

什么是领导力&#xff1f; 领导力是组织和团队成功的关键。在一个不断变化的商业环境中&#xff0c;理解领导力的本质至关重要。这篇文章将揭示有关领导力的三个常见误解&#xff0c;帮助读者更清晰地认识领导者的角色。 关于领导力的常见误解 人们对领导力的理解经常受到错…

如何使用bash写脚本

本章主要介绍如何使用bash写脚本。 了解通配符了解变量了解返回值和数值运算数值的对比判断语句循环语句 grep的用法是“grep 关键字 file”&#xff0c;意思是从file中过滤出含有关键字的行。 例如&#xff0c;grep root /var/log/messages&#xff0c;意思是从/var/log/me…

在做题中学习(33):只出现一次的数字 II

137. 只出现一次的数字 II - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 1.首先想到出现三次的数&#xff0c;它们仨的任意一位都是相同的&#xff08;1/0&#xff09; 2.可以发现出现三次的数的某一位和a某一位在所有情况下%3最后的结果都和a的那一位相同&…

【PyTorch】卷积神经网络

文章目录 1. 理论介绍1.1. 从全连接层到卷积层1.1.1. 背景1.1.2. 从全连接层推导出卷积层 1.2. 卷积层1.2.1. 图像卷积1.2.2. 填充和步幅1.2.3. 多通道 1.3. 池化层&#xff08;又称汇聚层&#xff09;1.3.1. 背景1.3.2. 池化运算1.3.3. 填充和步幅1.3.4. 多通道 1.4. 卷积神经…

抖店商品卡流量怎么做?附实操玩法解析及案例分享!

我是电商珠珠 在抖店中&#xff0c;我们会看到一些店铺从来都不直播&#xff0c;官方账号的作品很少&#xff0c;但是他的店铺GMV依旧过万。 其实这就是抖音的货架电商所带来的优势&#xff0c;抖音现在主要由两部分组成&#xff0c;一部分是内容场&#xff0c;就是咱们平时刷…

SpringBoot整合MongoDB详解

SpringBoot——整合MongoDB详解 注意&#xff1a; MongoDB默认是本机访问 需要开启远程访问 window修改如下 linux 修改如下 /usr/local/mongodb4/mongodb.conf 详细内容 dbpath/data/mongodb4/mongo #数据文件保存地址 logpath/data/mongodb4/log/mongod.log #日志保存地址…

架构设计系列之基础:初探软件架构设计

11 月开始突发奇想&#xff0c;想把自己在公司内部做的技术培训、平时的技术总结等等的内容分享出来&#xff0c;于是就开通了一个 Wechat 订阅号&#xff08;灸哥漫谈&#xff09;&#xff0c;开始同步发送内容。 今天&#xff08;12 月 10 日&#xff09;也同步在 CSDN 上开通…

mysql字段设计规范:使用unsigned(无符号的)存储非负值

如果一个字段存储的是数值&#xff0c;并且是非负数&#xff0c;要设置为unsigned&#xff08;无符号的&#xff09;。 例如&#xff1a; 备注&#xff1a;对于类型是 FLOAT、 DOUBLE和 DECIMAL的&#xff0c;UNSIGNED属性已经废弃了&#xff0c;可能在mysql的未来某个版本去…

AI隆重软件,AI原创文章隆重软件

随着信息量的急剧增加&#xff0c;许多写作者、网站管理员和内容创作者们纷纷感受到了文章降重的压力。原始文本的降重&#xff0c;需要保留关键信息的同时避免重复&#xff0c;这是一项既繁琐又耗时的任务。 改写软件的批量降重功能 147SEO改写软件在降重领域的卓越表现主要体…

常见SSL证书都有哪些格式

常见Web服务软件 常见的Web服务软件&#xff0c;通常都基于OpenSSL和Java两种基础密码库。 Tomcat、Weblogic、JBoss等Web服务软件&#xff0c;一般使用Java提供的密码库。通过Java Development Kit&#xff08;JDK&#xff09;工具包中的Keytool工具&#xff0c;生成Java Ke…

android studio 按键点击事件的实现方法

一、onClick属性&#xff1a; 1&#xff09;、在activity_main.xml中设置button的onClick属性&#xff1a; <Buttonandroid:id"id/button"android:layout_width"wrap_content"android:layout_height"wrap_content"android:text"开灯&q…

SpringCloud系列(三)| 集成Nacos注册中心

好了万事具备&#xff0c;接下来我们就开始搭建我们SpringCloud项目。本章节我们先来搭建我们SpringCloud项目框架&#xff0c;然后开发两个服务&#xff0c;把他们注册到Nacos注册中心中。上一章节我们已经介绍了Nacos是可以作为注册中心和配置中心的&#xff0c;这一章节我们…

Linux centos8安装JDK1.8、tomcat

一、安装jdk 1.如果之前安装过jdk&#xff0c;先卸载掉旧的 rpm -qa | grep -i jdk 2.检查yum中有没有java1.8的包 yum list java-1.8* 3.yum安装jdk yum install java-1.8.0-openjdk* -y 4.验证 二、安装tomcat Index of /tomcat 可以在这里选择你想要安装的tomcat版本…

【unity实战】一个通用的FPS枪支不同武器射击控制脚本

文章目录 前言模型素材文章用到的粒子火光特效射击效果换弹瞄准开枪抖动效果设置显示文本最终代码不同武器射击效果1. 手枪2. 机枪3. 狙击枪4. 霰弹枪5. 加特林 其他感谢完结 前言 实现FPS枪支不同武器效果&#xff0c;比如手枪&#xff0c;喷子&#xff0c;狙击枪&#xff0c…

ISCTF2023 Reverse方向 WP

文章目录 ReversecrackmeEasyRebabyReeasy_z3FloweyRSAeasy_flower_teamfx_rez3_revengeWHERE Reverse crackme 、 加了UPX壳&#xff0c;可以看到EP Section处UPX标识被修改了 用WinHex修改 之后UPX脱壳 得到flag。 EasyRe 逆向一下&#xff0c;先逆序&#xff0c;再做一些…

机器人行业数据闭环实践:从对象存储到 JuiceFS

JuiceFS 社区聚集了来自各行各业的前沿科技用户。本次分享的案例来源于刻行&#xff0c;一家商用服务机器人领域科技企业。 商用服务机器人指的是我们日常生活中常见的清洁机器人、送餐机器人、仓库机器人等。刻行采用 JuiceFS 来弥补对象存储性能不足等问题。 值得一提的是&am…

godot 报错Unable to initialize Vulkan video driver解决

版本 godot 4.2.1 现象 godot4.2.1 默认使用vulkan驱动&#xff0c;如果再不支持vulkan驱动的主机上&#xff0c;进入引擎编辑器将报错如下 解决 启动参数添加 –rendering-driver opengl3 即可进入引擎编辑器 此时运行项目仍然会报错无法初始化驱动 在项目设置中配置编…

编译Sqlite3记录

下载源文件&#xff1a; 下载地址&#xff1a;SQLite Download Page 打开QtCreator创建新的工程&#xff0c;选择纯C工程&#xff0c;将main.c删除&#xff0c;将下载的源码解压后的文件复制到并添加到工程中&#xff0c;其中的文件包括&#xff1a;sqlite3ext.h、sqlite3.h、…

Android多进程和跨进程通讯方式

前言 我们经常开发过程中经常会听到线程和进程&#xff0c;在讲述Android进程多进程前我打算先简单梳理一下这俩者。 了解什么是进程与线程 进程&#xff1a; 系统中正在运行的一个应用程序&#xff0c;某个程序一旦运行就是一个进程&#xff0c;是资源分配的最小单位&#…