如何根据金属视口清除颜色?

How to clear color according to viewport on Metal?

假设有一个 200 x 200 颜色的可绘制对象。我想清除屏幕的区域(0,0,100,100)以显示红色。代码如下:

- (void)drawInMTKView:(nonnull MTKView *)view
{
    // Create a new command buffer for each render pass to the current drawable.
    id<MTLCommandBuffer> commandBuffer = [_commandQueue commandBuffer];
    commandBuffer.label = @"MyCommand";

    // Obtain a renderPassDescriptor generated from the view's drawable textures.
    MTLRenderPassDescriptor *renderPassDescriptor = view.currentRenderPassDescriptor;
    renderPassDescriptor.colorAttachments[0].loadAction = MTLLoadActionClear;
    renderPassDescriptor.colorAttachments[0].storeAction = MTLStoreActionStore;
    renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(1.0, 0.0, 0.0, 1.0);
    
    if(renderPassDescriptor != nil)
    {
        // Create a render command encoder.
        id<MTLRenderCommandEncoder> renderEncoder =
        [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor];
        renderEncoder.label = @"MyRenderEncoder";

        // Set the region of the drawable to half.
        NSUInteger renderAreaWidth = _drawableSize.x/2;
        NSUInteger renderAreaHeight = _drawableSize.y/2;
        [renderEncoder setViewport:(MTLViewport){0, 0, renderAreaWidth, renderAreaHeight}];
        [renderEncoder setScissorRect:(MTLScissorRect){0, 0, renderAreaWidth, renderAreaHeight}];
        
        [renderEncoder endEncoding];
 
        // Schedule a present once the framebuffer is complete using the current drawable.
        [commandBuffer presentDrawable:view.currentDrawable];
    }

    // Finalize rendering here & push the command buffer to the GPU.
    [commandBuffer commit];
}

预期的结果应该是drawable 的左上部分清晰为红色,其余部分为黑色。
但是我发现整个drawable都是透明的红色。
怎么可能呢?我该如何解决?

正如您所确定的,Metal 不会将视口和剪刀应用到 renderpass 加载操作清除。

您必须手动清除子区域:

  • 如果您已经在渲染通道中,则可以渲染适当的剪辑 -space 四边形。
  • 如果渲染通道尚未启动,您可以选择使用计算通道,这可能会更快。
  • 如果 renderpass 还没有开始,并且要清除的区域具有一致的大小(即 - 你总是逐帧清除相同的区域),你可以填充一个单独的纹理或缓冲区,并将其 BLIT 到目标区域。这可能是最有效的选择。