UE中通过深度缓冲重建世界空间坐标原理和Unity shader重建原理基本一致,但是UE中重建世界坐标的实现路径与Unity是不一致的 :

        • Unity中使用 SAMPLE_DEPTH_TEXTUR 采样的是原始深度值(RawDepth),是一个范围[0,1]的非线性深度值;UE中 SceneDepth 节点获取的是真实距离的线性深度(Linearepth),单位是厘米。

        • Unity和UE的坐标系不同,Unity是左手坐标系,Y轴向上 (Y-Up),Z轴向前;UE是左手坐标系,Z轴向上 (Z-Up),X轴向前。这意味着Unity和UE的矩阵内容不同,Unity 的逆矩阵和 UE 的逆矩阵,里面的 16 个数字是不一样的;Clip Space 方向不同,Unity 的 UV 原点通常在左下角 (OpenGL) 或左上角 (DX),UE 的 UV 原点在左上角。这会导致 Y 轴方向可能需要 1 - y 反转。

        • Unity和UE的单位不一致,Unity的世界单位是米,UE的世界单位是厘米,因此按照Unity的路径重建出来是 (0, 1, 0),在 UE 里重建出来则是 (0, 0, 100)。如果不缩放,特效大小会差 100 倍

        因此在UE中通过深度缓冲重建世界坐标,建议使用射线法:

1. 射线法

        原理公式:P´ = C + ->v * Depth / ->v * ->f   

        如图所示,P 是像素的屏幕空间位置(ScreenPosition),P´ 是像素的世界空间位置(WorldPosition);C 是相机的世界空间位置(CameraPosition);->v 是相机指向像素 P 视线的向量(CameraVector),->f 是相机朝向向量(CameraDirrction);Depth 是像素 P 的深度值。由向量 ->v 点乘向量 ->f 可得向量 ->v 、->f 的夹角 θ 的余弦值 cosθ ,Depth / cosθ 获取 CP´ 长度。向量 ->v * 距离 CP´ 获得向量 ->CP´,向量 ->CP´ 只表示 P´ 到相机 C 的相对距离,要获取 P´ 在世界空间中的绝对位置,还需要加上相机 C 的世界空间坐标,即可确定像素 P 在世界空间中的位置 P´ 。公式如下:

        UE节点连线图:

2. 逆矩阵重建

        UE中通过逆矩阵重建世界坐标,基本逻辑和Unity一致,由裁剪空间逆矩阵反推至世界空间,但在具体执行层面与Unity不一样

2.1 实现方法

        UE中没有提供逆矩阵相关节点,因此需要使用CustomNode输入代码实现逆矩阵

//1.采样:获取纹理坐标,自动适配动态分辨率 (Screen Percentage)
//GetSceneTextureUV 为UE内置函数,用于采样屏幕空间UV坐标
float2 ScreenUV = GetSceneTextureUV(Parameters);

//获取 DeviceZ (采样0 ~ 1 的非线性深度)
float deviceZ = LookupDeviceZ(ScreenUV);


//2.几何重建
//获取NDC空间坐标,GetScreenPosition UE内置函数,直接获取NDC空间坐标
float2 ndcPos = GetScreenPosition(Parameters).xy;

//通过NDC坐标构建裁剪空间齐次坐标
float4 ClipPos = float4(ndcPos, deviceZ, 1.0);

//3.空间变换(Transform)
//逆投影矩阵,由裁剪空间齐次坐标转为平移世界空间坐标
float4 TranslatedWorldPosH = mul(ClipPos, ResolvedView.ClipToTranslatedWorld);

//透视除法(归一化),还原为平移世界空间笛卡尔2坐标
TranslatedWorldPos = TranslatedWorldPosH / TranslatedWorldPosH.w;

//4.LWC还原(LWC Restore)
//获取平移世界坐标偏移量
float3 PreViewTranslation = LWCToFloat(ResolvedView.PreViewTranslation);
//还原绝对世界坐标
float3 WorldPos = TranslatedPos.xyz - PreViewTranslation;

return WorldPos;

2.2 平移世界空间 (Translated World Space)

        平移世界空间 (Translated World Space) 是 Unreal Engine (UE) 渲染管线中一个非常独特且核心的概念。它是 “以相机为原点,但坐标轴方向与世界保持一致” 的坐标系。        

        在计算机图形学中,GPU处理顶点和像素位置时,通常使用32位浮点数 (Float32)。Float32有一个致命弱点:数值越大,精度越低。如一个超大开放世界游戏中,玩家走到地图边缘(比如坐标1000000, 1000000),此时如果直接使用绝对世界坐标进行渲染计算:模型会开始疯狂抖动(顶点乱跳)、阴影会变成锯齿状或消失、物理计算会崩溃。为了解决这个问题,UE采用了一个聪明的策略:既然GPU处理大数值精度低,那我就强行让所有计算都发生在原点 (0,0,0) 附近。

        • 绝对世界空间:世界原点固定不动;相机可能飞到十万八千里外;精度风险:高

        • 平移世界空间:强行把世界原点移动到相机所在的位置,在渲染每一帧时,引擎会计算一个偏移量 PreViewTranslation(大约等于 - CameraPosition),所有的物体坐标,都加上这个偏移量,无论玩家走到地图哪里,在GPU看来,相机永远在 (0,0,0) 附近,所有要渲染的物体也都在相机附近。数值永远很小,精度永远完美。

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐