writing to a depth target not working when using SCNTechnique with a metal shader

103 Views Asked by At

I have a SCNTechnique with multiple render passes setup. In one of those passes, I am sampling the depth of the lidar camera and want to write that to a target for use in a different render pass. It works fine if I write to a color target. As soon as I change the target to a depth target, the target is full of 0's and nothing I do affects it. Here is my fragment shader:

fragment float depth_fragment(depth_out_vertex_t vert [[stage_in]],
                              depth2d<float, access::sample> depthSampler [[texture(0)]])
{
    float depth = depthSampler.sample(s, vert.uv);
    return depth;
};

and my .plist entry:

<key>draw_depth</key>
<dict>
    <key>draw</key>
    <string>DRAW_QUAD</string>
    <key>program</key>
    <string>doesntexist</string>
    <key>metalVertexShader</key>
    <string>depth_vertex</string>
    <key>metalFragmentShader</key>
    <string>depth_fragment</string>
    <key>inputs</key>
    <dict>
        <key>depthSampler</key>
        <string>depthSymbol</string>
    </dict>
    <key>outputs</key>
    <dict>
        <key>depth</key>
        <string>depth_scene</string>
    </dict>
</dict>
...
<key>targets</key>
<dict>
    <key>depth_scene</key>
    <dict>
        <key>type</key>
        <string>depth</string>
    </dict>
</dict>

I'm accessing it like this:

fragment half4 depth_fragment(out_vertex_t vert [[stage_in]],
                              depth2d<float, access::sample> cameraDepthSampler [[texture(0)]]) {
    float camDepth = cameraDepthSampler.sample(s, vert.uv);
    return half4(half3(camDepth), 1);
}

Any idea what I might be doing wrong? I've never been able to get writing to a depth target from a fragment shader to work in any form. It only works if I don't use a metal shader (just a draw pass). And in case you're wondering, I'm rendering the depthSymbol using a metal shader to perform some necessary transformations on the input before it's usable. depthSymbol comes from the raw depth image from the lidar camera. Alternately, is there a way to change the color target to not clamp the output values to the range 0...1? That's the issue I'm running into using the color target.

1

There are 1 best solutions below

0
On

I was able to solve this problem by following the guide in this forum post. The key insight: the key in "inputs" needs to match the variable name in Metal.

fragment half4 depth_fragment(out_vertex_t vert [[stage_in]],
                              depth2d<float, access::sample> cameraDepthSampler [[texture(0)]]) {
    float camDepth = cameraDepthSampler.sample(s, vert.uv);
    return half4(half3(camDepth), 1);
}

Based on this shader, we need the dictionary to specify "cameraDepthSampler" as the input name:

<key>draw_depth</key>
<dict>
    <key>draw</key>
    <string>DRAW_QUAD</string>
    <key>program</key>
    <string>doesntexist</string>
    <key>metalVertexShader</key>
    <string>depth_vertex</string>
    <key>metalFragmentShader</key>
    <string>depth_fragment</string>
    <key>inputs</key>
    <dict>
        <key>cameraDepthSampler</key>
        <string>depthSymbol</string>
    </dict>
    <key>outputs</key>
    <dict>
        <key>depth</key>
        <string>depth_scene</string>
    </dict>
</dict>
...
<key>targets</key>
<dict>
    <key>depth_scene</key>
    <dict>
        <key>type</key>
        <string>depth</string>
    </dict>
</dict>