【发布时间】:2021-03-21 18:58:46
【问题描述】:
我有一个金属着色器(为 ARKit 应用程序编写为 SCNProgram),它获取从 smoothedSceneDepth 捕获的当前场景的深度图。我想使用捕获的深度信息来丢弃位于真实世界对象后面的任何虚拟对象的部分。但是,我无法在我的着色器中获得预期的片段深度。
这是我的基本片段着色器:
struct ColorInOut {
float4 position [[ position ]];
float2 depthTexCoords;
};
fragment float4 fragmentShader(
const ColorInOut in [[ stage_in ]],
depth2d<float, access::sample> sceneDepthTexture [[ texture(1) ]]
) {
constexpr sampler textureSampler(mag_filter::linear, min_filter::linear);
// Closest = 0.0m, farthest = 5.0m (lidar max)
// Seems to be in meters?
const float lidarDepth = sceneDepthTexture.sample(textureSampler, in.depthTexCoords);
float fragDepth = // ??? somehow get z distance to the current fragment in meters ???
// Compare the distances
const float zMargin = 0.1
if (lidarDepth < fragDepth - zMargin) {
discard_fragement()
}
...
}
我的理解是片段着色器中的position.z 应该在最接近=0 到最远=1 的范围内。但是,当我尝试使用当前的相机平面将其转换回现实世界的距离时,结果似乎不对:
const float zNear = 0.001;
const float zFar = 1000;
float fragDepth = in.position.z * (zFar - zNear);
当我使用return float4(fragDepth, 0, 0, 1); 调试着色器时,红色在我最接近对象时最亮,然后在我后退时消失。即使我使用fragDepth = 1 - fragDepth,深度似乎也与lidarDepth不同。
这里使用1 - fragDepth:
(我也尝试使用来自 this answer 的映射,但无法正常工作)
所以我的问题是:
-
in.position.z在什么坐标系中? -
如何将
in.position.z转换为一个深度值,以便与我已经拥有的捕获的深度信息进行比较? (反之亦然)
【问题讨论】:
-
« 即使我使用
fragDepth = 1 - fragDepth,深度似乎与lidarDepth不同 » 它们有多大不同?你有截图吗?你试过用SCNSceneBuffer的inverseProjectionTransform吗? -
有一个相当硬的边缘,深度从全黑到中间红色。我已经添加了这个截图。如果
fragDepth以米为单位,这应该更加渐进。核心问题是我不知道in.position.z在哪个坐标空间中,因为我根本不希望1 - fragDepth是必需的