LWC渲染概述
本次引入了全新的HLSL类型与大型世界坐标,可以在 LargeWorldCoordinates.ush
文件中找到。
HLSL类型 | 说明 |
---|---|
FLWCScalar FLWCVector2/3/4 | 这些类型类似float1/2/3/4,但是它们包含额外的图块(Tile)坐标。因此,FLWCVector2由float2图块和float2偏移组成。表示的值由以下公式计算:图块 * TileSize + 偏移,其中TileSize表示一个常量值,定义为256k。 |
FLWCMatrix FLWCInverseMatrix | 这些类型类似于float4x4,但是,它们都包含一个额外的float3图块坐标。 |
FLWCMatrix | 乘以矩阵后,将图块坐标添加到结果中。 |
FLWCInverseMatrix | 乘以矩阵前,添加图块坐标。 |
FLWCMatrix | 用于变换到世界空间(LocalToWorld)。 |
FLWCInverseMatrix | 用于从世界空间变换(WorldToLocal)。 |
你可以对这些类型执行 LWCAdd
或 LWCRsqrt
等操作。采用LWC输入值的操作将返回LWC输出(LWCAdd
),而其他操作则返回常规浮点输出(LWCRsqrt
)。你选择的实现方案导致了这种区别,但是使坐标变得更小的操作可以让你返回到常规浮点。
在着色器代码中,许多类型已切换为LWC变体。以下是一些值得注意的示例:
- 大致来说,LWC类型未直接包含在统一缓冲区中。 实体包含多条数据,它们都可以使用相同的图块坐标(WorldToLocal、LocalToWorld、AbsoluteWorldPosition)。因此,典型模式是将常规的非LWC值与单个float3 TilePosition值一起存储在统一缓冲区(RelativeWorldToLocal、LocalToRelativeWorld、RelativeWorldPosition)中。
在着色器内部,此统一数据"解压"到一个新的结构体类型中,其中包括实际的LWC值,里面许多值使用单个TilePosition进行初始化。
-
SceneData.ush、FPrimitiveSceneData 和 FInstanceSceneData 具有各种更新的矩阵和位置向量。
-
全局摄像机统一数据有各种矩阵和偏移变化(例如PreViewTranslation。) 此前,全局摄像机统一数据要么在渲染网格体(处理实例化立体渲染)时通过ResolvedView访问,要么在渲染后期处理和其他全局通道时通过View访问。
在以前的引擎版本中,View会直接引用全局统一缓冲区,因此我们添加了新别名 PrimaryView
,它将引用解压缩的全局视图结构体。因此,View.PreViewTranslation
名称更改为了 PrimaryView.PreViewTranslation
。ResolvedView.PreViewTranslation
会在适用的情况下继续起作用,并且对于从常规View别名访问非LWC量有效。
-
FNaniteView现在匹配摄像机统一数据的更新。
-
光源位置和反射捕获位置已切换到新的LWC HLSL类型。
切换这些全局类型将提供一般指示,来表明你的着色器代码需要重构哪些地方才能支持LWC。 例如:
float3 WorldPosition = mul(Input.LocalPosition, View.LocalToWorld);
//这将不再编译,需要重构为:
FLWCVector3 WorldPosition = LWCMultiply(Input.LocalPosition, PrimaryView.LocalToWorld);
初始LWC通道不会执行检查来确保所有着色器都能配合LWC正常运行。
为了适应它们,你可以使用全局函数 LWCHackToFloat
将LWC类型转换为非LWC类型。
LWCBackToFloat
充当 LWCToFloat
函数的包装器。它们之间的区别是,当你知道LWC场景比例可以安全地进行转换时,应使用 LWCToFloat
函数。 LWCHackToFloat
是可搜索标识。如果你没有时间重构代码库来将 WorldPosition
从 float3
切换到 FLWCVector3
,你可以改用以下代码:
float3 WorldPosition = mul(Input.LocalPosition, LWCHackToFloat(PrimaryView.LocalToWorld));
TranslatedWorldSpace是UE5着色器中使用的现有引擎概念。此前,它旨在通过相对于摄像机原点运行来提高精度。但是,此行为对LWC很有用,因为在TranslatedWorldSpace中运行时,可以使用浮点数。你可以使用以下公式,而不是将WorldPosition转换为LWC值:
float3 TranslatedWorldPosition = mul(Input.LocalPosition, PrimaryView.LocalToTranslatedWorld);
快速移植指南
你可以将现有的HLSL代码库移植到虚幻引擎5。以下是一些确保成功转换的建议。
-
访问世界空间(LocalToWorld、PreViewTranslation)中的值/矩阵时,将
View
更改为PrimaryView
。 -
如果你在世界空间中执行的代码无法编译(如果它缺少函数重载或类型转换),并且你没有资源重构你的代码库,你可以在需要时使用
LWCHackToFloat
函数,例如:(LWCHackToFloat(PrimaryView.PreViewTranslation))
如果你的代码仍然无法编译:
-
考虑将着色器代码更改为在TranslatedWorldSpace而不是WorldSpace中运行。
-
世界空间值需要LWC类型(FLWCVector3,而不是float3)。你可能需要使用
LWCAdd
和LWCMin
函数。
你开发的所有新代码都应遵循上面列出的指南,尽可能使用TranslatedWorldSpace,其他情况我们建议你使用LWC类型。
材质转换器
材质转换器(Material Translator) 已更新为使用LWC值。 查询AbsoluteWorldPosition并将其转换为WorldSpace时,材质节点将输出LWC值,而不是浮点。
材质将在LWC场景比例生效,但是,这可能会产生性能开销。 由于LWC操作会增加更多流程调用,因此你移植的材质可能会增加开销。