我自己的 Shader 与 Apple 的 Metal 样本的离屏渲染不起作用

Offscreen rendering of my own Shader with Apple's Metal sample doesn't work

Apple 示例程序

https://developer.apple.com/documentation/metal/customizing_render_pass_setup

我正在考虑制作 Swift 并使用我自己的 Shader 进行离屏渲染。 Swift 转换本身没有问题。 当我在那里写了下面的单色Shader时,我能够毫无问题地将它输出到屏幕上。

fragment float4 simpleFragmentShader(VertexOut vertexIn [[stage_in]] {
    return float4(1.0, 0.0, 0.0, 1.0);
}

但是,如果使用下面的Shade,屏幕会立即变黑,无法正常输出。 这个着色器与普通的 Metal 代码一起工作很好,但它在上面的示例环境中不起作用。 在上面的示例代码中使用这样一个Shader时,是否可以在不更改示例代码或在Shader的某个地方使用它?

vertex VertexOut simpleVertexShader(constant float4 *positions [[buffer(0)]],
 uint vid [[ vertex_id ]]) {
    
    VertexOut out;
    
    out.pos = positions[vid];
    
    return out;
}


fragment float4 simpleFragmentShader(VertexOut vertexIn [[stage_in]],
                                     constant float2 &resolution [[buffer(0)]]) {

    float2 resolution0 = float2(resolution[0], resolution[1]);
    float2 p = (vertexIn.pos.xy * 2.0 - resolution0) / min(resolution0.x, resolution0.y);

    return float4(p, 0.0, 1.0);
    
}

图片是为了成功。

分辨率等基本描述没有问题

renderEncoder.setFragmentBuffer(resolutionBuffer, offset: 0, index: 0)

添加最终渲染的Shader。

vertex VertexTextureOut textureVertexShader(constant float4 *positions [[buffer(0)]],
                                            constant float2 *texcoord [[buffer(1)]],
                                            uint vid [[ vertex_id ]]) {
    
    VertexTextureOut out;
    
    out.pos = positions[vid];
    out.texcoord = texcoord[vid];
    
    return out;
}

fragment float4 textureFragmentShader(VertexTextureOut vertexIn [[stage_in]],
                                     texture2d<float> renderTargetTexture [[texture(0)]]) {
    
    constexpr sampler simpleSampler;

    // Sample data from the texture.
    float4 colorSample = renderTargetTexture.sample(simpleSampler, vertexIn.texcoord);

    // Return the color sample as the final color.
    return colorSample;
}

问题是 'in.texcoord.xy' 已经在使用归一化坐标,因此它们已经在 0.0-1.0

的范围内

这个有效:

float2 p = (in.texcoord.xy) ;
return float4(p, 0.0, 1.0);

更新: 使用您的示例项目和:

float2 p = (vertexIn.pos.xy) / min(resolution0.x, resolution0.y);
return float4(p, 0.0, 1.0);

我得到这些似乎正确的结果:

更新二: 示例项目 2 对我来说崩溃了。我不得不注释掉这两行(Renderer.swift:

的第 63 行和第 65 行
//textureDescriptor.textureType = .type2DMultisample
//textureDescriptor.sampleCount = 4

这让我出现了部分黑屏。接下来我将 Shaders.metal 的第 29 行更改为:

float2 p = (vertexIn.pos.xy) / min(resolution0.x, resolution0.y);

这给了我预期的结果: