【问题标题】:iOS/Metal: how to read from the depth buffer at a point?iOS/Metal:如何从深度缓冲区中读取某个点?
【发布时间】:2015-02-10 05:40:06
【问题描述】:

我想从深度缓冲区中读取数据。在 OS X 上的 GL 中,我可以这样做:

float depth[2][2]; // get 2x2 for bilinear interpolation
glReadPixels(s.x, s.y, /*width*/2, /*height*/2, GL_DEPTH_COMPONENT, GL_FLOAT, depth);

(请注意,使用 iOS 上的 OpenGL ES,您无法从深度缓冲区中读取数据)

Metal 的等价物是什么?

看来我需要这样做:

_renderPassDescriptor.depthAttachment.storeAction = MTLStoreActionStore;

然后以某种方式通过 CPU 从缓冲区中读取?

虽然也许有更好的方法,因为我只需要一个点(触摸点)。片段着色器是否可以仅存储该点的深度(或 2x2 用于双线性插值),从而允许我将 storeAction 保留为 MTLStoreActionDontCare?

【问题讨论】:

    标签: ios opengl-es metal


    【解决方案1】:

    我将深度存储操作设置为MTLStoreActionStore,然后在渲染方法中做了以下操作:

    [commandBuffer addCompletedHandler:^(id<MTLCommandBuffer> buffer) {
    
        // We're done! So read from the depth texture.        
    
        // Just read the center pixel for now.
        MTLRegion region = MTLRegionMake2D(_depthTex.width/2, _depthTex.height/2, 1, 1);
    
        float depth;
        [_depthTex getBytes:&depth bytesPerRow:_depthTex.width*4 fromRegion:region mipmapLevel:0];
    
        NSLog(@"read depth: %f", depth);
    
        dispatch_semaphore_signal(block_sema);
    
    }];
    

    这很有效,并且在论坛上被一位 Apple 开发人员确认为“正确的做法”。

    请注意,使用 iOS 上的 OpenGL ES 无法读取深度缓冲区。金属FTW!

    【讨论】:

    • 我不相信你可以再使用 getBytes: 了。来自 Apple 的开发者网站:apple.co/1IG3jpw“具有深度、模板或深度/模板像素格式的纹理只能使用私有存储模式分配。要加载或保存这些纹理的内容,您必须执行 blit 操作。”
    • @datboi 很有趣。我将重新审视这个,我会更新代码。
    • 对不起,一个完整的解释:如果你在 iOS 上,纹理默认为 MTLStorageModeShared,它不需要通过 blit 命令编码器进行同步。然而,深度和模板纹理是一个例外,必须使用 MTLStorageModePrivate 进行分配。由于此存储模式要求,您唯一的选择是从该私有深度/模板纹理(在“VRAM”中)到 CPU 可访问内存,因为“具有私有存储模式的纹理不支持此 (getBytes) 方法”。 -苹果,apple.co/1OGM7h7
    猜你喜欢
    • 2011-11-11
    • 2013-08-03
    • 2015-06-12
    • 2020-07-13
    • 2011-09-27
    • 1970-01-01
    • 1970-01-01
    • 2011-02-05
    • 2018-06-19
    相关资源
    最近更新 更多