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

前言

随着电脑和手机硬件性能越来越高,游戏越来越追求大世界,而大世界非常核心的一环是地形系统,地形系统两大构成因素:高度和多材质混合,此篇文章介绍下UE4/UE5 地形的材质混合方案----基于WeightMap混合。

材质层

地形着色的基础组成,比如雪, 沙漠,岩石,绿地等等。在UE5创建材质层是材质的节点LandscapeLayerBlend节点中创建

LandscapeLayerBlend节点每个输入上游就是一个材质基础层

这里我用简单的例子,假定材质基础层都是一个float3常量颜色,比如float3(1.0, 0.2, 0.1)。

WeightMap

各个材质基础层按照一定权重混合得到最终的效果,

WeightMap就是材质权重图,里面存储了各个基础层材质混合的权重值。在UE5里,WeightMap的格式是RGBA8,可以存储四层材质层的权重值,精度为0 - 255 (对应 0.0 - 1.0的精度)。

WeightMap数量和通道使用

从之前我UE地形系列文章,我们知道UE地形是由一个个地形块(LandscapeComponent)组成,一个LandscapeComponent可以存在多个WeightMap, 假设存在N个WeightMap.

那么最终地块的基础材质层总数:4 * (N - 1) < MaterialLayerNum <= 4 *N.

这里之所以用“<=” 和 “>”, 而不是“= 4 * N”,是因为一张WeightMap不一定会用完所有通道。比如当前地形块刷了5种材质基础层,则该地形块就存在两张WeightMap, 第一张WeightMap RGBA都用来存储四种材质基础层的权重,第二张WeightMap的R通道用来存储第五种材质基础层的权重,剩余的GBA通道都是零权重。

材质基础层用了哪张WeightMap的哪个通道是记录在ULandscapeComponent里

WeightMap存储权重总和

不管地形块刷了多少层材质基础层,最终地形某个点的各层权重总和为1.0(255).比如说上面的地形刷了五层材质基础层,有两张WeightMap,分别为W1和W2, W1[n][n].R 代表访问W1权重图的N行N列的像素R通道值。

则存在公式:

W1[n][n].R +  W1[n][n].G + W1[n][n].B +  W1[n][n].A + W2[n][n].R  = 255(byte)

                         (注意:W2[n][n].G = W2[n][n].B = W2[n][n].A = 0)

UE5地形权重混合的HLSL代码分析

生成的具体HLSL代码

以上面的5层材质的为案例, 抓帧得到的HLSL代码(位于Material.ush文件)

大致能看到采样了WeightMap1和WeightMap2, 然后大致能看到颜色混合了5次。

为更清楚的表示, 手写HLSL代码表示,大致如下:


float4 Weigh1 = Texture2DSample(WeightMap1, UV);
float4 Weigh2 = Texture2DSample(WeightMap2, UV);
float4 Layer1Mask = float(1.0, 0.0, 0.0, 0.0);
float4 Layer2Mask = float(0.0, 1.0, 0.0, 0.0);
float4 Layer3Mask = float(1.0, 0.0, 1.0, 0.0);
float4 Layer5Mask = float(0.0, 0.0, 0.0, 1.0);
float4 Layer6Mask = float(1.0, 0.0, 0.0, 0.0);

float3 L1 = float3(0.78437978,0.95937508,0.50223249);
float3 L2 = float3(0.98749989,0.06583356,0.17528065);
float3 L3 = float3(0.45752281,0.53502721,0.88749981);
float4 L5 = float3(0.22312574,0.97916698,0.28475177);
float4 L6 = float3(0.88749981,0.25128645,0.26541224);


float3 BaseColor = float3(0.0, 0.0, 0.0);

// five layer blend
BaseColor += dot(Layer1Mask, Weigh1) * L1;
BaseColor += dot(Layer2Mask, Weigh1) * L2;
BaseColor += dot(Layer3Mask, Weigh1) * L3;
BaseColor += dot(Layer5Mask, Weigh1) * L5;
BaseColor += dot(Layer6Mask, Weigh2) * L6;

这里dot(float4(1, 0, 0,0),A),其实就是取A的R通道, 其他类似道理。

地形材质Shader代码编译流程

上面可以更清楚整个材质权重混合的流程. 代码是动态生成的,和地块现在使用到的实际材质基础层数量相关,所以在刷UE地形的时候,刷一种未出现的新材质会引起材质编译

编译生成流程的最终在UMaterialExpressionLandscapeLayerBlend::Compile编译Shader代码,

这里判断是否需要编译发生在ULandscapeComponent::GetCombinationMaterial

首先ULandscapeComponent的所属ALandscapeProxy里存在一个 MaterialInstanceConstantMap 材质实例管理表

这个表会缓存出现过的各种地形材质实例,MaterialInstanceConstantMap的key代表使用了哪些材质基础,并且哪个基础材质使用了哪张权重纹理,如下红圈所示:

代表了LandscapeMaterialInstanceConstant_10材质实例是在 L1. L3, L3,L7使用WeightMap0, L6使用了WeightMap0的情况下编译出来的。

如果在MaterialInstanceConstantMap找到同个Key的,就使用已有的MaterialInstance, 如果找不到就以ALandscape的母材质为基础创建新的材质实例,并且设TerrainLayerWeightParameters材质静态编译信息, 触发编译。

上面WeightMap%d和LayerMask_%s 指在Shader代码中生成了每个Layer对应的权重图和纹理通道遮罩索引,在上面的HLSL实现地形材质混合的简化代码大致相符合。

当然最终这个材质实例是保存到ULandscapeComponent的MaterialInstances,被UPROPERTY序列化下来。

当然最终材质编译完后,得更新地形的材质实例参数值: WeightMap和LayerMask遮罩

参考资料

UE5.2的地形系统实现

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

总结:利用JDK原生命令,制作可执行jar包与依赖jar包

总结&#xff1a;利用JDK原生命令&#xff0c;制作可执行jar包与依赖jar包 一什么是jar包&#xff1f;二制作jar包的工具&#xff1a;JDK原生自带的jar命令&#xff08;1&#xff09;jar命令注意事项&#xff1a;&#xff08;2&#xff09;jar包清单文件创建示例&#xff1a;&a…

Yolo自制detect训练

Install 把代码拉下来 GitHub - ultralytics/yolov5 at v5.0 然后 pip install -r requirements.txt 安装完了,运行一下detect.py即可 结果会保存在对应的目录下 Intro ├── data:主要是存放一些超参数的配置文件(这些文件(yaml文件)是用来配置训练集和测试集还有验…

【Redis】set 集合

上一篇&#xff1a;list 列表 https://blog.csdn.net/m0_67930426/article/details/134364315?spm1001.2014.3001.5501 目录 Sadd Smembers Sismember Scard Srem ​编辑Srandomember Spop Smove 集合类 Sdiff Sinter Sunion 官网 https://redis.io/commands/?…

01-Spring中的工厂模式

工厂模式 工厂模式的三种形态: 工厂模式是解决对象创建问题的属于创建型设计模式,Spring框架底层使用了大量的工厂模式 第一种&#xff1a;简单工厂模式是工厂方法模式的一种特殊实现,简单工厂模式又叫静态工厂方法模式不属于23种设计模式之一第二种&#xff1a;工厂方法模式…

记录一次某某虚拟机的逆向

导语 学了一段时间的XPosed&#xff0c;发现XPosed真的好强&#xff0c;只要技术强&#xff0c;什么操作都能实现... 这次主要记录一下我对这款应用的逆向思路 apk检查 使用MT管理器检查apk的加壳情况 发现是某数字的免费版本 直接使用frida-dexdump 脱下来后备用 应用分…

基于springboot实现桥牌计分管理系统项目【项目源码】

基于springboot实现桥牌计分管理系统演示 JAVA简介 JavaScript是一种网络脚本语言&#xff0c;广泛运用于web应用开发&#xff0c;可以用来添加网页的格式动态效果&#xff0c;该语言不用进行预编译就直接运行&#xff0c;可以直接嵌入HTML语言中&#xff0c;写成js语言&#…

Lambertian模型(完美漫反射)

这里使用相乘的方式组合光照色和纹理色。根据这个模型,面朝光源的区域光照强度高,纹理色也相应增强。面背光源的区域光照弱,纹理色也被抑制。这样通过光照和纹理的结合,可以合成出具有照明效果的面部颜色,而不仅仅是固定的纹理本身的颜色。相乘方式可以近似实现不同光照方向下面…

“第六十六天”

这个我记得是有更优解的&#xff0c;不过还是明天发吧&#xff0c;明天想一想&#xff0c;看看能不能想起来 #include<string.h> int main() {char a[201] { 0 };char b[201] { 0 };scanf("%s %s", a, b);int na strlen(a);int nb strlen(b);int i 0, j …

Leetcode421. 数组中两个数的最大异或值

Every day a Leetcode 题目来源&#xff1a;421. 数组中两个数的最大异或值 解法1&#xff1a;贪心 位运算 初始化答案 ans 0。从最高位 high_bit 开始枚举 i&#xff0c;也就是 max⁡(nums) 的二进制长度减一。设 newAns ans 2i&#xff0c;看能否从数组 nums 中选两个…

基于SpringBoot+Vue的在线学习平台系统

基于SpringBootVue的在线学习平台系统的设计与实现~ 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringBootMyBatisVue工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 主页 用户界面 登录界面 管理员界面 摘要 本文设计并实现了一套基于Spri…

【MySQL】使用C/C++访问MySQL

文章目录 一. 环境准备1. 方法一2. 方法二 二. MySQL接口介绍1. 初始化/连接/关闭2. 执行操作3. 查找操作 结束语 本篇环境是云服务器Centos上的MySQL 版本; 一. 环境准备 使用C/C访问MySQL&#xff0c;首先需要MySQL的开发者库 这里提供两种方法&#xff1a; 1. 方法一 …

【Java 进阶篇】Java与JQuery:探秘事件绑定、入口函数与样式控制

在现代的Web开发中&#xff0c;Java和JQuery是两个不可或缺的角色。Java为我们提供了强大的后端支持&#xff0c;而JQuery则是前端开发的得力助手。本篇博客将围绕Java和JQuery&#xff0c;深入探讨事件绑定、入口函数和样式控制&#xff0c;带你进入前端开发的奇妙世界。 Jav…

音视频基础知识

图像&#xff08;YUV RGB&#xff09; ​​​​​​​​​​​​​​这个讲的比较好 RGB颜色编码 图像显示主要是由像素组成&#xff0c;每个像素点的颜色组成都是采用RGB格式&#xff0c;RGB就是红、绿、蓝&#xff0c;RGB分别取不同的值&#xff0c;展示不同的颜色。 YUV…

支持存档的书签服务LinkWarden

什么是 LinkWarden &#xff1f; Linkwarden 是一个自托管、开源协作书签管理器&#xff0c;用于收集、组织和存档网页。目标是将您在网络上找到的有用网页和文章组织到一个地方&#xff0c;并且由于有用的网页可能会消失&#xff08;参见链接失效的必然性&#xff09;&#xf…

网络原理-UDP/TCP详解

一. UDP协议 UDP协议端格式 由上图可以看出&#xff0c;一个UDP报文最大长度就是65535. • 16位长度&#xff0c;表示整个数据报&#xff08;UDP首部UDP数据&#xff09;的最大长度&#xff08;注意&#xff0c;这里的16位UDP长度只是一个标识这个数据报长度的字段&#xff0…

设计模式之十一:代理模式

代理可以控制和管理访问。 RMI提供了客户辅助对象和服务辅助对象&#xff0c;为客户辅助对象创建和服务对象相同的方法。RMI的好处在于你不必亲自写任何网络或I/O代码。客户程序调用远程方法就和运行在客户自己本地JVM对对象进行正常方法调用一样。 步骤一&#xff1a;制作远程…

【Redis系列】Redis的核心命令(上)

哈喽&#xff0c;大家好&#xff0c;我是小浪。那么上篇博客教会了大家如何在Linux上安装Redis&#xff0c;那么本篇博客就要正式开始学习Redis啦&#xff0c;跟着俺的随笔往下看~ 1、启动Redis 那么如何启动Redis呢&#xff1f;最常用的是以下这个命令&#xff1a; redis-cl…

Linux提取RPM包文件

在讲解如何从 RPM 包中提取文件之前&#xff0c;先来系统学习一下 cpio 命令。cpio 命令用于从归档包中存入和读取文件&#xff0c;换句话说&#xff0c;cpio 命令可以从归档包中提取文件&#xff08;或目录&#xff09;&#xff0c;也可以将文件&#xff08;或目录&#xff09…

Java基础知识第四讲:Java 基础 - 深入理解泛型机制

Java 基础 - 深入理解泛型机制 背景&#xff1a;Java泛型这个特性是从JDK 1.5才开始加入的&#xff0c;为了兼容之前的版本&#xff0c;Java泛型的实现采取了“伪泛型”的策略&#xff0c;即Java在语法上支持泛型&#xff0c;但是在编译阶段会进行所谓的“类型擦除”&#xff0…

基于springboot的在线文档管理系统

基于springboot的在线文档管理系统 摘要 基于Spring Boot的在线文档管理系统是一种通过使用Spring Boot框架构建的现代化应用程序&#xff0c;旨在有效地组织、存储和分享文档内容。该系统通过利用Spring Boot的快速开发和简化配置的优势&#xff0c;提供了一个稳健的基础架构&…